| Anonymous | Login | Signup for a new account | 2013-05-25 06:55 CEST | ![]() |
| Main | My View | View Issues | Change Log | Roadmap | Repositories |
| View Issue Details [ Jump to Notes ] | [ Issue History ] [ Print ] | ||||||||
| ID | Project | Category | View Status | Date Submitted | Last Update | ||||
| 0002393 | Spring engine | General | public | 2011-04-01 00:20 | 2011-05-31 23:47 | ||||
| Reporter | abma | ||||||||
| Assigned To | abma | ||||||||
| Priority | normal | Severity | crash | Reproducibility | always | ||||
| Status | resolved | Resolution | fixed | ||||||
| Product Version | 0.82.3+git | ||||||||
| Target Version | Fixed in Version | ||||||||
| Summary | 0002393: (master) crash with "Red Build/Order Menu" and >300 Units when pressing CTRL+A (Out of Memory) | ||||||||
| Description | i didn't test a long time, so this crashes maybe have nothing to do with assimp crashes sometimes with the /cheat /give all /give all 1 "test" | ||||||||
| Additional Information | http://pastebin.com/sfQKiMMM [^] git describe 0.82.3-1685-gda562a5 | ||||||||
| Tags | No tags attached. | ||||||||
| Attached Files | diff --git a/rts/Game/Camera.cpp b/rts/Game/Camera.cpp
index 3a13aae..aec1220 100644
--- a/rts/Game/Camera.cpp
+++ b/rts/Game/Camera.cpp
@@ -132,9 +132,8 @@ void CCamera::Update(bool freeze, bool resetUp)
const float gndHeight = ground->GetHeightAboveWater(pos.x, pos.z);
const float rangemod = 1.0f + std::max(0.0f, pos.y - gndHeight - 500.0f) * 0.0003f;
- const float zNear = (CGlobalRendering::NEAR_PLANE * rangemod);
-
- globalRendering->viewRange = CGlobalRendering::MAX_VIEW_RANGE * rangemod;
+ const float zNear = (NEAR_PLANE * rangemod);
+ globalRendering->viewRange = MAX_VIEW_RANGE * rangemod;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
diff --git a/rts/Game/Game.cpp b/rts/Game/Game.cpp
index 4e046dc..85ea86f 100644
--- a/rts/Game/Game.cpp
+++ b/rts/Game/Game.cpp
@@ -217,6 +217,7 @@ CR_REG_METADATA(CGame,(
CGame::CGame(const std::string& mapname, const std::string& modName, ILoadSaveHandler* saveFile) :
+ finishedLoading(false),
gameDrawMode(gameNotDrawing),
defsParser(NULL),
fps(0),
@@ -230,7 +231,6 @@ CGame::CGame(const std::string& mapname, const std::string& modName, ILoadSaveHa
gameOver(false),
noSpectatorChat(false),
- finishedLoading(false),
infoConsole(NULL),
consoleHistory(NULL),
@@ -708,23 +708,20 @@ void CGame::ResizeEvent()
}
-int CGame::KeyPressed(unsigned short key, bool isRepeat)
+int CGame::KeyPressed(unsigned short k, bool isRepeat)
{
if (!gameOver && !isRepeat) {
playerHandler->Player(gu->myPlayerNum)->currentStats.keyPresses++;
}
- // Get the list of possible key actions
- const CKeySet ks(key, false);
- const CKeyBindings::ActionList& actionList = keyBindings->GetActionList(ks);
-
if (!hotBinding.empty()) {
- if (key == SDLK_ESCAPE) {
+ if (k == SDLK_ESCAPE) {
hotBinding.clear();
}
- else if (!keyCodes->IsModifier(key) && (key != keyBindings->GetFakeMetaKey())) {
+ else if (!keyCodes->IsModifier(k) && (k != keyBindings->GetFakeMetaKey())) {
+ CKeySet ks(k, false);
string cmd = "bind";
- cmd += " " + ks.GetString(false);
+ cmd += " " + ks.GetString(false) ;
cmd += " " + hotBinding;
keyBindings->Command(cmd);
hotBinding.clear();
@@ -733,15 +730,173 @@ int CGame::KeyPressed(unsigned short key, bool isRepeat)
return 0;
}
+ // Get the list of possible key actions
+ CKeySet ks(k, false);
+ const CKeyBindings::ActionList& actionList = keyBindings->GetActionList(ks);
+
if (userWriting) {
- for (unsigned int actionIndex = 0; actionIndex < actionList.size(); actionIndex++) {
- if (ProcessKeyPressAction(key, actionList[actionIndex])) {
- // the key was used, ignore it (ex: alt+a)
- ignoreNextChar = (actionIndex < (actionList.size() - 1));
+ unsigned int actionIndex;
+ for (actionIndex = 0; actionIndex < actionList.size(); actionIndex++) {
+ const Action& action = actionList[actionIndex];
+
+ if (action.command == "edit_return") {
+ userWriting=false;
+ writingPos = 0;
+
+ if (k == SDLK_RETURN) {
+ keyInput->SetKeyState(k, 0); //prevent game start when server chats
+ }
+ if (chatting) {
+ string command;
+ if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
+ command = userInput.substr(2);
+ } else {
+ command = userInput;
+ }
+ if ((command[0] == '/') && (command[1] != '/')) {
+ // execute an action
+ consoleHistory->AddLine(command);
+ const string actionLine = command.substr(1); // strip the '/'
+ chatting = false;
+ userInput = "";
+ writingPos = 0;
+ logOutput.Print(command);
+ CKeySet ks(k, false);
+ Action fakeAction(actionLine);
+ ActionPressed(fakeAction, ks, isRepeat);
+ }
+ }
+ break;
+ }
+ else if ((action.command == "edit_escape") &&
+ (chatting || inMapDrawer->wantLabel)) {
+ if (chatting) {
+ consoleHistory->AddLine(userInput);
+ }
+ userWriting=false;
+ chatting=false;
+ inMapDrawer->wantLabel=false;
+ userInput="";
+ writingPos = 0;
+ break;
+ }
+ else if (action.command == "edit_complete") {
+ string head = userInput.substr(0, writingPos);
+ string tail = userInput.substr(writingPos);
+ const vector<string> &partials = wordCompletion->Complete(head);
+ userInput = head + tail;
+ writingPos = (int)head.length();
+ if (!partials.empty()) {
+ string msg;
+ for (unsigned int i = 0; i < partials.size(); i++) {
+ msg += " ";
+ msg += partials[i];
+ }
+ logOutput.Print(msg);
+ }
+ break;
+ }
+ else if (action.command == "chatswitchall") {
+ if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
+ userInput = userInput.substr(2);
+ writingPos = std::max(0, writingPos - 2);
+ }
+ userInputPrefix = "";
+ break;
+ }
+ else if (action.command == "chatswitchally") {
+ if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
+ userInput[0] = 'a';
+ } else {
+ userInput = "a:" + userInput;
+ writingPos += 2;
+ }
+ userInputPrefix = "a:";
+ break;
+ }
+ else if (action.command == "chatswitchspec") {
+ if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
+ userInput[0] = 's';
+ } else {
+ userInput = "s:" + userInput;
+ writingPos += 2;
+ }
+ userInputPrefix = "s:";
+ break;
+ }
+ else if (action.command == "pastetext") {
+ if (!action.extra.empty()) {
+ userInput.insert(writingPos, action.extra);
+ writingPos += action.extra.length();
+ } else {
+ PasteClipboard();
+ }
+ break;
+ }
+
+ else if (action.command == "edit_backspace") {
+ if (!userInput.empty() && (writingPos > 0)) {
+ userInput.erase(writingPos - 1, 1);
+ writingPos--;
+ }
+ break;
+ }
+ else if (action.command == "edit_delete") {
+ if (!userInput.empty() && (writingPos < (int)userInput.size())) {
+ userInput.erase(writingPos, 1);
+ }
+ break;
+ }
+ else if (action.command == "edit_home") {
+ writingPos = 0;
+ break;
+ }
+ else if (action.command == "edit_end") {
+ writingPos = (int)userInput.length();
+ break;
+ }
+ else if (action.command == "edit_prev_char") {
+ writingPos = std::max(0, std::min((int)userInput.length(), writingPos - 1));
+ break;
+ }
+ else if (action.command == "edit_next_char") {
+ writingPos = std::max(0, std::min((int)userInput.length(), writingPos + 1));
+ break;
+ }
+ else if (action.command == "edit_prev_word") {
+ // prev word
+ const char* s = userInput.c_str();
+ int p = writingPos;
+ while ((p > 0) && !isalnum(s[p - 1])) { p--; }
+ while ((p > 0) && isalnum(s[p - 1])) { p--; }
+ writingPos = p;
+ break;
+ }
+ else if (action.command == "edit_next_word") {
+ const int len = (int)userInput.length();
+ const char* s = userInput.c_str();
+ int p = writingPos;
+ while ((p < len) && !isalnum(s[p])) { p++; }
+ while ((p < len) && isalnum(s[p])) { p++; }
+ writingPos = p;
+ break;
+ }
+ else if ((action.command == "edit_prev_line") && chatting) {
+ userInput = consoleHistory->PrevLine(userInput);
+ writingPos = (int)userInput.length();
+ break;
+ }
+ else if ((action.command == "edit_next_line") && chatting) {
+ userInput = consoleHistory->NextLine(userInput);
+ writingPos = (int)userInput.length();
break;
}
}
+ if (actionIndex != actionList.size()) {
+ ignoreNextChar = true; // the key was used, ignore it (ex: alt+a)
+ }
+
return 0;
}
@@ -749,15 +904,15 @@ int CGame::KeyPressed(unsigned short key, bool isRepeat)
std::deque<CInputReceiver*>& inputReceivers = GetInputReceivers();
std::deque<CInputReceiver*>::iterator ri;
for (ri = inputReceivers.begin(); ri != inputReceivers.end(); ++ri) {
- CInputReceiver* recv = *ri;
- if (recv && recv->KeyPressed(key, isRepeat)) {
+ CInputReceiver* recv=*ri;
+ if (recv && recv->KeyPressed(k, isRepeat)) {
return 0;
}
}
// try our list of actions
- for (unsigned int i = 0; i < actionList.size(); ++i) {
- if (ActionPressed(key, actionList[i], isRepeat)) {
+ for (int i = 0; i < (int)actionList.size(); ++i) {
+ if (ActionPressed(actionList[i], ks, isRepeat)) {
return 0;
}
}
@@ -1609,12 +1764,9 @@ void CGame::SimFrame() {
m_validateAllAllocUnits();
#endif
- // Important: gs->frameNum must be updated *before* GameFrame is called,
- // or any call-outs called by Lua will see a stale gs->frameNum.
- // (e.g. effective TTL of CEGs emitted in GameFrame will be reduced...)
- // It must still be passed the old frameNum because Lua may depend on it.
- // (e.g. initialization in frame 0...)
- eventHandler.GameFrame(gs->frameNum++);
+ eventHandler.GameFrame(gs->frameNum);
+
+ gs->frameNum++;
if (!skipping) {
infoConsole->Update();
diff --git a/rts/Game/Game.h b/rts/Game/Game.h
index bfcb914..5837b90 100644
--- a/rts/Game/Game.h
+++ b/rts/Game/Game.h
@@ -47,7 +47,6 @@ private:
public:
CGame(const std::string& mapname, const std::string& modName, ILoadSaveHandler* saveFile);
- virtual ~CGame();
bool Draw();
bool DrawMT();
@@ -57,22 +56,20 @@ public:
/// Called when a key is released by the user
int KeyReleased(unsigned short k);
/// Called when the key is pressed by the user (can be called several times due to key repeat)
- int KeyPressed(unsigned short k, bool isRepeat);
+ int KeyPressed(unsigned short k,bool isRepeat);
void ResizeEvent();
+ virtual ~CGame();
-
- bool ProcessCommandText(unsigned int key, const std::string& command);
- bool ProcessKeyPressAction(unsigned int key, const Action& action);
-
- bool ActionPressed(unsigned int key, const Action&, bool isRepeat);
+ bool ActionPressed(const Action&, const CKeySet& ks, bool isRepeat);
bool ActionReleased(const Action&);
-
+
bool HasLag() const;
+ volatile bool finishedLoading;
+
/// show GameEnd-window, calculate mouse movement etc.
void GameEnd(const std::vector<unsigned char>& winningAllyTeams);
-
enum GameDrawMode {
gameNotDrawing = 0,
gameNormalDraw = 1,
@@ -120,7 +117,6 @@ public:
bool showMTInfo;
/// Prevents spectator msgs from being seen by players
bool noSpectatorChat;
- volatile bool finishedLoading;
unsigned char gameID[16];
@@ -142,7 +138,7 @@ private:
void SendNetChat(std::string message, int destination = -1);
/// Format and display a chat message received over network
void HandleChatMsg(const ChatMessage& msg);
-
+
/// synced actions (received from server) go in here
void ActionReceived(const Action&, int playernum);
diff --git a/rts/Game/GameHelper.cpp b/rts/Game/GameHelper.cpp
index 404c9af..53b72de 100644
--- a/rts/Game/GameHelper.cpp
+++ b/rts/Game/GameHelper.cpp
@@ -829,7 +829,7 @@ public:
-void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* lastTargetUnit, std::multimap<float, CUnit*>& targets)
+void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, CUnit* lastTarget, std::multimap<float, CUnit*>& targets)
{
GML_RECMUTEX_LOCK(qnum); // GenerateTargets
@@ -845,7 +845,7 @@ void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* last
const std::vector<int>& quads = qf->GetQuads(pos, radius + (aHeight - std::max(0.f, readmap->minheight)) * heightMod);
- const int tempNum = gs->tempNum++;
+ int tempNum = gs->tempNum++;
typedef std::vector<int>::const_iterator VectorIt;
typedef std::list<CUnit*>::const_iterator ListIt;
@@ -893,16 +893,13 @@ void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* last
const float modRange = radius + (aHeight - targPos.y) * heightMod;
if ((pos - targPos).SqLength2D() <= modRange * modRange) {
- const float dist2D = (pos - targPos).Length2D();
- const float rangeMul = (dist2D * weapon->weaponDef->proximityPriority + modRange * 0.4f + 100.0f);
- const float damageMul = weapon->weaponDef->damages[targetUnit->armorType] * targetUnit->curArmorMultiple;
-
- targetPriority *= rangeMul;
+ float dist2d = (pos - targPos).Length2D();
+ targetPriority *= (dist2d * weapon->weaponDef->proximityPriority + modRange * 0.4f + 100.0f);
if (targetLOSState & LOS_INLOS) {
targetPriority *= (secDamage + targetUnit->health);
- if (targetUnit == lastTargetUnit) {
+ if (targetUnit == lastTarget) {
targetPriority *= weapon->avoidTarget ? 10.0f : 0.4f;
}
@@ -918,7 +915,9 @@ void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* last
}
if (targetLOSState & LOS_PREVLOS) {
- targetPriority /= (damageMul * targetUnit->power * (0.7f + gs->randFloat() * 0.6f));
+ targetPriority /=
+ weapon->weaponDef->damages[targetUnit->armorType] * targetUnit->curArmorMultiple *
+ targetUnit->power * (0.7f + gs->randFloat() * 0.6f);
if (targetUnit->category & weapon->badTargetCategory) {
targetPriority *= 100.0f;
@@ -945,6 +944,7 @@ void CGameHelper::GenerateWeaponTargets(const CWeapon* weapon, const CUnit* last
tracefile << "\n";
}
#endif
+
}
CUnit* CGameHelper::GetClosestUnit(const float3 &pos, float searchRadius)
diff --git a/rts/Game/GameHelper.h b/rts/Game/GameHelper.h
index b079d10..8d4845d 100644
--- a/rts/Game/GameHelper.h
+++ b/rts/Game/GameHelper.h
@@ -55,7 +55,7 @@ public:
CUnit* GetClosestFriendlyUnit(const float3& pos, float searchRadius, int searchAllyteam);
CUnit* GetClosestEnemyAircraft(const float3& pos, float searchRadius, int searchAllyteam);
- void GenerateWeaponTargets(const CWeapon* attacker, const CUnit* lastTarget, std::multimap<float, CUnit*>& targets);
+ void GenerateWeaponTargets(const CWeapon* attacker, CUnit* lastTarget, std::multimap<float, CUnit*>& targets);
float TraceRay(const float3& start, const float3& dir, float length, float power, const CUnit* owner, const CUnit*& hit, int collisionFlags = 0, const CFeature** hitFeature = NULL);
float GuiTraceRay(const float3& start, const float3& dir, float length, const CUnit*& hit, bool useRadar, const CUnit* exclude = NULL);
float GuiTraceRayFeature(const float3& start, const float3& dir, float length, const CFeature*& feature);
diff --git a/rts/Game/PreGame.cpp b/rts/Game/PreGame.cpp
index 69c4927..476d066 100644
--- a/rts/Game/PreGame.cpp
+++ b/rts/Game/PreGame.cpp
@@ -214,23 +214,19 @@ void CPreGame::UpdateClientNet()
std::string message;
pckt >> message;
logOutput.Print(message);
- handleerror(NULL, "Remote requested quit: " + message, "Quit message", MBF_OK | MBF_EXCL);
+ handleerror(NULL, message, "Quit message", MBF_OK | MBF_EXCL);
} catch (netcode::UnpackPacketException &e) {
logOutput.Print("Got invalid QuitMessage: %s", e.err.c_str());
}
break;
}
- case NETMSG_CREATE_NEWPLAYER: {
- // server will send this first if we're using mid-game join
- // feature, to let us know about ourself (we won't be in
- // gamedata), otherwise skip to gamedata
+ case NETMSG_CREATE_NEWPLAYER: { // server will send this first if we're using midgame join feature, to let us know about ourself (we won't be in gamedata), otherwise skip to gamedata
try {
netcode::UnpackPacket pckt(packet, 3);
unsigned char spectator, team, playerNum;
std::string name;
- // since the >> operator uses dest size to extract data from
- // the packet, we need to use temp variables of the same
- // size of the packet, before converting to dest variable
+ // since the >> operator uses dest size to extract data from the packet, we need to use temp variables
+ // of the same size of the packet, then convert to dest variable
pckt >> playerNum;
pckt >> spectator;
pckt >> team;
@@ -241,30 +237,22 @@ void CPreGame::UpdateClientNet()
player.spectator = spectator;
player.team = team;
player.playerNum = playerNum;
- // add ourself, to avoid crashing if our player num gets
- // queried we will receive the same message later, in the
- // game class, which is the global broadcast version
- // the global broadcast will overwrite the user with the
- // same values as here
+ // add ourself, to avoid crashing if our player num gets queried
+ // we'll receive the same message later, in the game class, which is the global broadcast version
+ // the global broadcast will overwrite the user with the same values as here
playerHandler->AddPlayer(player);
} catch (netcode::UnpackPacketException &e) {
logOutput.Print("Got invalid New player message: %s", e.err.c_str());
}
break;
}
- case NETMSG_GAMEDATA: {
- // server first sends this to let us know about teams, allyteams
- // etc.
- // (not if we are joining mid-game as extra players)
- // see NETMSG_SETPLAYERNUM
+ case NETMSG_GAMEDATA: { // server first ( not if we're joining midgame as extra players ) sends this to let us know about teams, allyteams etc.
if (gameSetup)
throw content_error("Duplicate game data received from server");
GameDataReceived(packet);
break;
}
- case NETMSG_SETPLAYERNUM: {
- // this is sent after NETMSG_GAMEDATA, to let us know which
- // playernum we have
+ case NETMSG_SETPLAYERNUM: { // this is sent afterwards to let us know which playernum we have
if (!gameSetup)
throw content_error("No game data received from server");
diff --git a/rts/Game/UI/GuiHandler.cpp b/rts/Game/UI/GuiHandler.cpp
index 0c298c2..87be01c 100644
--- a/rts/Game/UI/GuiHandler.cpp
+++ b/rts/Game/UI/GuiHandler.cpp
@@ -1412,7 +1412,8 @@ void CGuiHandler::RunCustomCommands(const std::vector<std::string>& cmds, bool r
Action action(copy);
if (!ProcessLocalActions(action)) {
- game->ActionPressed(-1, action, false /*isRepeat*/);
+ CKeySet ks;
+ game->ActionPressed(action, ks, false /*isRepeat*/);
}
keyInput->SetKeyState(SDLK_LALT, tmpAlt);
diff --git a/rts/Game/UnsyncedGameCommands.cpp b/rts/Game/UnsyncedGameCommands.cpp
index d7aae2a..ffb936b 100644
--- a/rts/Game/UnsyncedGameCommands.cpp
+++ b/rts/Game/UnsyncedGameCommands.cpp
@@ -15,7 +15,7 @@
#include "PlayerRoster.h"
#include "TimeProfiler.h"
#include "IVideoCapturing.h"
-#include "WordCompletion.h"
+#include "Game/UI/UnitTracker.h"
#ifdef _WIN32
# include "winerror.h"
#endif
@@ -55,7 +55,6 @@
#include "UI/SelectionKeyHandler.h"
#include "UI/ShareBox.h"
#include "UI/TooltipConsole.h"
-#include "UI/UnitTracker.h"
#include "UI/ProfileDrawer.h"
#include "System/ConfigHandler.h"
#include "System/EventHandler.h"
@@ -89,186 +88,9 @@ static std::vector<std::string> _local_strSpaceTokenize(const std::string& text)
}
-
-bool CGame::ProcessCommandText(unsigned int key, const std::string& command) {
- if (command.size() <= 2)
- return false;
-
- if ((command[0] == '/') && (command[1] != '/')) {
- const string actionLine = command.substr(1); // strip the '/'
-
- Action fakeAction(actionLine);
- ActionPressed(key, fakeAction, false);
- return true;
- }
-
- return false;
-}
-
-bool CGame::ProcessKeyPressAction(unsigned int key, const Action& action) {
- if (action.command == "edit_return") {
- userWriting = false;
- writingPos = 0;
-
- if (key == SDLK_RETURN) {
- // prevent game start when host enters a chat message
- keyInput->SetKeyState(key, 0);
- }
- if (chatting) {
- string command;
-
- if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
- command = userInput.substr(2);
- } else {
- command = userInput;
- }
-
- if (ProcessCommandText(key, command)) {
- // execute an action
- consoleHistory->AddLine(command);
- logOutput.Print(command);
-
- chatting = false;
- userInput = "";
- writingPos = 0;
- }
- }
- return true;
- }
- else if ((action.command == "edit_escape") && (chatting || inMapDrawer->wantLabel)) {
- if (chatting) {
- consoleHistory->AddLine(userInput);
- }
- userWriting = false;
- chatting = false;
- inMapDrawer->wantLabel = false;
- userInput = "";
- writingPos = 0;
- return true;
- }
- else if (action.command == "edit_complete") {
- string head = userInput.substr(0, writingPos);
- string tail = userInput.substr(writingPos);
- const vector<string> &partials = wordCompletion->Complete(head);
- userInput = head + tail;
- writingPos = (int)head.length();
-
- if (!partials.empty()) {
- string msg;
- for (unsigned int i = 0; i < partials.size(); i++) {
- msg += " ";
- msg += partials[i];
- }
- logOutput.Print(msg);
- }
- return true;
- }
- else if (action.command == "chatswitchall") {
- if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
- userInput = userInput.substr(2);
- writingPos = std::max(0, writingPos - 2);
- }
-
- userInputPrefix = "";
- return true;
- }
- else if (action.command == "chatswitchally") {
- if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
- userInput[0] = 'a';
- } else {
- userInput = "a:" + userInput;
- writingPos += 2;
- }
-
- userInputPrefix = "a:";
- return true;
- }
- else if (action.command == "chatswitchspec") {
- if ((userInput.find_first_of("aAsS") == 0) && (userInput[1] == ':')) {
- userInput[0] = 's';
- } else {
- userInput = "s:" + userInput;
- writingPos += 2;
- }
-
- userInputPrefix = "s:";
- return true;
- }
- else if (action.command == "pastetext") {
- if (!action.extra.empty()) {
- userInput.insert(writingPos, action.extra);
- writingPos += action.extra.length();
- } else {
- PasteClipboard();
- }
- return true;
- }
-
- else if (action.command == "edit_backspace") {
- if (!userInput.empty() && (writingPos > 0)) {
- userInput.erase(writingPos - 1, 1);
- writingPos--;
- }
- return true;
- }
- else if (action.command == "edit_delete") {
- if (!userInput.empty() && (writingPos < (int)userInput.size())) {
- userInput.erase(writingPos, 1);
- }
- return true;
- }
- else if (action.command == "edit_home") {
- writingPos = 0;
- return true;
- }
- else if (action.command == "edit_end") {
- writingPos = (int)userInput.length();
- return true;
- }
- else if (action.command == "edit_prev_char") {
- writingPos = std::max(0, std::min((int)userInput.length(), writingPos - 1));
- return true;
- }
- else if (action.command == "edit_next_char") {
- writingPos = std::max(0, std::min((int)userInput.length(), writingPos + 1));
- return true;
- }
- else if (action.command == "edit_prev_word") {
- // prev word
- const char* s = userInput.c_str();
- int p = writingPos;
- while ((p > 0) && !isalnum(s[p - 1])) { p--; }
- while ((p > 0) && isalnum(s[p - 1])) { p--; }
- writingPos = p;
- return true;
- }
- else if (action.command == "edit_next_word") {
- const int len = (int)userInput.length();
- const char* s = userInput.c_str();
- int p = writingPos;
- while ((p < len) && !isalnum(s[p])) { p++; }
- while ((p < len) && isalnum(s[p])) { p++; }
- writingPos = p;
- return true;
- }
- else if ((action.command == "edit_prev_line") && chatting) {
- userInput = consoleHistory->PrevLine(userInput);
- writingPos = (int)userInput.length();
- return true;
- }
- else if ((action.command == "edit_next_line") && chatting) {
- userInput = consoleHistory->NextLine(userInput);
- writingPos = (int)userInput.length();
- return true;
- }
-
- return false;
-}
-
-
-
// FOR UNSYNCED MESSAGES
-bool CGame::ActionPressed(unsigned int key, const Action& action, bool isRepeat)
+bool CGame::ActionPressed(const Action& action,
+ const CKeySet& ks, bool isRepeat)
{
// we may need these later
CBaseGroundDrawer* gd = readmap->GetGroundDrawer();
@@ -409,7 +231,7 @@ bool CGame::ActionPressed(unsigned int key, const Action& action, bool isRepeat)
if (pos.x >= 0) {
inMapDrawer->keyPressed = false;
inMapDrawer->PromptLabel(pos);
- if ((key >= SDLK_SPACE) && (key <= SDLK_DELETE)) {
+ if ((ks.Key() >= SDLK_SPACE) && (ks.Key() <= SDLK_DELETE)) {
ignoreNextChar=true;
}
}
@@ -803,7 +625,7 @@ bool CGame::ActionPressed(unsigned int key, const Action& action, bool isRepeat)
else if (((cmd == "chat") || (cmd == "chatall") ||
(cmd == "chatally") || (cmd == "chatspec")) &&
// if chat is bound to enter and we're waiting for user to press enter to start game, ignore.
- (key != SDLK_RETURN || playing || !keyInput->IsKeyPressed(SDLK_LCTRL))) {
+ (ks.Key() != SDLK_RETURN || playing || !keyInput->IsKeyPressed(SDLK_LCTRL))) {
if (cmd == "chatall") { userInputPrefix = ""; }
if (cmd == "chatally") { userInputPrefix = "a:"; }
@@ -814,7 +636,7 @@ bool CGame::ActionPressed(unsigned int key, const Action& action, bool isRepeat)
writingPos = (int)userInput.length();
chatting = true;
- if (key != SDLK_RETURN) {
+ if (ks.Key() != SDLK_RETURN) {
ignoreNextChar = true;
}
@@ -1646,3 +1468,5 @@ bool CGame::ActionPressed(unsigned int key, const Action& action, bool isRepeat)
return true;
}
+
+
diff --git a/rts/Rendering/Env/AdvSky.cpp b/rts/Rendering/Env/AdvSky.cpp
index 08393fe..680fa0f 100644
--- a/rts/Rendering/Env/AdvSky.cpp
+++ b/rts/Rendering/Env/AdvSky.cpp
@@ -46,7 +46,6 @@ CAdvSky::CAdvSky()
domeWidth = sin(2*PI/32)*400*1.7f;
UpdateSkyDir();
- InitSun();
UpdateSunDir();
for(int a=0;a<CLOUD_DETAIL;a++)
@@ -65,15 +64,11 @@ CAdvSky::CAdvSky()
CreateClouds();
dynamicSky = configHandler->Get("DynamicSky", false);
+ InitSun();
oldCoverBaseX=-5;
cloudFP = LoadFragmentProgram("ARB/clouds.fp");
- CreateSkyDomeList();
-}
-
-void CAdvSky::CreateSkyDomeList()
-{
glGetError();
skyDomeList = glGenLists(1);
glNewList(skyDomeList, GL_COMPILE);
@@ -665,7 +660,7 @@ void CAdvSky::InitSun()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
// gluBuild2DMipmaps(GL_TEXTURE_2D,1 ,32, 2, GL_ALPHA, GL_UNSIGNED_BYTE, mem);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE ,32, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);
+ glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE ,32, 4,0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);
delete [] mem;
}
diff --git a/rts/Rendering/Env/AdvSky.h b/rts/Rendering/Env/AdvSky.h
index f963437..5686ce9 100644
--- a/rts/Rendering/Env/AdvSky.h
+++ b/rts/Rendering/Env/AdvSky.h
@@ -21,7 +21,6 @@ public:
void UpdateSkyTexture();
private:
- void CreateSkyDomeList();
void InitSun();
void UpdateSunFlare();
void CreateCover(int baseX, int baseY, float* buf);
diff --git a/rts/Rendering/Env/BaseTreeDrawer.cpp b/rts/Rendering/Env/BaseTreeDrawer.cpp
index bcfcd20..31ebe22 100644
--- a/rts/Rendering/Env/BaseTreeDrawer.cpp
+++ b/rts/Rendering/Env/BaseTreeDrawer.cpp
@@ -7,7 +7,6 @@
#include "BasicTreeDrawer.h"
#include "AdvTreeDrawer.h"
#include "Game/Camera.h"
-#include "Rendering/GlobalRendering.h"
#include "Sim/Features/FeatureHandler.h"
#include "Sim/Features/Feature.h"
#include "Sim/Misc/GlobalConstants.h"
@@ -83,8 +82,7 @@ void CBaseTreeDrawer::DrawShadowPass()
void CBaseTreeDrawer::Draw(bool drawReflection)
{
- const float maxDistance = CGlobalRendering::MAX_VIEW_RANGE / (SQUARE_SIZE * TREE_SQUARE_SIZE);
- const float treeDistance = Clamp(baseTreeDistance, 1.0f, maxDistance);
+ const float treeDistance = Clamp(baseTreeDistance, 1.0f, (float)MAX_VIEW_RANGE / (SQUARE_SIZE * TREE_SQUARE_SIZE));
Draw(treeDistance, drawReflection);
}
diff --git a/rts/Rendering/Env/BasicSky.cpp b/rts/Rendering/Env/BasicSky.cpp
index 67621f5..10b2b3e 100644
--- a/rts/Rendering/Env/BasicSky.cpp
+++ b/rts/Rendering/Env/BasicSky.cpp
@@ -48,7 +48,6 @@ CBasicSky::CBasicSky()
domeWidth=sin(PI/16)*400*1.7f;
UpdateSkyDir();
- InitSun();
UpdateSunDir();
cloudDensity = 0.25f + mapInfo->atmosphere.cloudDensity * 0.5f;
@@ -67,9 +66,8 @@ CBasicSky::CBasicSky()
CreateClouds();
dynamicSky = configHandler->Get("DynamicSky", false);
+ InitSun();
oldCoverBaseX=-5;
-
- CreateSkyDomeList();
}
void CBasicSky::CreateSkyDomeList()
@@ -514,7 +512,7 @@ void CBasicSky::DrawSun()
glDisable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
- static unsigned char buf[32];
+ static unsigned char buf[128];
glEnable(GL_TEXTURE_2D);
float3 modCamera=sundir1*camera->pos.x+sundir2*camera->pos.z;
@@ -538,6 +536,7 @@ void CBasicSky::DrawSun()
}
float mid=0;
+ unsigned char *bf=buf+32, *bf2=buf+64;
for(int x=0;x<32;++x){
float cx1=(*cvs++)*(1-fx)+(*cvs1++)*fx;
float cx2=(*cvs2++)*(1-fx)+(*cvs3++)*fx;
@@ -546,6 +545,9 @@ void CBasicSky::DrawSun()
if(cover>127.5f)
cover=127.5f;
mid+=cover;
+
+ (*bf++)=(unsigned char)(255-cover*2);
+ (*bf2++)=(unsigned char)(128-cover);
}
mid*=1.0f/32;
for(int x=0;x<32;++x){
@@ -553,7 +555,7 @@ void CBasicSky::DrawSun()
}
glBindTexture(GL_TEXTURE_2D, sunFlareTex);
- glTexSubImage2D(GL_TEXTURE_2D,0,0,0,32,1,GL_LUMINANCE,GL_UNSIGNED_BYTE,buf);
+ glTexSubImage2D(GL_TEXTURE_2D,0,0,0,32,3,GL_LUMINANCE,GL_UNSIGNED_BYTE,buf);
const float si = skyLight->GetLightIntensity();
const float3 sc = sunColor * si;
@@ -584,9 +586,9 @@ void CBasicSky::UpdateSunFlare() {
float dx=sin(x*2*PI/256.0f);
float dy=cos(x*2*PI/256.0f);
- glTexCoord2f(x/256.0f,0.25f);
+ glTexCoord2f(x/256.0f,0.125f);
glVertexf3(modSunDir*5+ldir*dx*0.0014f+udir*dy*0.0014f);
- glTexCoord2f(x/256.0f,0.75f);
+ glTexCoord2f(x/256.0f,0.875f);
glVertexf3(modSunDir*5+ldir*dx*4+udir*dy*4);
}
glEnd();
@@ -621,7 +623,7 @@ void CBasicSky::InitSun()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
glBuildMipmaps(GL_TEXTURE_2D,GL_RGBA8 ,128, 128, GL_RGBA, GL_UNSIGNED_BYTE, mem);
- for(int y=0;y<2;++y){
+ for(int y=0;y<4;++y){
for(int x=0;x<32;++x){
if(y==0 && x%2)
mem[(y*32+x)]=255;
@@ -635,7 +637,7 @@ void CBasicSky::InitSun()
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE ,32, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);
+ glTexImage2D(GL_TEXTURE_2D,0, GL_LUMINANCE, 32, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mem);
delete[] mem;
}
@@ -793,13 +795,14 @@ void CBasicSky::UpdateTexPartDot3(int x, int y, unsigned char (*texp)[4]) {
const float sunInt = skyLight->GetLightIntensity();
const float sunDist = acos(dir.dot(skyLight->GetLightDir())) * 50;
- const float sunMod = sunInt * (0.3f / math::sqrt(sunDist) + 2.0f / sunDist);
+ const float sunMod = sunInt * (0.3f / math::sqrt(sunDist) + 3.0f / (1 + sunDist));
const float green = std::min(1.0f, (0.55f + sunMod));
+ const float blue = 203 - sunInt * (40.0f / (3 + sunDist));
texp[x][0] = (unsigned char) (sunInt * (255 - std::min(255.0f, sunDist))); // sun on borders
texp[x][1] = (unsigned char) (green * 255); // sun light through
- texp[x][2] = (unsigned char) 203; // ambient
+ texp[x][2] = (unsigned char) blue; // ambient
texp[x][3] = 255;
}
diff --git a/rts/Rendering/FarTextureHandler.cpp b/rts/Rendering/FarTextureHandler.cpp
old mode 100644
new mode 100755
index 3a7978a..74f20f4
--- a/rts/Rendering/FarTextureHandler.cpp
+++ b/rts/Rendering/FarTextureHandler.cpp
@@ -181,7 +181,7 @@ void CFarTextureHandler::CreateFarTexture(const CSolidObject* obj)
unitDrawer->SetupForUnitDrawing();
unitDrawer->GetOpaqueModelRenderer(model->type)->PushRenderState();
- if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ) {
+ if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ || model->type == MODELTYPE_ASS) {
// FIXME for some strange reason we need to invert the culling, why?
if (model->type == MODELTYPE_S3O) {
glCullFace(GL_FRONT);
diff --git a/rts/Rendering/FeatureDrawer.cpp b/rts/Rendering/FeatureDrawer.cpp
old mode 100644
new mode 100755
index 4385a71..b88eab3
--- a/rts/Rendering/FeatureDrawer.cpp
+++ b/rts/Rendering/FeatureDrawer.cpp
@@ -229,7 +229,7 @@ void CFeatureDrawer::DrawOpaqueFeatures(int modelType)
FeatureSet::iterator featureSetIt;
for (featureBinIt = featureBin.begin(); featureBinIt != featureBin.end(); ++featureBinIt) {
- if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ) {
+ if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ || modelType == MODELTYPE_ASS) {
texturehandlerS3O->SetS3oTexture(featureBinIt->first);
}
@@ -371,7 +371,7 @@ void CFeatureDrawer::DrawFadeFeaturesHelper(int modelType) {
FeatureRenderBin& featureBin = cloakedModelRenderers[modelType]->GetFeatureBinMutable();
for (FeatureRenderBinIt it = featureBin.begin(); it != featureBin.end(); ++it) {
- if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ) {
+ if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ || modelType == MODELTYPE_ASS) {
texturehandlerS3O->SetS3oTexture(it->first);
}
diff --git a/rts/Rendering/GlobalRendering.cpp b/rts/Rendering/GlobalRendering.cpp
index 60bd337..86d328b 100644
--- a/rts/Rendering/GlobalRendering.cpp
+++ b/rts/Rendering/GlobalRendering.cpp
@@ -22,8 +22,6 @@
*/
CGlobalRendering* globalRendering;
-const float CGlobalRendering::MAX_VIEW_RANGE = 8000.0f;
-const float CGlobalRendering::NEAR_PLANE = 2.8f;
CR_BIND(CGlobalRendering, );
diff --git a/rts/Rendering/GlobalRendering.h b/rts/Rendering/GlobalRendering.h
index 38525b0..e60ba46 100644
--- a/rts/Rendering/GlobalRendering.h
+++ b/rts/Rendering/GlobalRendering.h
@@ -4,6 +4,8 @@
#define _GLOBAL_RENDERING_H
#include "System/creg/creg_cond.h"
+#include "System/float4.h"
+#include "System/Matrix44f.h"
/**
* @brief Globally accessible unsynced, rendering related data
@@ -180,18 +182,6 @@ public:
* @brief full-screen or windowed rendering
*/
bool fullScreen;
-
-
-
- /**
- * @brief max view range in elmos
- */
- static const float MAX_VIEW_RANGE;
-
- /**
- * @brief near z-plane distance in elmos
- */
- static const float NEAR_PLANE;
};
extern CGlobalRendering* globalRendering;
diff --git a/rts/Rendering/Models/3DModel.cpp b/rts/Rendering/Models/3DModel.cpp
old mode 100644
new mode 100755
index 5c3d98d..02df7b7
--- a/rts/Rendering/Models/3DModel.cpp
+++ b/rts/Rendering/Models/3DModel.cpp
@@ -18,6 +18,18 @@
//////////////////////////////////////////////////////////////////////
+// S3DModel
+//
+
+S3DModelPiece* S3DModel::FindPiece( std::string name )
+{
+ const ModelPieceMap::const_iterator it = pieces.find(name);
+ if (it != pieces.end()) return it->second;
+ return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
// S3DModelPiece
//
diff --git a/rts/Rendering/Models/3DModel.h b/rts/Rendering/Models/3DModel.h
old mode 100644
new mode 100755
index ba577b7..0501a41
--- a/rts/Rendering/Models/3DModel.h
+++ b/rts/Rendering/Models/3DModel.h
@@ -5,23 +5,26 @@
#include <vector>
#include <string>
-
+#include <set>
+#include <map>
#include "System/Matrix44f.h"
-
const int
MODELTYPE_3DO = 0,
MODELTYPE_S3O = 1,
MODELTYPE_OBJ = 2,
- MODELTYPE_OTHER = 3;
+ MODELTYPE_ASS = 3, // Model loaded by Assimp library
+ MODELTYPE_OTHER = 4; // For future use. Still used in some parts of code.
struct CollisionVolume;
struct S3DModel;
struct S3DModelPiece;
struct LocalModel;
struct LocalModelPiece;
+struct aiScene;
+typedef std::map<std::string, S3DModelPiece*> ModelPieceMap;
struct S3DModelPiece {
S3DModelPiece(): type(-1) {
@@ -53,8 +56,10 @@ struct S3DModelPiece {
std::string name;
+ std::string parentName;
std::vector<S3DModelPiece*> childs;
+ S3DModel* model;
S3DModelPiece* parent;
CollisionVolume* colvol;
@@ -68,23 +73,32 @@ struct S3DModelPiece {
float3 maxs;
float3 offset; // wrt. parent
float3 goffset; // wrt. root
+ float3 rot;
+ float3 scale;
};
struct S3DModel
{
S3DModel(): id(-1), type(-1), textureType(-1) {
- numPieces = 0;
-
- radius = 0.0f;
- height = 0.0f;
-
- rootPiece = NULL;
+ height = 0.0f;
+ radius = 0.0f;
+ relMidPos = float3(0.0f, 0.0f, 0.0f);
+ mins = float3(10000.0f, 10000.0f, 10000.0f);
+ maxs = float3(-10000.0f, -10000.0f, -10000.0f);
+ tex1 = "default.png";
+ tex2 = "";
+ flipTexY = false;
+ invertTexAlpha = false;
+ numPieces = 0;
+ rootPiece = NULL;
+ scene = NULL;
}
S3DModelPiece* GetRootPiece() { return rootPiece; }
void SetRootPiece(S3DModelPiece* p) { rootPiece = p; }
void DrawStatic() const { rootPiece->DrawStatic(); }
+ S3DModelPiece* FindPiece( std::string name );
std::string name;
std::string tex1;
@@ -93,8 +107,9 @@ struct S3DModel
int id; //! unsynced ID, starting with 1
int type; //! MODELTYPE_*
int textureType; //! FIXME: MAKE S3O ONLY (0 = 3DO, otherwise S3O or OBJ)
+ bool flipTexY; //! Turn both textures upside down before use
+ bool invertTexAlpha; //! Invert teamcolor alpha channel in S3O texture 1
- int numPieces;
float radius;
float height;
@@ -102,7 +117,10 @@ struct S3DModel
float3 maxs;
float3 relMidPos;
- S3DModelPiece* rootPiece;
+ int numPieces;
+ S3DModelPiece* rootPiece; //! The piece at the base of the model hierarchy
+ ModelPieceMap pieces; //! Lookup table for pieces by name
+ const aiScene* scene; //! Assimp scene containing all loaded model data. NULL for S30/3DO.
};
diff --git a/rts/Rendering/Models/3DModelLog.h b/rts/Rendering/Models/3DModelLog.h
new file mode 100644
index 0000000..c1b38e2
--- /dev/null
+++ b/rts/Rendering/Models/3DModelLog.h
@@ -0,0 +1,14 @@
+/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
+
+#ifndef _3DMODELLOG_H_
+#define _3DMODELLOG_H_
+
+#include "System/LogOutput.h"
+
+// Enabling the "Model" and "Piece" log subsystems will help debug model loading. "Model-detail" is extremely verbose.
+static CLogSubsystem LOG_MODEL("Model");
+static CLogSubsystem LOG_MODEL_DETAIL("Model-detail");
+static CLogSubsystem LOG_PIECE("Piece");
+static CLogSubsystem LOG_PIECE_DETAIL("Piece-detail");
+
+#endif // _3DMODELLOG_H_
diff --git a/rts/Rendering/Models/AssIO.cpp b/rts/Rendering/Models/AssIO.cpp
new file mode 100644
index 0000000..9a2a1cb
--- /dev/null
+++ b/rts/Rendering/Models/AssIO.cpp
@@ -0,0 +1,96 @@
+#include "StdAfx.h"
+
+#include <string>
+
+#include "AssIO.h"
+
+#include "FileSystem/FileHandler.h"
+
+AssVFSStream::AssVFSStream(const std::string& pFile, const std::string& pMode)
+{
+ file = new CFileHandler(pFile, pMode);
+}
+
+AssVFSStream::~AssVFSStream(void)
+{
+ delete file;
+}
+
+size_t AssVFSStream::Read( void* pvBuffer, size_t pSize, size_t pCount)
+{
+ // Spring VFS only supports reading chars. Need to convert.
+ int length = pSize * pCount;
+ return file->Read(pvBuffer, length);
+}
+
+size_t AssVFSStream::Write( const void* pvBuffer, size_t pSize, size_t pCount)
+{
+ // FAKE. Shouldn't need to write back to VFS
+ return pSize * pCount;
+}
+
+aiReturn AssVFSStream::Seek( size_t pOffset, aiOrigin pOrigin)
+{
+ switch(pOrigin){
+ case aiOrigin_SET: // from start of file
+ if ( pOffset >= file->FileSize() ) return AI_FAILURE;
+ file->Seek( pOffset, std::ios_base::beg );
+ break;
+ case aiOrigin_CUR: // from current position in file
+ if ( pOffset >= ( file->FileSize() + file->GetPos() ) ) return AI_FAILURE;
+ file->Seek( pOffset, std::ios_base::cur );
+ break;
+ case aiOrigin_END: // reverse from end of file
+ if ( pOffset >= file->FileSize() ) return AI_FAILURE;
+ file->Seek( pOffset, std::ios_base::end );
+ break;
+ }
+ return AI_SUCCESS;
+}
+
+size_t AssVFSStream::Tell() const
+{
+ return file->GetPos();
+}
+
+
+size_t AssVFSStream::FileSize() const
+{
+ int filesize = file->FileSize();
+ if ( filesize < 0 ) filesize = 0;
+ return filesize;
+}
+
+void AssVFSStream::Flush () // FAKE
+{
+}
+
+
+// Check whether a specific file exists
+bool AssVFSSystem::Exists( const char* pFile) const
+{
+ CFileHandler file(pFile);
+ return file.FileExists();
+}
+
+// Get the path delimiter character we'd like to get
+char AssVFSSystem::getOsSeparator() const
+{
+ return '/';
+}
+
+bool AssVFSSystem::ComparePaths (const std::string& one, const std::string& second) const
+{
+ return one == second; // too naive? probably should convert to absolute paths
+}
+
+// open a custom stream
+Assimp::IOStream* AssVFSSystem::Open( const char* pFile, const char* pMode)
+{
+ return new AssVFSStream( pFile, pMode );
+}
+
+void AssVFSSystem::Close( Assimp::IOStream* pFile)
+{
+ delete pFile;
+}
diff --git a/rts/Rendering/Models/AssIO.h b/rts/Rendering/Models/AssIO.h
new file mode 100644
index 0000000..7b34efa
--- /dev/null
+++ b/rts/Rendering/Models/AssIO.h
@@ -0,0 +1,52 @@
+#ifndef ASSIO_H
+#define ASSIO_H
+
+#include "IOStream.h"
+#include "IOSystem.h"
+class CFileHandler;
+
+// Custom implementation of Assimp IOStream to support Spring's VFS
+// Required because Assimp models often need to load textures from other files
+
+class AssVFSStream : public Assimp::IOStream
+{
+ friend class AssVFSSystem;
+ CFileHandler* file;
+
+protected:
+ // Constructor protected for private usage by AssVFSSystem
+ AssVFSStream(const std::string& pFile, const std::string& pMode);
+
+public:
+ ~AssVFSStream(void);
+ size_t Read( void* pvBuffer, size_t pSize, size_t pCount);
+ size_t Write( const void* pvBuffer, size_t pSize, size_t pCount);
+ aiReturn Seek( size_t pOffset, aiOrigin pOrigin);
+ size_t Tell() const;
+ size_t FileSize() const;
+ void Flush ();
+};
+
+
+// Spring VFS Filesystem Wrapper for Assimp
+
+class AssVFSSystem : public Assimp::IOSystem
+{
+public:
+ AssVFSSystem() { }
+ ~AssVFSSystem() { }
+
+ // Check whether a specific file exists
+ bool Exists( const char* pFile) const;
+
+ // Get the path delimiter character we'd like to get
+ char getOsSeparator() const;
+ bool ComparePaths (const std::string& one, const std::string& second) const;
+
+ // open a custom stream
+ Assimp::IOStream* Open( const char* pFile, const char* pMode = "rb" );
+
+ void Close( Assimp::IOStream* pFile);
+};
+
+#endif
diff --git a/rts/Rendering/Models/AssParser.cpp b/rts/Rendering/Models/AssParser.cpp
new file mode 100755
index 0000000..2678a01
--- /dev/null
+++ b/rts/Rendering/Models/AssParser.cpp
@@ -0,0 +1,565 @@
+// AssParser.cpp: implementation of the CAssParser class. Reads 3D formats supported by Assimp lib.
+//
+//////////////////////////////////////////////////////////////////////
+//#include "StdAfx.h"
+
+#include "Util.h"
+#include "LogOutput.h"
+#include "Platform/errorhandler.h"
+#include "System/Exceptions.h"
+#include "Sim/Misc/CollisionVolume.h"
+#include "FileSystem/FileHandler.h"
+#include "Lua/LuaParser.h"
+#include "3DModel.h"
+#include "3DModelLog.h"
+#include "S3OParser.h"
+#include "AssIO.h"
+#include "AssParser.h"
+
+#include "assimp.hpp"
+#include "aiDefines.h"
+#include "aiTypes.h"
+#include "aiScene.h"
+#include "aiPostProcess.h"
+#include "DefaultLogger.h"
+#include "Rendering/Textures/S3OTextureHandler.h"
+
+#define IS_QNAN(f) (f != f)
+#define DEGTORAD 0.0174532925
+
+// triangulate guarantees the most complex mesh is a triangle
+// sortbytype ensure only 1 type of primitive type per mesh is used
+#define ASS_POSTPROCESS_OPTIONS \
+ aiProcess_RemoveComponent | \
+ aiProcess_FindInvalidData | \
+ aiProcess_CalcTangentSpace | \
+ aiProcess_GenSmoothNormals | \
+ aiProcess_SplitLargeMeshes | \
+ aiProcess_Triangulate | \
+ aiProcess_GenUVCoords | \
+ aiProcess_SortByPType | \
+ aiProcess_JoinIdenticalVertices
+
+//aiProcess_ImproveCacheLocality
+
+// Convert Assimp quaternion to radians around x, y and z
+float3 QuaternionToRadianAngles( aiQuaternion q1 )
+{
+ float sqw = q1.w*q1.w;
+ float sqx = q1.x*q1.x;
+ float sqy = q1.y*q1.y;
+ float sqz = q1.z*q1.z;
+ float unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise is correction factor
+ float test = q1.x*q1.y + q1.z*q1.w;
+
+ float3 result(0.0f, 0.0f, 0.0f);
+
+ if (test > 0.499f * unit) { // singularity at north pole
+ result.x = 2 * atan2(q1.x,q1.w);
+ result.y = PI/2;
+ } else if (test < -0.499f * unit) { // singularity at south pole
+ result.x = -2 * atan2(q1.x,q1.w);
+ result.y = -PI/2;
+ } else {
+ result.x = atan2(2*q1.y*q1.w-2*q1.x*q1.z , sqx - sqy - sqz + sqw);
+ result.y = asin(2*test/unit);
+ result.z = atan2(2*q1.x*q1.w-2*q1.y*q1.z , -sqx + sqy - sqz + sqw);
+ }
+ return result;
+}
+
+// Convert float3 rotations in degrees to radians
+void DegreesToRadianAngles( float3& angles )
+{
+ angles.x *= DEGTORAD;
+ angles.y *= DEGTORAD;
+ angles.z *= DEGTORAD;
+}
+
+class AssLogStream : public Assimp::LogStream
+{
+public:
+ AssLogStream() {}
+ ~AssLogStream() {}
+ void write(const char* message)
+ {
+ logOutput.Print (LOG_MODEL_DETAIL, "Assimp: %s", message);
+ }
+};
+
+
+
+S3DModel* CAssParser::Load(const std::string& modelFileName)
+{
+ logOutput.Print (LOG_MODEL, "Loading model: %s\n", modelFileName.c_str() );
+ std::string modelPath = modelFileName.substr(0, modelFileName.find_last_of('/'));
+ std::string modelFileNameNoPath = modelFileName.substr(modelPath.length()+1, modelFileName.length());
+ std::string modelName = modelFileNameNoPath.substr(0, modelFileNameNoPath.find_last_of('.'));
+ std::string modelExt = modelFileNameNoPath.substr(modelFileNameNoPath.find_last_of('.'), modelFileName.length());
+
+ // LOAD METADATA
+ // Load the lua metafile. This contains properties unique to Spring models and must return a table
+ std::string metaFileName = modelFileName + ".lua";
+ CFileHandler* metaFile = new CFileHandler(metaFileName);
+ if (!metaFile->FileExists()) {
+ // Try again without the model file extension
+ metaFileName = modelPath + '/' + modelName + ".lua";
+ metaFile = new CFileHandler(metaFileName);
+ }
+ LuaParser metaFileParser(metaFileName, SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
+ if (!metaFileParser.Execute()) {
+ if (!metaFile->FileExists()) {
+ logOutput.Print(LOG_MODEL, "No meta-file '%s'. Using defaults.", metaFileName.c_str());
+ } else {
+ logOutput.Print(LOG_MODEL, "ERROR in '%s': %s. Using defaults.", metaFileName.c_str(), metaFileParser.GetErrorLog().c_str());
+ }
+ }
+ // Get the (root-level) model table
+ const LuaTable& metaTable = metaFileParser.GetRoot();
+ if (metaTable.IsValid()) logOutput.Print(LOG_MODEL, "Found valid model metadata in '%s'", metaFileName.c_str());
+
+
+ // LOAD MODEL DATA
+ // Create a model importer instance
+ Assimp::Importer importer;
+
+ // Create a logger for debugging model loading issues
+ Assimp::DefaultLogger::create("",Assimp::Logger::VERBOSE);
+ const unsigned int severity = Assimp::Logger::DEBUGGING|Assimp::Logger::INFO|Assimp::Logger::ERR|Assimp::Logger::WARN;
+ Assimp::DefaultLogger::get()->attachStream( new AssLogStream(), severity );
+
+ // Give the importer an IO class that handles Spring's VFS
+ importer.SetIOHandler( new AssVFSSystem() );
+
+ // Speed-up processing by skipping things we don't need
+ importer.SetPropertyInteger(AI_CONFIG_PP_RVC_FLAGS, aiComponent_CAMERAS|aiComponent_LIGHTS|aiComponent_TEXTURES|aiComponent_ANIMATIONS);
+
+ // Read the model file to build a scene object
+ logOutput.Print(LOG_MODEL, "Importing model file: %s\n", modelFileName.c_str() );
+ const aiScene* scene = importer.ReadFile( modelFileName, ASS_POSTPROCESS_OPTIONS );
+ if (scene != NULL) {
+ logOutput.Print(LOG_MODEL, "Processing scene for model: %s (%d meshes / %d materials / %d textures)", modelFileName.c_str(), scene->mNumMeshes, scene->mNumMaterials, scene->mNumTextures );
+ } else {
+ logOutput.Print (LOG_MODEL, "Model Import Error: %s\n", importer.GetErrorString());
+ }
+
+ S3DModel* model = new S3DModel;
+ model->name = modelFileName;
+ model->type = MODELTYPE_ASS;
+ model->numPieces = 0;
+ model->scene = scene;
+ //model->meta = &metaTable;
+
+ // Assign textures
+ // The S3O texture handler uses two textures.
+ // The first contains diffuse color (RGB) and teamcolor (A)
+ // The second contains glow (R), reflectivity (G) and 1-bit Alpha (A).
+ if (metaTable.KeyExists("tex1")) {
+ model->tex1 = metaTable.GetString("tex1", "default.png");
+ } else {
+ // Search for a texture
+ std::vector<std::string> files = CFileHandler::FindFiles("unittextures/", modelName + ".*");
+ for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) {
+ std::string texPath = std::string(*fi);
+ model->tex1 = texPath.substr(texPath.find('/')+1, texPath.length());
+ break; // there can be only one!
+ }
+ }
+ if (metaTable.KeyExists("tex2")) {
+ model->tex2 = metaTable.GetString("tex2", "");
+ } else {
+ // Search for a texture
+ std::vector<std::string> files = CFileHandler::FindFiles("unittextures/", modelName + "2.*");
+ for(std::vector<std::string>::iterator fi = files.begin(); fi != files.end(); ++fi) {
+ std::string texPath = std::string(*fi);
+ model->tex2 = texPath.substr(texPath.find('/')+1, texPath.length());
+ break; // there can be only one!
+ }
+ }
+ model->flipTexY = metaTable.GetBool("fliptextures", true); // Flip texture upside down
+ model->invertTexAlpha = metaTable.GetBool("invertteamcolor", true); // Reverse teamcolor levels
+
+ // Load textures
+ logOutput.Print(LOG_MODEL, "Loading textures. Tex1: '%s' Tex2: '%s'", model->tex1.c_str(), model->tex2.c_str());
+ texturehandlerS3O->LoadS3OTexture(model);
+
+ // Load all pieces in the model
+ logOutput.Print(LOG_MODEL, "Loading pieces from root node '%s'", scene->mRootNode->mName.data);
+ LoadPiece( model, scene->mRootNode, metaTable );
+
+ // Update piece hierarchy based on metadata
+ BuildPieceHierarchy( model );
+
+ // Simplified dimensions used for rough calculations
+ model->radius = metaTable.GetFloat("radius", model->radius);
+ model->height = metaTable.GetFloat("height", model->height);
+ model->relMidPos = metaTable.GetFloat3("midpos", model->relMidPos);
+ model->mins = metaTable.GetFloat3("mins", model->mins);
+ model->maxs = metaTable.GetFloat3("maxs", model->maxs);
+
+ // Calculate model dimensions if not set
+ if (!metaTable.KeyExists("mins") || !metaTable.KeyExists("maxs")) CalculateMinMax( model->rootPiece );
+ if (model->radius < 0.0001f) CalculateRadius( model );
+ if (model->height < 0.0001f) CalculateHeight( model );
+
+ // Verbose logging of model properties
+ logOutput.Print(LOG_MODEL_DETAIL, "model->name: %s", model->name.c_str());
+ logOutput.Print(LOG_MODEL_DETAIL, "model->numobjects: %d", model->numPieces);
+ logOutput.Print(LOG_MODEL_DETAIL, "model->radius: %f", model->radius);
+ logOutput.Print(LOG_MODEL_DETAIL, "model->height: %f", model->height);
+ logOutput.Print(LOG_MODEL_DETAIL, "model->mins: (%f,%f,%f)", model->mins[0], model->mins[1], model->mins[2]);
+ logOutput.Print(LOG_MODEL_DETAIL, "model->maxs: (%f,%f,%f)", model->maxs[0], model->maxs[1], model->maxs[2]);
+
+ logOutput.Print (LOG_MODEL, "Model %s Imported.", model->name.c_str());
+ return model;
+}
+
+SAssPiece* CAssParser::LoadPiece(S3DModel* model, aiNode* node, const LuaTable& metaTable)
+{
+ // Create new piece
+ model->numPieces++;
+ SAssPiece* piece = new SAssPiece;
+ piece->type = MODELTYPE_OTHER;
+ piece->node = node;
+ piece->model = model;
+ piece->isEmpty = node->mNumMeshes == 0;
+
+ if (node->mParent) {
+ piece->name = std::string(node->mName.data);
+ } else {
+ piece->name = "root"; // The real model root
+ }
+ logOutput.Print(LOG_PIECE, "Converting node '%s' to piece '%s' (%d meshes).", node->mName.data, piece->name.c_str(), node->mNumMeshes);
+
+ // Load additional piece properties from metadata
+ const LuaTable& pieceTable = metaTable.SubTable("pieces").SubTable(piece->name);
+ if (pieceTable.IsValid()) logOutput.Print(LOG_PIECE, "Found metadata for piece '%s'", piece->name.c_str());
+
+ // Process transforms
+ float3 rotate, scale, offset;
+ aiVector3D _scale, _offset;
+ aiQuaternion _rotate;
+ node->mTransformation.Decompose(_scale,_rotate,_offset);
+
+ logOutput.Print(LOG_PIECE, "(%d:%s) Assimp offset (%f,%f,%f), rotate (%f,%f,%f), scale (%f,%f,%f)", model->numPieces, piece->name.c_str(),
+ _offset.x, _offset.y, _offset.z,
+ _rotate.x, _rotate.y, _rotate.z,
+ _scale.x, _scale.y, _scale.z
+ );
+
+ offset = pieceTable.GetFloat3("offset", float3(_offset.x, _offset.y, _offset.z));
+ offset.x = pieceTable.GetFloat("offsetx", offset.x);
+ offset.y = pieceTable.GetFloat("offsety", offset.y);
+ offset.z = pieceTable.GetFloat("offsetz", offset.z);
+
+ if (pieceTable.KeyExists("rotate")) {
+ rotate = pieceTable.GetFloat3("rotate", float3(0.0f, 0.0f, 0.0f));
+ DegreesToRadianAngles(rotate);
+ } else {
+ rotate = QuaternionToRadianAngles(_rotate);
+ rotate = float3(rotate.z, rotate.x, rotate.y);
+ }
+ if (pieceTable.KeyExists("rotatex")) rotate.x = pieceTable.GetFloat("rotatex", 0.0f) * DEGTORAD;
+ if (pieceTable.KeyExists("rotatey")) rotate.y = pieceTable.GetFloat("rotatey", 0.0f) * DEGTORAD;
+ if (pieceTable.KeyExists("rotatez")) rotate.z = pieceTable.GetFloat("rotatez", 0.0f) * DEGTORAD;
+
+ scale = pieceTable.GetFloat3("scale", float3(_scale.x, _scale.z, _scale.y));
+ scale.x = pieceTable.GetFloat("scalex", scale.x);
+ scale.y = pieceTable.GetFloat("scaley", scale.y);
+ scale.z = pieceTable.GetFloat("scalez", scale.z);
+
+ logOutput.Print(LOG_PIECE, "(%d:%s) Relative offset (%f,%f,%f), rotate (%f,%f,%f), scale (%f,%f,%f)", model->numPieces, piece->name.c_str(),
+ offset.x, offset.y, offset.z,
+ rotate.x, rotate.y, rotate.z,
+ scale.x, scale.y, scale.z
+ );
+ piece->offset = offset;
+ piece->rot = rotate;
+ piece->scale = scale;
+
+ // Get vertex data from node meshes
+ for ( unsigned meshListIndex = 0; meshListIndex < node->mNumMeshes; meshListIndex++ ) {
+ unsigned int meshIndex = node->mMeshes[meshListIndex];
+ logOutput.Print(LOG_PIECE_DETAIL, "Fetching mesh %d from scene", meshIndex );
+ aiMesh* mesh = model->scene->mMeshes[meshIndex];
+ std::vector<unsigned> mesh_vertex_mapping;
+ // extract vertex data
+ logOutput.Print(LOG_PIECE_DETAIL, "Processing vertices for mesh %d (%d vertices)", meshIndex, mesh->mNumVertices );
+ logOutput.Print(LOG_PIECE_DETAIL, "Normals: %s Tangents/Bitangents: %s TexCoords: %s",
+ (mesh->HasNormals())?"Y":"N",
+ (mesh->HasTangentsAndBitangents())?"Y":"N",
+ (mesh->HasTextureCoords(0)?"Y":"N")
+ );
+ for ( unsigned vertexIndex= 0; vertexIndex < mesh->mNumVertices; vertexIndex++) {
+ SAssVertex vertex;
+
+ // vertex coordinates
+ logOutput.Print(LOG_PIECE_DETAIL, "Fetching vertex %d from mesh", vertexIndex );
+ aiVector3D& aiVertex = mesh->mVertices[vertexIndex];
+ vertex.pos.x = aiVertex.x;
+ vertex.pos.y = aiVertex.y;
+ vertex.pos.z = aiVertex.z;
+
+ // update piece min/max extents
+ piece->mins.x = std::min(piece->mins.x, aiVertex.x);
+ piece->mins.y = std::min(piece->mins.y, aiVertex.y);
+ piece->mins.z = std::min(piece->mins.z, aiVertex.z);
+ piece->maxs.x = std::max(piece->maxs.x, aiVertex.x);
+ piece->maxs.y = std::max(piece->maxs.y, aiVertex.y);
+ piece->maxs.z = std::max(piece->maxs.z, aiVertex.z);
+
+ logOutput.Print(LOG_PIECE_DETAIL, "vertex position %d: %f %f %f", vertexIndex, vertex.pos.x, vertex.pos.y, vertex.pos.z );
+
+ // vertex normal
+ logOutput.Print(LOG_PIECE_DETAIL, "Fetching normal for vertex %d", vertexIndex );
+ aiVector3D& aiNormal = mesh->mNormals[vertexIndex];
+ vertex.hasNormal = !IS_QNAN(aiNormal);
+ if ( vertex.hasNormal ) {
+ vertex.normal.x = aiNormal.x;
+ vertex.normal.y = aiNormal.y;
+ vertex.normal.z = aiNormal.z;
+ logOutput.Print(LOG_PIECE_DETAIL, "vertex normal %d: %f %f %f",vertexIndex, vertex.normal.x, vertex.normal.y,vertex.normal.z );
+ }
+
+ // vertex tangent, x is positive in texture axis
+ if (mesh->HasTangentsAndBitangents()) {
+ logOutput.Print(LOG_PIECE_DETAIL, "Fetching tangent for vertex %d", vertexIndex );
+ aiVector3D& aiTangent = mesh->mTangents[vertexIndex];
+ vertex.hasTangent = !IS_QNAN(aiTangent);
+ if ( vertex.hasTangent ) {
+ float3 tangent;
+ tangent.x = aiTangent.x;
+ tangent.y = aiTangent.y;
+ tangent.z = aiTangent.z;
+ logOutput.Print(LOG_PIECE_DETAIL, "vertex tangent %d: %f %f %f",vertexIndex, tangent.x, tangent.y,tangent.z );
+ piece->sTangents.push_back(tangent);
+ // bitangent is cross product of tangent and normal
+ float3 bitangent;
+ if ( vertex.hasNormal ) {
+ bitangent = tangent.cross(vertex.normal);
+ logOutput.Print(LOG_PIECE_DETAIL, "vertex bitangent %d: %f %f %f",vertexIndex, bitangent.x, bitangent.y,bitangent.z );
+ piece->tTangents.push_back(bitangent);
+ }
+ }
+ } else {
+ vertex.hasTangent = false;
+ }
+
+ // vertex texcoords
+ if (mesh->HasTextureCoords(0)) {
+ vertex.textureX = mesh->mTextureCoords[0][vertexIndex].x;
+ vertex.textureY = mesh->mTextureCoords[0][vertexIndex].y;
+ logOutput.Print(LOG_PIECE_DETAIL, "vertex texcoords %d: %f %f", vertexIndex, vertex.textureX, vertex.textureY );
+ }
+
+ mesh_vertex_mapping.push_back(piece->vertices.size());
+ piece->vertices.push_back(vertex);
+ }
+
+ // extract face data
+ if ( mesh->HasFaces() ) {
+ logOutput.Print(LOG_PIECE_DETAIL, "Processing faces for mesh %d (%d faces)", meshIndex, mesh->mNumFaces);
+ for ( unsigned faceIndex = 0; faceIndex < mesh->mNumFaces; faceIndex++ ) {
+ aiFace& face = mesh->mFaces[faceIndex];
+ // get the vertex belonging to the mesh
+ for ( unsigned vertexListID = 0; vertexListID < face.mNumIndices; vertexListID++ ) {
+ unsigned int vertexID = mesh_vertex_mapping[face.mIndices[vertexListID]];
+ logOutput.Print(LOG_PIECE_DETAIL, "face %d vertex %d", faceIndex, vertexID );
+ piece->vertexDrawOrder.push_back(vertexID);
+ }
+ }
+ }
+ }
+
+ // Check if piece is special (ie, used to set Spring model properties)
+ if (strcmp(node->mName.data, "SpringHeight") == 0) {
+ // Set the model height to this nodes Z value
+ if (!metaTable.KeyExists("height")) {
+ model->height = piece->offset.z;
+ logOutput.Print (LOG_MODEL, "Model height of %f set by special node 'SpringHeight'", model->height);
+ }
+ return NULL;
+ }
+ if (strcmp(node->mName.data, "SpringRadius") == 0) {
+ if (!metaTable.KeyExists("midpos")) {
+ model->relMidPos = float3(piece->offset.x, piece->offset.z, piece->offset.y); // Y and Z are swapped because this piece isn't rotated
+ logOutput.Print (LOG_MODEL, "Model midpos of (%f,%f,%f) set by special node 'SpringRadius'", model->relMidPos.x, model->relMidPos.y, model->relMidPos.z);
+ }
+ if (!metaTable.KeyExists("radius")) {
+ if (piece->maxs.x <= 0.00001f) {
+ model->radius = piece->scale.x; // the blender import script only sets the scale property
+ } else {
+ model->radius = piece->maxs.x; // use the transformed mesh extents
+ }
+ logOutput.Print (LOG_MODEL, "Model radius of %f set by special node 'SpringRadius'", model->radius);
+ }
+ return NULL;
+ }
+
+ // collision volume for piece (not sure about these coords)
+ const float3 cvScales = (piece->maxs) - (piece->mins);
+ const float3 cvOffset = (piece->maxs - piece->offset) + (piece->mins - piece->offset);
+ //const float3 cvOffset(piece->offset.x, piece->offset.y, piece->offset.z);
+ piece->colvol = new CollisionVolume("box", cvScales, cvOffset, CollisionVolume::COLVOL_HITTEST_CONT);
+
+ // Get parent name from metadata or model
+ if (pieceTable.KeyExists("parent")) {
+ piece->parentName = pieceTable.GetString("parent", "");
+ } else if (node->mParent) {
+ if (node->mParent->mParent) {
+ piece->parentName = std::string(node->mParent->mName.data);
+ } else { // my parent is the root, which gets renamed
+ piece->parentName = "root";
+ }
+ } else {
+ piece->parentName = "";
+ }
+
+ logOutput.Print(LOG_PIECE, "Loaded model piece: %s with %d meshes\n", piece->name.c_str(), node->mNumMeshes );
+
+ // Verbose logging of piece properties
+ logOutput.Print(LOG_PIECE, "piece->name: %s", piece->name.c_str());
+ logOutput.Print(LOG_PIECE, "piece->parent: %s", piece->parentName.c_str());
+
+ // Recursively process all child pieces
+ for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+ LoadPiece(model, node->mChildren[i], metaTable);
+ }
+
+ model->pieces[piece->name] = piece;
+ return piece;
+}
+
+// Because of metadata overrides we don't know the true hierarchy until all pieces have been loaded
+void CAssParser::BuildPieceHierarchy( S3DModel* model )
+{
+ // Loop through all pieces and create missing hierarchy info
+ ModelPieceMap::const_iterator end = model->pieces.end();
+ for (ModelPieceMap::const_iterator it = model->pieces.begin(); it != end; ++it)
+ {
+ S3DModelPiece* piece = it->second;
+ if (piece->name == "root") {
+ piece->parent = NULL;
+ model->SetRootPiece(piece);
+ } else if (piece->parentName != "") {
+ piece->parent = model->FindPiece(piece->parentName);
+ if (piece->parent == NULL) {
+ logOutput.Print( LOG_PIECE, "Error: Missing piece '%s' declared as parent of '%s'.\n", piece->parentName.c_str(), piece->name.c_str() );
+ } else {
+ piece->parent->childs.push_back(piece);
+ }
+ } else {
+ // A piece with no parent that isn't the root (orphan)
+ piece->parent = model->FindPiece("root");
+ if (piece->parent == NULL) {
+ logOutput.Print( LOG_PIECE, "Error: Missing root piece.\n" );
+ } else {
+ piece->parent->childs.push_back(piece);
+ }
+ }
+ }
+}
+
+// Iterate over the model and calculate its overall dimensions
+void CAssParser::CalculateMinMax( S3DModelPiece* piece )
+{
+ piece->goffset = piece->parent ? piece->parent->goffset + piece->offset : piece->offset;
+
+ // update model min/max extents
+ piece->model->mins.x = std::min(piece->goffset.x + piece->mins.x, piece->model->mins.x);
+ piece->model->mins.y = std::min(piece->goffset.y + piece->mins.y, piece->model->mins.y);
+ piece->model->mins.z = std::min(piece->goffset.z + piece->mins.z, piece->model->mins.z);
+ piece->model->maxs.x = std::max(piece->goffset.x + piece->maxs.x, piece->model->maxs.x);
+ piece->model->maxs.y = std::max(piece->goffset.y + piece->maxs.y, piece->model->maxs.y);
+ piece->model->maxs.z = std::max(piece->goffset.z + piece->maxs.z, piece->model->maxs.z);
+
+ // Repeat with childs
+ for (unsigned int i = 0; i < piece->childs.size(); i++) {
+ CalculateMinMax(piece->childs[i]);
+ }
+}
+
+// Calculate model radius from the min/max extents
+void CAssParser::CalculateRadius( S3DModel* model )
+{
+ model->radius = std::max(model->radius, model->maxs.x);
+ model->radius = std::max(model->radius, model->maxs.y);
+ model->radius = std::max(model->radius, model->maxs.z);
+}
+
+// Calculate model height from the min/max extents
+void CAssParser::CalculateHeight( S3DModel* model )
+{
+ model->height = model->maxs.z;
+}
+
+void DrawPiecePrimitive( const S3DModelPiece* o)
+{
+ if (o->isEmpty) {
+ return;
+ }
+ logOutput.Print(LOG_PIECE_DETAIL, "Compiling piece %s", o->name.c_str());
+ // Add GL commands to the pieces displaylist
+
+ const SAssPiece* so = static_cast<const SAssPiece*>(o);
+ const SAssVertex* sAssV = static_cast<const SAssVertex*>(&so->vertices[0]);
+
+
+ // pass the tangents as 3D texture coordinates
+ // (array elements are float3's, which are 12
+ // bytes in size and each represent a single
+ // xyz triple)
+ // TODO: test if we have this many texunits
+ // (if not, could only send the s-tangents)?
+
+ if (!so->sTangents.empty()) {
+ glClientActiveTexture(GL_TEXTURE5);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, sizeof(float3), &so->sTangents[0].x);
+ }
+ if (!so->tTangents.empty()) {
+ glClientActiveTexture(GL_TEXTURE6);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(3, GL_FLOAT, sizeof(float3), &so->tTangents[0].x);
+ }
+
+ glClientActiveTexture(GL_TEXTURE0);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(SAssVertex), &sAssV->textureX);
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(SAssVertex), &sAssV->pos.x);
+
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(SAssVertex), &sAssV->normal.x);
+
+ // since aiProcess_SortByPType is being used, we're sure we'll get only 1 type here, so combination check isn't needed, also anything more complex than triangles is being split thanks to aiProcess_Triangulate
+ glDrawElements(GL_TRIANGLES, so->vertexDrawOrder.size(), GL_UNSIGNED_INT, &so->vertexDrawOrder[0]);
+
+ if (!so->sTangents.empty()) {
+ glClientActiveTexture(GL_TEXTURE6);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ if (!so->tTangents.empty()) {
+ glClientActiveTexture(GL_TEXTURE5);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+
+ glClientActiveTexture(GL_TEXTURE0);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ logOutput.Print(LOG_PIECE_DETAIL, "Completed compiling piece %s", o->name.c_str());
+}
+
+void CAssParser::Draw( const S3DModelPiece* o) const
+{
+ DrawPiecePrimitive( o );
+}
+
+void SAssPiece::DrawList() const
+{
+ DrawPiecePrimitive(this);
+}
diff --git a/rts/Rendering/Models/AssParser.h b/rts/Rendering/Models/AssParser.h
new file mode 100755
index 0000000..e7a5b70
--- /dev/null
+++ b/rts/Rendering/Models/AssParser.h
@@ -0,0 +1,51 @@
+#ifndef ASSPARSER_H
+#define ASSPARSER_H
+
+#include <map>
+#include "IModelParser.h"
+#include "float3.h"
+
+struct aiNode;
+struct aiScene;
+class LuaTable;
+
+struct SAssVertex {
+ float3 pos;
+ float3 normal;
+ float textureX;
+ float textureY;
+ bool hasNormal;
+ bool hasTangent;
+};
+
+struct SAssPiece: public S3DModelPiece
+{
+public:
+ aiNode* node;
+
+ const float3& GetVertexPos(int idx) const { return vertices[idx].pos; }
+ void DrawList() const;
+ std::vector<SAssVertex> vertices;
+
+ std::vector<unsigned int> vertexDrawOrder;
+ // cannot store these in SAssVertex
+ std::vector<float3> sTangents; // == T(angent) dirs
+ std::vector<float3> tTangents; // == B(itangent) dirs
+};
+
+
+class CAssParser: public IModelParser
+{
+public:
+ S3DModel* Load(const std::string& modelFileName);
+ void Draw(const S3DModelPiece* o) const;
+
+private:
+ SAssPiece* LoadPiece(S3DModel* model, aiNode* node, const LuaTable& metaTable);
+ void BuildPieceHierarchy(S3DModel* model);
+ void CalculateRadius( S3DModel* model );
+ void CalculateHeight( S3DModel* model );
+ void CalculateMinMax( S3DModelPiece* piece );
+};
+
+#endif /* ASSPARSER_H */
diff --git a/rts/Rendering/Models/IModelParser.cpp b/rts/Rendering/Models/IModelParser.cpp
old mode 100644
new mode 100755
index aff59ad..e9513ee
--- a/rts/Rendering/Models/IModelParser.cpp
+++ b/rts/Rendering/Models/IModelParser.cpp
@@ -8,9 +8,12 @@
#include "IModelParser.h"
#include "3DModel.h"
+#include "3DModelLog.h"
#include "3DOParser.h"
#include "S3OParser.h"
#include "OBJParser.h"
+#include "AssParser.h"
+#include "assimp.hpp"
#include "Sim/Misc/CollisionVolume.h"
#include "Sim/Units/Unit.h"
#include "System/FileSystem/FileSystem.h"
@@ -18,10 +21,8 @@
#include "System/LogOutput.h"
#include "System/Exceptions.h"
-
C3DModelLoader* modelParser = NULL;
-
//////////////////////////////////////////////////////////////////////
// C3DModelLoader
//
@@ -31,7 +32,26 @@ C3DModelLoader::C3DModelLoader()
// file-extension should be lowercase
parsers["3do"] = new C3DOParser();
parsers["s3o"] = new CS3OParser();
- parsers["obj"] = new COBJParser();
+ //parsers["obj"] = new COBJParser(); // replaced by Assimp
+
+ // assimp library
+ CAssParser* unitassparser = new CAssParser();
+ std::string extensionlist;
+
+ Assimp::Importer importer;
+ importer.GetExtensionList(extensionlist); // get a ";" separated list of wildcards
+ char* charextensionlist = new char[extensionlist.size() +1];
+ strcpy (charextensionlist, extensionlist.c_str());
+ logOutput.Print("Assimp: Supported model formats: %s", extensionlist.c_str());
+ char* extensionchar = strtok( charextensionlist, ";" );
+ while( extensionchar )
+ {
+ std::string extension = extensionchar;
+ extension = extension.substr( 2 ); // strip wildcard and dot
+ parsers[extension] = unitassparser; // register extension
+ extensionchar = strtok( NULL, ";" );
+ }
+ delete charextensionlist;
}
@@ -48,11 +68,15 @@ C3DModelLoader::~C3DModelLoader()
cache.clear();
// delete parsers
+ std::set<IModelParser*> dedupe_parsers; // this is to avoid deleting the same parser twice, if it's assigned to multiple model formats
std::map<std::string, IModelParser*>::iterator pi;
for (pi = parsers.begin(); pi != parsers.end(); ++pi) {
+ if ( dedupe_parsers.count( pi->second ) != 0 ) continue;
+ dedupe_parsers.insert( pi->second );
delete pi->second;
}
parsers.clear();
+ dedupe_parsers.clear();
#if defined(USE_GML) && GML_ENABLE_SIM
createLists.clear();
@@ -67,7 +91,7 @@ inline int ModelExtToModelType(const std::string& ext) {
if (ext == "3do") { return MODELTYPE_3DO; }
if (ext == "s3o") { return MODELTYPE_S3O; }
if (ext == "obj") { return MODELTYPE_OBJ; }
- return -1;
+ return MODELTYPE_ASS; // FIXME: Return -1 if Assimp cant handle extension
}
inline S3DModelPiece* ModelTypeToModelPiece(int type) {
if (type == MODELTYPE_3DO) { return (new S3DOPiece()); }
diff --git a/rts/Rendering/Models/WorldObjectModelRenderer.cpp b/rts/Rendering/Models/WorldObjectModelRenderer.cpp
old mode 100644
new mode 100755
index 778f11b..bd8237b
--- a/rts/Rendering/Models/WorldObjectModelRenderer.cpp
+++ b/rts/Rendering/Models/WorldObjectModelRenderer.cpp
@@ -14,6 +14,7 @@ IWorldObjectModelRenderer* IWorldObjectModelRenderer::GetInstance(int modelType)
case MODELTYPE_3DO: { return (new WorldObjectModelRenderer3DO()); } break;
case MODELTYPE_S3O: { return (new WorldObjectModelRendererS3O()); } break;
case MODELTYPE_OBJ: { return (new WorldObjectModelRendererOBJ()); } break;
+ case MODELTYPE_ASS: { return (new WorldObjectModelRendererASS()); } break;
default: { return (new IWorldObjectModelRenderer(MODELTYPE_OTHER)); } break;
}
}
@@ -226,7 +227,18 @@ void WorldObjectModelRendererOBJ::PopRenderState()
// WRITEME
}
-
+void WorldObjectModelRendererASS::PushRenderState()
+{
+ #if (WORLDOBJECT_MODEL_RENDERER_DEBUG == 1)
+ #endif
+ // WRITEME
+}
+void WorldObjectModelRendererASS::PopRenderState()
+{
+ #if (WORLDOBJECT_MODEL_RENDERER_DEBUG == 1)
+ #endif
+ // WRITEME
+}
void WorldObjectModelRendererS3O::DrawModel(const CUnit* u)
{
diff --git a/rts/Rendering/Models/WorldObjectModelRenderer.h b/rts/Rendering/Models/WorldObjectModelRenderer.h
old mode 100644
new mode 100755
index 386da99..11a7644
--- a/rts/Rendering/Models/WorldObjectModelRenderer.h
+++ b/rts/Rendering/Models/WorldObjectModelRenderer.h
@@ -117,4 +117,11 @@ public:
void PopRenderState();
};
+class WorldObjectModelRendererASS: public IWorldObjectModelRenderer {
+public:
+ WorldObjectModelRendererASS(): IWorldObjectModelRenderer(MODELTYPE_ASS) {}
+ void PushRenderState();
+ void PopRenderState();
+};
+
#endif
diff --git a/rts/Rendering/ProjectileDrawer.cpp b/rts/Rendering/ProjectileDrawer.cpp
old mode 100644
new mode 100755
diff --git a/rts/Rendering/Textures/Bitmap.cpp b/rts/Rendering/Textures/Bitmap.cpp
old mode 100644
new mode 100755
index 2445c31..0e31ad6
--- a/rts/Rendering/Textures/Bitmap.cpp
+++ b/rts/Rendering/Textures/Bitmap.cpp
@@ -282,9 +282,9 @@ bool CBitmap::LoadGrayscale(const std::string& filename)
delete[] mem;
mem = new unsigned char[xsize * ysize];
memcpy(mem, ilGetData(), xsize * ysize);
-
+
ilDeleteImages(1, &ImageName);
-
+
return true;
}
@@ -738,6 +738,18 @@ void CBitmap::InvertColors()
}
+void CBitmap::InvertAlpha()
+{
+ if (type != BitmapTypeStandardRGBA) return; // Don't try to invert DDS
+ for (int y = 0; y < ysize; ++y) {
+ for (int x = 0; x < xsize; ++x) {
+ const int base = ((y * xsize) + x) * 4;
+ mem[base + 3] = 0xFF - mem[base + 3];
+ }
+ }
+}
+
+
void CBitmap::GrayScale()
{
if (type != BitmapTypeStandardRGBA) {
@@ -786,6 +798,7 @@ void CBitmap::Tint(const float tint[3])
void CBitmap::ReverseYAxis()
{
+ if (type != BitmapTypeStandardRGBA) return; // don't try to flip DDS
unsigned char* tmpLine = new unsigned char[channels * xsize];
for (int y=0; y < (ysize / 2); ++y) {
const int pixelLow = (((y ) * xsize) + 0) * channels;
diff --git a/rts/Rendering/Textures/Bitmap.h b/rts/Rendering/Textures/Bitmap.h
old mode 100644
new mode 100755
index 9b1577b..9d984f9
--- a/rts/Rendering/Textures/Bitmap.h
+++ b/rts/Rendering/Textures/Bitmap.h
@@ -83,6 +83,7 @@ public:
CBitmap CreateRescaled(int newx, int newy) const;
void ReverseYAxis();
void InvertColors();
+ void InvertAlpha();
void GrayScale();
void Tint(const float tint[3]);
};
diff --git a/rts/Rendering/Textures/S3OTextureHandler.cpp b/rts/Rendering/Textures/S3OTextureHandler.cpp
old mode 100644
new mode 100755
index 857406b..abb6a02
--- a/rts/Rendering/Textures/S3OTextureHandler.cpp
+++ b/rts/Rendering/Textures/S3OTextureHandler.cpp
@@ -20,6 +20,15 @@
#include "System/Exceptions.h"
#include "System/LogOutput.h"
+static CLogSubsystem LOG_TEXTURE("Texture");
+
+// The S3O texture handler uses two textures.
+// The first contains diffuse color (RGB) and teamcolor (A)
+// The second contains glow (R), reflectivity (G) and 1-bit Alpha (A).
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
CS3OTextureHandler* texturehandlerS3O = NULL;
@@ -52,6 +61,10 @@ void CS3OTextureHandler::Update() {
int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model)
{
GML_STDMUTEX_LOCK(model); // LoadS3OTextureNow
+ logOutput.Print(LOG_TEXTURE, "Load S3O texture now (Flip Y Axis: %s, Invert Team Alpha: %s)",
+ model->flipTexY ? "yes" : "no",
+ model->invertTexAlpha ? "yes" : "no"
+ );
const string totalName = model->tex1 + model->tex2;
@@ -74,6 +87,8 @@ int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model)
tex1bm.mem[2] = 0;
tex1bm.mem[3] = 255;
}
+ if (model->flipTexY) tex1bm.ReverseYAxis();
+ if (model->invertTexAlpha) tex1bm.InvertAlpha();
tex.num = s3oTextures.size();
tex.tex1 = tex1bm.CreateTexture(true);
@@ -92,6 +107,7 @@ int CS3OTextureHandler::LoadS3OTextureNow(const S3DModel* model)
tex2bm.mem[2] = 0; // unused
tex2bm.mem[3] = 255; // team-color
}
+ if (model->flipTexY) tex2bm.ReverseYAxis();
tex.tex2 = tex2bm.CreateTexture(true);
tex.tex2SizeX = tex2bm.xsize;
diff --git a/rts/Rendering/Textures/S3OTextureHandler.h b/rts/Rendering/Textures/S3OTextureHandler.h
old mode 100644
new mode 100755
diff --git a/rts/Rendering/UnitDrawer.cpp b/rts/Rendering/UnitDrawer.cpp
old mode 100644
new mode 100755
index 9dc973b..f6ca177
--- a/rts/Rendering/UnitDrawer.cpp
+++ b/rts/Rendering/UnitDrawer.cpp
@@ -519,7 +519,7 @@ void CUnitDrawer::DrawOpaqueUnits(int modelType, const CUnit* excludeUnit, bool
UnitSet::const_iterator unitSetIt;
for (unitBinIt = unitBin.begin(); unitBinIt != unitBin.end(); ++unitBinIt) {
- if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ) {
+ if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ || modelType == MODELTYPE_ASS) {
texturehandlerS3O->SetS3oTexture(unitBinIt->first);
}
@@ -779,13 +779,13 @@ inline void CUnitDrawer::DrawOpaqueUnitShadow(CUnit* unit) {
#define S3O_TEX(model) \
texturehandlerS3O->GetS3oTex(model->textureType)
#define PUSH_SHADOW_TEXTURE_STATE(model) \
- if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ) { \
+ if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ || model->type == MODELTYPE_ASS) { \
glActiveTexture(GL_TEXTURE0); \
glEnable(GL_TEXTURE_2D); \
glBindTexture(GL_TEXTURE_2D, S3O_TEX(model)->tex2); \
}
#define POP_SHADOW_TEXTURE_STATE(model) \
- if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ) { \
+ if (model->type == MODELTYPE_S3O || model->type == MODELTYPE_OBJ || model->type == MODELTYPE_ASS) { \
glBindTexture(GL_TEXTURE_2D, 0); \
glDisable(GL_TEXTURE_2D); \
glActiveTexture(GL_TEXTURE0); \
@@ -1042,7 +1042,7 @@ void CUnitDrawer::DrawCloakedUnitsHelper(int modelType)
// cloaked units
for (UnitRenderBinIt it = unitBin.begin(); it != unitBin.end(); ++it) {
- if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ) {
+ if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ || modelType == MODELTYPE_ASS) {
texturehandlerS3O->SetS3oTexture(it->first);
}
@@ -1099,7 +1099,7 @@ inline void CUnitDrawer::DrawCloakedUnit(CUnit* unit, int modelType, bool drawGh
glTranslatef3(unit->pos);
glRotatef(unit->buildFacing * 90.0f, 0, 1, 0);
- if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ) {
+ if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ || modelType == MODELTYPE_ASS) {
// the units in liveGhostedBuildings[modelType] are not
// sorted by textureType, but we cannot merge them with
// cloakedModelRenderers[modelType] since they are not
@@ -1183,7 +1183,7 @@ void CUnitDrawer::DrawGhostedBuildings(int modelType)
glTranslatef3((*it)->pos);
glRotatef((*it)->facing * 90.0f, 0, 1, 0);
- if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ)
+ if (modelType == MODELTYPE_S3O || modelType == MODELTYPE_OBJ || modelType == MODELTYPE_ASS)
texturehandlerS3O->SetS3oTexture((*it)->model->textureType);
SetTeamColour((*it)->team, cloakAlpha1);
@@ -1559,7 +1559,7 @@ void CUnitDrawer::DrawIndividual(CUnit* unit)
SetupForUnitDrawing();
opaqueModelRenderers[MDL_TYPE(unit)]->PushRenderState();
- if (MDL_TYPE(unit) == MODELTYPE_S3O || MDL_TYPE(unit) == MODELTYPE_OBJ) {
+ if (MDL_TYPE(unit) == MODELTYPE_S3O || MDL_TYPE(unit) == MODELTYPE_OBJ || MDL_TYPE(unit) == MODELTYPE_ASS) {
texturehandlerS3O->SetS3oTexture(TEX_TYPE(unit));
}
@@ -1599,7 +1599,8 @@ void CUnitDrawer::DrawBuildingSample(const UnitDef* unitdef, int side, float3 po
texturehandler3DO->Set3doAtlases();
} break;
case MODELTYPE_S3O:
- case MODELTYPE_OBJ: {
+ case MODELTYPE_OBJ:
+ case MODELTYPE_ASS: {
texturehandlerS3O->SetS3oTexture(model->textureType);
} break;
default: {
@@ -1987,7 +1988,7 @@ inline void CUnitDrawer::UpdateUnitIconState(CUnit* unit) {
#ifdef USE_GML
if (showHealthBars && !unit->noDraw &&
(unit->health < unit->maxHealth || unit->paralyzeDamage > 0.0f || unit->limExperience > 0.0f ||
- unit->beingBuilt || unit->stockpileWeapon || unit->group) &&
+ unit->beingBuilt || unit->stockpileWeapon || unit->group) &&
((unit->pos - camera->pos).SqLength() < (unitDrawDistSqr * 500.0f)))
drawStat.insert(unit);
#endif
diff --git a/rts/Sim/Misc/GlobalConstants.h b/rts/Sim/Misc/GlobalConstants.h
index 78c5305..6006a4e 100644
--- a/rts/Sim/Misc/GlobalConstants.h
+++ b/rts/Sim/Misc/GlobalConstants.h
@@ -39,6 +39,13 @@ const int UNIT_SLOWUPDATE_RATE = 16;
const int TEAM_SLOWUPDATE_RATE = 32;
/**
+ * @brief max view range
+ *
+ * Defines the maximum view range as 8000
+ */
+const int MAX_VIEW_RANGE = 8000;
+
+/**
* @brief max teams
*
* Defines the maximum number of teams
@@ -56,10 +63,9 @@ const int MAX_PLAYERS = 251;
/**
* @brief max units
*
- * Defines the absolute global maximum number of units allowed to exist in a game.
- * MUST be <= SHRT_MAX ((1 << ((sizeof(short) * 8) - 1)) - 1) because current net
- * code transmits unit ID's as signed shorts. The effective global unit limit is
- * stored in UnitHandler::maxUnits and is always clamped to this value.
+ * Defines the maximum number of untis that may be set as maximum for a game.
+ * The real maximum of the game is stored in uh->maxUnits,
+ * and may not be higher then this value.
*/
const int MAX_UNITS = 32000;
@@ -69,6 +75,13 @@ const int MAX_UNITS = 32000;
const int MAX_WEAPONS_PER_UNIT = 32;
/**
+ * @brief near plane
+ *
+ * Defines the near plane as 2.8f
+ */
+const float NEAR_PLANE = 2.8f;
+
+/**
* @brief randint max
*
* Defines the maximum random integer as 0x7fff
diff --git a/rts/Sim/Misc/Team.cpp b/rts/Sim/Misc/Team.cpp
index 407c17f..3b84cc6 100644
--- a/rts/Sim/Misc/Team.cpp
+++ b/rts/Sim/Misc/Team.cpp
@@ -27,52 +27,56 @@
CR_BIND(CTeam,);
CR_REG_METADATA(CTeam, (
- // from CTeamBase
- CR_MEMBER(leader),
- CR_MEMBER(color),
- CR_MEMBER(incomeMultiplier),
- CR_MEMBER(side),
- CR_MEMBER(startPos),
- CR_MEMBER(teamStartNum),
- CR_MEMBER(teamAllyteam),
- // CR_MEMBER(customValues),
- // from CTeam
- CR_MEMBER(teamNum),
- CR_MEMBER(isDead),
- CR_MEMBER(gaia),
- CR_MEMBER(origColor),
- CR_MEMBER(units),
- CR_MEMBER(metal),
- CR_MEMBER(energy),
- CR_MEMBER(metalPull),
- CR_MEMBER(prevMetalPull),
- CR_MEMBER(metalIncome),
- CR_MEMBER(prevMetalIncome),
- CR_MEMBER(metalExpense),
- CR_MEMBER(prevMetalExpense),
- CR_MEMBER(energyPull),
- CR_MEMBER(prevEnergyPull),
- CR_MEMBER(energyIncome),
- CR_MEMBER(prevEnergyIncome),
- CR_MEMBER(energyExpense),
- CR_MEMBER(prevEnergyExpense),
- CR_MEMBER(metalStorage),
- CR_MEMBER(energyStorage),
- CR_MEMBER(metalShare),
- CR_MEMBER(energyShare),
- CR_MEMBER(delayedMetalShare),
- CR_MEMBER(delayedEnergyShare),
- CR_MEMBER(metalSent),
- CR_MEMBER(metalReceived),
- CR_MEMBER(energySent),
- CR_MEMBER(energyReceived),
- //CR_MEMBER(currentStats),
- CR_MEMBER(nextHistoryEntry),
- //CR_MEMBER(statHistory),
- CR_MEMBER(modParams),
- CR_MEMBER(modParamsMap),
- CR_RESERVED(64)
-));
+// from CTeamBase
+ CR_MEMBER(leader),
+ CR_MEMBER(color),
+ CR_MEMBER(incomeMultiplier),
+ CR_MEMBER(side),
+ CR_MEMBER(startPos),
+ CR_MEMBER(teamStartNum),
+ CR_MEMBER(teamAllyteam),
+// CR_MEMBER(customValues),
+// from CTeam
+ CR_MEMBER(teamNum),
+ CR_MEMBER(isDead),
+ CR_MEMBER(gaia),
+ CR_MEMBER(origColor),
+ CR_MEMBER(units),
+ CR_MEMBER(metal),
+ CR_MEMBER(energy),
+ CR_MEMBER(metalPull),
+ CR_MEMBER(prevMetalPull),
+ CR_MEMBER(metalIncome),
+ CR_MEMBER(prevMetalIncome),
+ CR_MEMBER(metalExpense),
+ CR_MEMBER(prevMetalExpense),
+ CR_MEMBER(metalUpkeep),
+ CR_MEMBER(prevMetalUpkeep),
+ CR_MEMBER(energyPull),
+ CR_MEMBER(prevEnergyPull),
+ CR_MEMBER(energyIncome),
+ CR_MEMBER(prevEnergyIncome),
+ CR_MEMBER(energyExpense),
+ CR_MEMBER(prevEnergyExpense),
+ CR_MEMBER(energyUpkeep),
+ CR_MEMBER(prevEnergyUpkeep),
+ CR_MEMBER(metalStorage),
+ CR_MEMBER(energyStorage),
+ CR_MEMBER(metalShare),
+ CR_MEMBER(energyShare),
+ CR_MEMBER(delayedMetalShare),
+ CR_MEMBER(delayedEnergyShare),
+ CR_MEMBER(metalSent),
+ CR_MEMBER(metalReceived),
+ CR_MEMBER(energySent),
+ CR_MEMBER(energyReceived),
+ //CR_MEMBER(currentStats),
+ CR_MEMBER(nextHistoryEntry),
+ //CR_MEMBER(statHistory),
+ CR_MEMBER(modParams),
+ CR_MEMBER(modParamsMap),
+ CR_RESERVED(64)
+ ));
//////////////////////////////////////////////////////////////////////
@@ -88,9 +92,11 @@ CTeam::CTeam() :
metalPull(0.0f), prevMetalPull(0.0f),
metalIncome(0.0f), prevMetalIncome(0.0f),
metalExpense(0.0f), prevMetalExpense(0.0f),
+ metalUpkeep(0.0f), prevMetalUpkeep(0.0f),
energyPull(0.0f), prevEnergyPull(0.0f),
energyIncome(0.0f), prevEnergyIncome(0.0f),
energyExpense(0.0f), prevEnergyExpense(0.0f),
+ energyUpkeep(0.0f), prevEnergyUpkeep(0.0f),
metalStorage(1000000),
energyStorage(1000000),
metalShare(0.99f),
@@ -114,10 +120,14 @@ CTeam::CTeam() :
}
+CTeam::~CTeam()
+{
+}
+
bool CTeam::UseMetal(float amount)
{
- if (metal >= amount) {
+ if ((metal - (prevMetalUpkeep * 10)) >= amount) {
metal -= amount;
metalExpense += amount;
return true;
@@ -125,9 +135,10 @@ bool CTeam::UseMetal(float amount)
return false;
}
+
bool CTeam::UseEnergy(float amount)
{
- if (energy >= amount) {
+ if ((energy - (prevEnergyUpkeep * 10)) >= amount) {
energy -= amount;
energyExpense += amount;
return true;
@@ -136,6 +147,29 @@ bool CTeam::UseEnergy(float amount)
}
+bool CTeam::UseMetalUpkeep(float amount)
+{
+ if (metal >= amount) {
+ metal -= amount;
+ metalExpense += amount;
+ metalUpkeep += amount;
+ return true;
+ }
+ return false;
+}
+
+
+bool CTeam::UseEnergyUpkeep(float amount)
+{
+ if (energy >= amount) {
+ energy -= amount;
+ energyExpense += amount;
+ energyUpkeep += amount;
+ return true;
+ }
+ return false;
+}
+
void CTeam::AddMetal(float amount, bool useIncomeMultiplier)
{
@@ -143,24 +177,23 @@ void CTeam::AddMetal(float amount, bool useIncomeMultiplier)
metal += amount;
metalIncome += amount;
if (metal > metalStorage) {
- delayedMetalShare += (metal - metalStorage);
+ delayedMetalShare += metal - metalStorage;
metal = metalStorage;
}
}
+
void CTeam::AddEnergy(float amount, bool useIncomeMultiplier)
{
if (useIncomeMultiplier) { amount *= GetIncomeMultiplier(); }
energy += amount;
energyIncome += amount;
if (energy > energyStorage) {
- delayedEnergyShare += (energy - energyStorage);
+ delayedEnergyShare += energy - energyStorage;
energy = energyStorage;
}
}
-
-
void CTeam::GiveEverythingTo(const unsigned toTeam)
{
CTeam* target = teamHandler->Team(toTeam);
@@ -220,6 +253,10 @@ void CTeam::Died()
eventHandler.TeamDied(teamNum);
}
+void CTeam::StartposMessage(const float3& pos)
+{
+ startPos = pos;
+}
CTeam& CTeam::operator=(const TeamBase& base)
{
@@ -227,36 +264,43 @@ CTeam& CTeam::operator=(const TeamBase& base)
return *this;
}
-
-
-void CTeam::ResetResourceState()
+void CTeam::ResetFrameVariables()
{
- // reset all state variables that were
- // potentially modified during the last
- // <TEAM_SLOWUPDATE_RATE> frames
- prevMetalPull = metalPull; metalPull = 0.0f;
- prevMetalIncome = metalIncome; metalIncome = 0.0f;
- prevMetalExpense = metalExpense; metalExpense = 0.0f;
- prevEnergyPull = energyPull; energyPull = 0.0f;
- prevEnergyIncome = energyIncome; energyIncome = 0.0f;
- prevEnergyExpense = energyExpense; energyExpense = 0.0f;
-
- // reset the sharing accumulators
- metalSent = 0.0f; metalReceived = 0.0f;
- energySent = 0.0f; energyReceived = 0.0f;
+ prevMetalPull = metalPull;
+ prevMetalIncome = metalIncome;
+ prevMetalExpense = metalExpense;
+ prevMetalUpkeep = metalUpkeep;
+ prevEnergyPull = energyPull;
+ prevEnergyIncome = energyIncome;
+ prevEnergyExpense = energyExpense;
+ prevEnergyUpkeep = energyUpkeep;
+
+ metalPull = 0;
+ metalIncome = 0;
+ metalExpense = 0;
+ metalUpkeep = 0;
+ energyPull = 0;
+ energyIncome = 0;
+ energyExpense = 0;
+ energyUpkeep = 0;
+
+ metalSent = 0;
+ energySent = 0;
+ metalReceived = 0;
+ energyReceived = 0;
}
void CTeam::SlowUpdate()
{
- float eShare = 0.0f, mShare = 0.0f;
+ currentStats->metalProduced += prevMetalIncome;
+ currentStats->energyProduced += prevEnergyIncome;
+ currentStats->metalUsed += prevMetalUpkeep + prevMetalExpense;
+ currentStats->energyUsed += prevEnergyUpkeep + prevEnergyExpense;
- // calculate the total amount of resources that all
- // (allied) teams can collectively receive through
- // sharing
+ float eShare = 0.0f, mShare = 0.0f;
for (int a = 0; a < teamHandler->ActiveTeams(); ++a) {
- CTeam* team = teamHandler->Team(a);
-
if ((a != teamNum) && (teamHandler->AllyTeam(teamNum) == teamHandler->AllyTeam(a))) {
+ CTeam* team = teamHandler->Team(a);
if (team->isDead)
continue;
@@ -265,25 +309,21 @@ void CTeam::SlowUpdate()
}
}
+ metal += delayedMetalShare;
+ energy += delayedEnergyShare;
+ delayedMetalShare = 0;
+ delayedEnergyShare = 0;
- currentStats->metalProduced += prevMetalIncome;
- currentStats->energyProduced += prevEnergyIncome;
- currentStats->metalUsed += prevMetalExpense;
- currentStats->energyUsed += prevEnergyExpense;
-
- metal += delayedMetalShare; delayedMetalShare = 0.0f;
- energy += delayedEnergyShare; delayedEnergyShare = 0.0f;
-
-
- // calculate how much we can share in total (any and all excess resources)
const float eExcess = std::max(0.0f, energy - (energyStorage * energyShare));
const float mExcess = std::max(0.0f, metal - (metalStorage * metalShare));
float de = 0.0f, dm = 0.0f;
- if (eShare > 0.0f) { de = std::min(1.0f, eExcess / eShare); }
- if (mShare > 0.0f) { dm = std::min(1.0f, mExcess / mShare); }
-
- // now evenly distribute our excess resources among allied teams
+ if (eShare > 0.0f) {
+ de = std::min(1.0f, eExcess/eShare);
+ }
+ if (mShare > 0.0f) {
+ dm = std::min(1.0f, mExcess/mShare);
+ }
for (int a = 0; a < teamHandler->ActiveTeams(); ++a) {
if ((a != teamNum) && (teamHandler->AllyTeam(teamNum) == teamHandler->AllyTeam(a))) {
CTeam* team = teamHandler->Team(a);
@@ -291,19 +331,23 @@ void CTeam::SlowUpdate()
continue;
const float edif = std::max(0.0f, (team->energyStorage * 0.99f) - team->energy) * de;
- const float mdif = std::max(0.0f, (team->metalStorage * 0.99f) - team->metal) * dm;
+ energy -= edif;
+ energySent += edif;
+ currentStats->energySent += edif;
+ team->energy += edif;
+ team->energyReceived += edif;
+ team->currentStats->energyReceived += edif;
- energy -= edif; team->energy += edif;
- energySent += edif; team->energyReceived += edif;
- metal -= mdif; team->metal += mdif;
- metalSent += mdif; team->metalReceived += mdif;
-
- currentStats->energySent += edif; team->currentStats->energyReceived += edif;
- currentStats->metalSent += mdif; team->currentStats->metalReceived += mdif;
+ const float mdif = std::max(0.0f, (team->metalStorage * 0.99f) - team->metal) * dm;
+ metal -= mdif;
+ metalSent += mdif;
+ currentStats->metalSent += mdif;
+ team->metal += mdif;
+ team->metalReceived += mdif;
+ team->currentStats->metalReceived += mdif;
}
}
- // clamp resource levels to storage capacity
if (metal > metalStorage) {
currentStats->metalExcess += (metal - metalStorage);
metal = metalStorage;
@@ -325,10 +369,11 @@ void CTeam::SlowUpdate()
nextHistoryEntry = gs->frameNum + statsFrames;
currentStats->frame = nextHistoryEntry;
}
+
}
-void CTeam::AddUnit(CUnit* unit, AddType type)
+void CTeam::AddUnit(CUnit* unit,AddType type)
{
units.insert(unit);
switch (type) {
@@ -348,7 +393,7 @@ void CTeam::AddUnit(CUnit* unit, AddType type)
}
-void CTeam::RemoveUnit(CUnit* unit, RemoveType type)
+void CTeam::RemoveUnit(CUnit* unit,RemoveType type)
{
units.erase(unit);
switch (type) {
diff --git a/rts/Sim/Misc/Team.h b/rts/Sim/Misc/Team.h
index fdd6bcf..f390cbc 100644
--- a/rts/Sim/Misc/Team.h
+++ b/rts/Sim/Misc/Team.h
@@ -21,20 +21,28 @@ class CTeam : public TeamBase, private boost::noncopyable //! cannot allow shall
CR_DECLARE(CTeam);
public:
CTeam();
+ ~CTeam();
+public:
- void ResetResourceState();
+ /**
+ * This has to be called for every team before SlowUpdates start,
+ * otherwise values get overwritten.
+ */
+ void ResetFrameVariables();
void SlowUpdate();
void AddMetal(float amount, bool useIncomeMultiplier = true);
void AddEnergy(float amount, bool useIncomeMultiplier = true);
bool UseEnergy(float amount);
bool UseMetal(float amount);
+ bool UseEnergyUpkeep(float amount);
+ bool UseMetalUpkeep(float amount);
void GiveEverythingTo(const unsigned toTeam);
void Died();
- void StartposMessage(const float3& pos) { startPos = pos; }
+ void StartposMessage(const float3& pos);
CTeam& operator=(const TeamBase& base);
@@ -71,10 +79,12 @@ public:
float metalPull, prevMetalPull;
float metalIncome, prevMetalIncome;
float metalExpense, prevMetalExpense;
+ float metalUpkeep, prevMetalUpkeep;
float energyPull, prevEnergyPull;
float energyIncome, prevEnergyIncome;
float energyExpense, prevEnergyExpense;
+ float energyUpkeep, prevEnergyUpkeep;
SyncedFloat metalStorage, energyStorage;
diff --git a/rts/Sim/Misc/TeamHandler.cpp b/rts/Sim/Misc/TeamHandler.cpp
index 0bbbf99..04e5bd0 100644
--- a/rts/Sim/Misc/TeamHandler.cpp
+++ b/rts/Sim/Misc/TeamHandler.cpp
@@ -25,7 +25,7 @@ CR_REG_METADATA(CTeamHandler, (
));
-CTeamHandler* teamHandler = NULL;
+CTeamHandler* teamHandler;
CTeamHandler::CTeamHandler():
@@ -88,12 +88,12 @@ void CTeamHandler::LoadFromSetup(const CGameSetup* setup)
void CTeamHandler::GameFrame(int frameNum)
{
- if ((frameNum % TEAM_SLOWUPDATE_RATE) == 0) {
+ if (!(frameNum & (TEAM_SLOWUPDATE_RATE-1))) {
for (int a = 0; a < ActiveTeams(); ++a) {
- teams[a]->ResetResourceState();
+ Team(a)->ResetFrameVariables();
}
for (int a = 0; a < ActiveTeams(); ++a) {
- teams[a]->SlowUpdate();
+ Team(a)->SlowUpdate();
}
}
}
diff --git a/rts/Sim/MoveTypes/AAirMoveType.cpp b/rts/Sim/MoveTypes/AAirMoveType.cpp
index 5cabd4e..67943ce 100644
--- a/rts/Sim/MoveTypes/AAirMoveType.cpp
+++ b/rts/Sim/MoveTypes/AAirMoveType.cpp
@@ -39,9 +39,9 @@ AAirMoveType::AAirMoveType(CUnit* unit) :
wantedHeight(80.0f),
collide(true),
useSmoothMesh(false),
- autoLand(true),
lastColWarning(NULL),
lastColWarningType(0),
+ autoLand(true),
lastFuelUpdateFrame(0)
{
useHeading = false;
diff --git a/rts/Sim/MoveTypes/AirMoveType.cpp b/rts/Sim/MoveTypes/AirMoveType.cpp
index f0aade2..bc09cbf 100644
--- a/rts/Sim/MoveTypes/AirMoveType.cpp
+++ b/rts/Sim/MoveTypes/AirMoveType.cpp
@@ -1088,7 +1088,7 @@ void CAirMoveType::SetState(AAirMoveType::AircraftState state)
-void CAirMoveType::ImpulseAdded(const float3&)
+void CAirMoveType::ImpulseAdded(void)
{
if (aircraftState == AIRCRAFT_FLYING) {
owner->speed += owner->residualImpulse;
diff --git a/rts/Sim/MoveTypes/AirMoveType.h b/rts/Sim/MoveTypes/AirMoveType.h
index 2f70cab..bc3db18 100644
--- a/rts/Sim/MoveTypes/AirMoveType.h
+++ b/rts/Sim/MoveTypes/AirMoveType.h
@@ -32,7 +32,7 @@ public:
float engine, const float3& engineVector);
void SetState(AircraftState state);
void UpdateTakeOff(float wantedHeight);
- void ImpulseAdded(const float3&);
+ void ImpulseAdded();
float3 FindLandingPos() const;
void DependentDied(CObject* o);
diff --git a/rts/Sim/MoveTypes/GroundMoveType.cpp b/rts/Sim/MoveTypes/GroundMoveType.cpp
index 58e8670..984aa85 100644
--- a/rts/Sim/MoveTypes/GroundMoveType.cpp
+++ b/rts/Sim/MoveTypes/GroundMoveType.cpp
@@ -81,11 +81,12 @@ CR_REG_METADATA(CGroundMoveType, (
CR_MEMBER(canReverse),
CR_MEMBER(useMainHeading),
+ CR_MEMBER(skidRotSpeed),
+
CR_MEMBER(waypointDir),
CR_MEMBER(flatFrontDir),
CR_MEMBER(skidRotVector),
- CR_MEMBER(skidRotSpeed),
CR_MEMBER(skidRotSpeed2),
CR_MEMBER(skidRotPos2),
CR_ENUM_MEMBER(oldPhysState),
@@ -110,10 +111,10 @@ CGroundMoveType::CGroundMoveType(CUnit* owner):
maxReverseSpeed(0.0f),
wantedSpeed(0.0f),
currentSpeed(0.0f),
- requestedSpeed(0.0f),
deltaSpeed(0.0f),
deltaHeading(0),
+ flatFrontDir(0.0f, 0.0, 1.0f),
pathId(0),
goalRadius(0),
@@ -121,7 +122,15 @@ CGroundMoveType::CGroundMoveType(CUnit* owner):
nextWaypoint(ZeroVector),
atGoal(false),
haveFinalWaypoint(false),
+
+ requestedSpeed(0.0f),
currentDistanceToWaypoint(0),
+ pathRequestDelay(0),
+ numIdlingUpdates(0),
+ numIdlingSlowUpdates(0),
+
+ nextDeltaSpeedUpdate(0),
+ nextObstacleAvoidanceUpdate(0),
skidding(false),
flying(false),
@@ -130,22 +139,12 @@ CGroundMoveType::CGroundMoveType(CUnit* owner):
canReverse(owner->unitDef->rSpeed > 0.0f),
useMainHeading(false),
- skidRotVector(UpVector),
skidRotSpeed(0.0f),
+ skidRotVector(UpVector),
skidRotSpeed2(0.0f),
skidRotPos2(0.0f),
oldPhysState(CSolidObject::OnGround),
-
- flatFrontDir(0.0f, 0.0, 1.0f),
- mainHeadingPos(ZeroVector),
-
- nextDeltaSpeedUpdate(0),
- nextObstacleAvoidanceUpdate(0),
-
- pathRequestDelay(0),
-
- numIdlingUpdates(0),
- numIdlingSlowUpdates(0)
+ mainHeadingPos(0.0f, 0.0f, 0.0f)
{
if (owner) {
moveSquareX = owner->pos.x / MIN_WAYPOINT_DISTANCE;
@@ -560,17 +559,23 @@ void CGroundMoveType::ChangeHeading(short wantedHeading) {
tracefile << "unit " << owner->id << " changed heading to " << heading << " from " << _oldheading << " (wantedHeading: " << wantedHeading << ")\n";
#endif
- owner->SetDirectionFromHeading();
+ owner->frontdir = GetVectorFromHeading(heading);
+ if (owner->upright) {
+ owner->updir = UpVector;
+ owner->rightdir = owner->frontdir.cross(owner->updir);
+ } else {
+ owner->updir = ground->GetNormal(owner->pos.x, owner->pos.z);
+ owner->rightdir = owner->frontdir.cross(owner->updir);
+ owner->rightdir.Normalize();
+ owner->frontdir = owner->updir.cross(owner->rightdir);
+ }
flatFrontDir = owner->frontdir;
flatFrontDir.y = 0.0f;
flatFrontDir.Normalize();
}
-
-
-
-void CGroundMoveType::ImpulseAdded(const float3&)
+void CGroundMoveType::ImpulseAdded()
{
if (owner->beingBuilt || owner->unitDef->movedata->moveType == MoveData::Ship_Move)
return;
@@ -583,34 +588,25 @@ void CGroundMoveType::ImpulseAdded(const float3&)
impulse = ZeroVector;
}
- const float3& groundNormal = ground->GetNormal(owner->pos.x, owner->pos.z);
- const float groundImpulseScale = impulse.dot(groundNormal);
+ float3 groundNormal = ground->GetNormal(owner->pos.x, owner->pos.z);
+
+ if (impulse.dot(groundNormal) < 0)
+ impulse -= groundNormal * impulse.dot(groundNormal);
- if (groundImpulseScale < 0.0f)
- impulse -= (groundNormal * groundImpulseScale);
+ const float sqstrength = impulse.SqLength();
- if (impulse.SqLength() > 9.0f || groundImpulseScale > 0.3f) {
+ if (sqstrength > 9 || impulse.dot(groundNormal) > 0.3f) {
skidding = true;
speed += impulse;
impulse = ZeroVector;
- // FIXME: impulse should not cause a _random_ rotational component
skidRotSpeed += (gs->randFloat() - 0.5f) * 1500;
- skidRotSpeed2 = 0.0f;
- skidRotPos2 = 0.0f;
-
- float3 skidDir;
-
- if (speed.SqLength2D() >= 0.01f) {
- skidDir = speed;
- skidDir.y = 0.0f;
+ skidRotPos2 = 0;
+ skidRotSpeed2 = 0;
+ float3 skidDir(speed);
+ skidDir.y = 0;
skidDir.Normalize();
- } else {
- skidDir = owner->frontdir;
- }
-
skidRotVector = skidDir.cross(UpVector);
-
oldPhysState = owner->physicalState;
owner->physicalState = CSolidObject::Flying;
owner->moveType->useHeading = false;
@@ -690,8 +686,8 @@ void CGroundMoveType::UpdateSkid()
speed *= (speedf - speedReduction) / speedf;
}
- const float remTime = speedf / speedReduction - 1.0f;
- const float rp = floor(skidRotPos2 + skidRotSpeed2 * remTime + 0.5f);
+ float remTime = speedf / speedReduction - 1.0f;
+ float rp = floor(skidRotPos2 + skidRotSpeed2 * remTime + 0.5f);
skidRotSpeed2 = (remTime + 1.0f == 0.0f ) ? 0.0f : (rp - skidRotPos2) / (remTime + 1.0f);
@@ -720,7 +716,13 @@ void CGroundMoveType::UpdateSkid()
}
}
CalcSkidRot();
- owner->MoveMidPos(speed);
+
+ midPos += speed;
+ pos = midPos -
+ owner->frontdir * owner->relMidPos.z -
+ owner->updir * owner->relMidPos.y -
+ owner->rightdir * owner->relMidPos.x;
+ owner->midPos = midPos;
CheckCollisionSkid();
ASSERT_SYNCED_FLOAT3(owner->midPos);
@@ -733,17 +735,25 @@ void CGroundMoveType::UpdateControlledDrop()
SyncedFloat3& midPos = owner->midPos;
if (owner->falling) {
- speed.y += (mapInfo->map.gravity * owner->fallSpeed);
- speed.y = std::min(speed.y, 0.0f);
+ speed.y += mapInfo->map.gravity * owner->fallSpeed;
- owner->MoveMidPos(speed);
+ if (owner->speed.y > 0) //sometimes the dropped unit gets an upward force, still unsure where its coming from
+ owner->speed.y = 0;
- if (midPos.y < 0.0f)
- speed *= 0.90;
+ midPos += speed;
+ pos = midPos -
+ owner->frontdir * owner->relMidPos.z -
+ owner->updir * owner->relMidPos.y -
+ owner->rightdir * owner->relMidPos.x;
+
+ owner->midPos.y = owner->pos.y + owner->relMidPos.y;
+
+ if(midPos.y < 0)
+ speed*=0.90;
const float wh = GetGroundHeight(midPos);
- if (wh > (midPos.y - owner->relMidPos.y)) {
+ if (wh > midPos.y - owner->relMidPos.y) {
owner->falling = false;
midPos.y = wh + owner->relMidPos.y - speed.y * 0.8;
owner->script->Landed(); //stop parachute animation
@@ -781,8 +791,12 @@ void CGroundMoveType::CheckCollisionSkid()
const float impactSpeed = -owner->speed.dot(dif);
if (impactSpeed > 0.0f) {
- owner->MoveMidPos(dif * impactSpeed);
- owner->speed += ((dif * impactSpeed) * 1.8f);
+ midPos += dif * impactSpeed;
+ pos = midPos -
+ owner->frontdir * owner->relMidPos.z -
+ owner->updir * owner->relMidPos.y -
+ owner->rightdir * owner->relMidPos.x;
+ owner->speed += dif * (impactSpeed * 1.8f);
// damage the collider
if (impactSpeed > ownerUD->minCollisionSpeed && ownerUD->minCollisionSpeed >= 0) {
@@ -799,10 +813,17 @@ void CGroundMoveType::CheckCollisionSkid()
const float impactSpeed = (u->speed - owner->speed).dot(dif) * 0.5f;
if (impactSpeed > 0.0f) {
- owner->MoveMidPos(dif * (impactSpeed * (1 - part) * 2));
+ midPos += dif * (impactSpeed * (1 - part) * 2);
+ pos = midPos -
+ owner->frontdir * owner->relMidPos.z -
+ owner->updir * owner->relMidPos.y -
+ owner->rightdir * owner->relMidPos.x;
owner->speed += dif * (impactSpeed * (1 - part) * 2);
-
- u->MoveMidPos(dif * (impactSpeed * part * -2));
+ u->midPos -= dif * (impactSpeed * part * 2);
+ u->pos = u->midPos -
+ u->frontdir * u->relMidPos.z -
+ u->updir * u->relMidPos.y -
+ u->rightdir * u->relMidPos.x;
u->speed -= dif * (impactSpeed * part * 2);
if (CGroundMoveType* mt = dynamic_cast<CGroundMoveType*>(u->moveType)) {
@@ -845,8 +866,12 @@ void CGroundMoveType::CheckCollisionSkid()
const float impactSpeed = -owner->speed.dot(dif);
if (impactSpeed > 0.0f) {
- owner->MoveMidPos(dif * impactSpeed);
- owner->speed += ((dif * impactSpeed) * 1.8f);
+ midPos += dif * impactSpeed;
+ pos = midPos -
+ owner->frontdir * owner->relMidPos.z -
+ owner->updir * owner->relMidPos.y -
+ owner->rightdir * owner->relMidPos.x;
+ owner->speed += dif * (impactSpeed * 1.8f);
if (impactSpeed > ownerUD->minCollisionSpeed && ownerUD->minCollisionSpeed >= 0) {
owner->DoDamage(DamageArray(impactSpeed * owner->mass * 0.2f), 0, ZeroVector);
@@ -859,7 +884,18 @@ void CGroundMoveType::CheckCollisionSkid()
void CGroundMoveType::CalcSkidRot()
{
owner->heading += (short int) skidRotSpeed;
- owner->SetDirectionFromHeading();
+
+ owner->frontdir = GetVectorFromHeading(owner->heading);
+
+ if (owner->upright) {
+ owner->updir = UpVector;
+ owner->rightdir = owner->frontdir.cross(owner->updir);
+ } else {
+ owner->updir = ground->GetSmoothNormal(owner->pos.x, owner->pos.z);
+ owner->rightdir = owner->frontdir.cross(owner->updir);
+ owner->rightdir.Normalize();
+ owner->frontdir = owner->updir.cross(owner->rightdir);
+ }
skidRotPos2 += skidRotSpeed2;
@@ -868,25 +904,22 @@ void CGroundMoveType::CalcSkidRot()
float3 f1 = skidRotVector * skidRotVector.dot(owner->frontdir);
float3 f2 = owner->frontdir - f1;
+ f2 = f2 * cosp + f2.cross(skidRotVector) * sinp;
+ owner->frontdir = f1 + f2;
float3 r1 = skidRotVector * skidRotVector.dot(owner->rightdir);
float3 r2 = owner->rightdir - r1;
+ r2 = r2 * cosp + r2.cross(skidRotVector) * sinp;
+ owner->rightdir = r1 + r2;
float3 u1 = skidRotVector * skidRotVector.dot(owner->updir);
float3 u2 = owner->updir - u1;
-
- f2 = f2 * cosp + f2.cross(skidRotVector) * sinp;
- r2 = r2 * cosp + r2.cross(skidRotVector) * sinp;
u2 = u2 * cosp + u2.cross(skidRotVector) * sinp;
-
- owner->frontdir = f1 + f2;
- owner->rightdir = r1 + r2;
- owner->updir = u1 + u2;
+ owner->updir = u1 + u2;
}
-
/*
* Dynamic obstacle avoidance, helps the unit to
* follow the path even when it's not perfect.
diff --git a/rts/Sim/MoveTypes/GroundMoveType.h b/rts/Sim/MoveTypes/GroundMoveType.h
index 30ee478..ad8c805 100644
--- a/rts/Sim/MoveTypes/GroundMoveType.h
+++ b/rts/Sim/MoveTypes/GroundMoveType.h
@@ -29,7 +29,7 @@ public:
void SetMaxSpeed(float speed);
- void ImpulseAdded(const float3&);
+ void ImpulseAdded();
void KeepPointingTo(float3 pos, float distance, bool aggressive);
void KeepPointingTo(CUnit* unit, float distance, bool aggressive);
diff --git a/rts/Sim/MoveTypes/MoveType.h b/rts/Sim/MoveTypes/MoveType.h
index b89ff88..c47428c 100644
--- a/rts/Sim/MoveTypes/MoveType.h
+++ b/rts/Sim/MoveTypes/MoveType.h
@@ -23,7 +23,7 @@ public:
virtual void KeepPointingTo(float3 pos, float distance, bool aggressive) = 0;
virtual void KeepPointingTo(CUnit* unit, float distance, bool aggressive);
virtual void StopMoving() = 0;
- virtual void ImpulseAdded(const float3&) {}
+ virtual void ImpulseAdded(void) {}
virtual void ReservePad(CAirBaseHandler::LandingPad* lp);
virtual void SetGoal(const float3& pos);
diff --git a/rts/Sim/MoveTypes/ScriptMoveType.h b/rts/Sim/MoveTypes/ScriptMoveType.h
index 1195710..904fd91 100644
--- a/rts/Sim/MoveTypes/ScriptMoveType.h
+++ b/rts/Sim/MoveTypes/ScriptMoveType.h
@@ -34,6 +34,7 @@ class CScriptMoveType : public AMoveType
void KeepPointingTo(CUnit* unit, float distance, bool aggressive) {}
void StopMoving() {}
+ void ImpulseAdded() {}
void SetGoal(float3 pos) {}
void SetMaxSpeed(float speed) {}
void SetWantedMaxSpeed(float speed) {}
diff --git a/rts/Sim/Objects/SolidObject.cpp b/rts/Sim/Objects/SolidObject.cpp
index f3ec270..949f734 100644
--- a/rts/Sim/Objects/SolidObject.cpp
+++ b/rts/Sim/Objects/SolidObject.cpp
@@ -60,8 +60,8 @@ CSolidObject::CSolidObject():
isMoving(false),
isUnderWater(false),
isMarkedOnBlockingMap(false),
- speed(ZeroVector),
- residualImpulse(ZeroVector),
+ speed(0, 0, 0),
+ residualImpulse(0, 0, 0),
allyteam(0),
team(0),
mobility(NULL),
diff --git a/rts/Sim/Path/Default/PathEstimator.cpp b/rts/Sim/Path/Default/PathEstimator.cpp
index b612a2b..e64fb78 100644
--- a/rts/Sim/Path/Default/PathEstimator.cpp
+++ b/rts/Sim/Path/Default/PathEstimator.cpp
@@ -1,9 +1,6 @@
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "StdAfx.h"
-
-#include "lib/gml/gml.h" // FIXME: linux for some reason does not compile without this
-
#include "PathEstimator.h"
#include <fstream>
diff --git a/rts/Sim/Projectiles/Projectile.h b/rts/Sim/Projectiles/Projectile.h
index ab75359..b0385c1 100644
--- a/rts/Sim/Projectiles/Projectile.h
+++ b/rts/Sim/Projectiles/Projectile.h
@@ -3,7 +3,7 @@
#ifndef PROJECTILE_H
#define PROJECTILE_H
-#include "lib/gml/gml.h" // for GML_ENABLE_SIM
+#include "Rendering/GL/myGL.h"
#ifdef _MSC_VER
#pragma warning(disable:4291)
diff --git a/rts/Sim/Units/Unit.cpp b/rts/Sim/Units/Unit.cpp
index 7802b41..07ac36a 100644
--- a/rts/Sim/Units/Unit.cpp
+++ b/rts/Sim/Units/Unit.cpp
@@ -120,7 +120,6 @@ CUnit::CUnit() : CSolidObject(),
stunned(false),
useHighTrajectory(false),
dontUseWeapons(false),
- dontFire(false),
deathScriptFinished(false),
delayedWreckLevel(-1),
restTime(0),
@@ -201,6 +200,7 @@ CUnit::CUnit() : CSolidObject(),
commandShotCount(-1),
fireState(FIRESTATE_FIREATWILL),
moveState(MOVESTATE_MANEUVER),
+ dontFire(false),
activated(false),
crashing(false),
isDead(false),
@@ -233,10 +233,6 @@ CUnit::CUnit() : CSolidObject(),
myTrack(NULL),
lastFlareDrop(0),
currentFuel(0.0f),
- maxSpeed(0.0f),
- maxReverseSpeed(0.0f),
- alphaThreshold(0.1f),
- cegDamage(1),
luaDraw(false),
noDraw(false),
noSelect(false),
@@ -244,8 +240,12 @@ CUnit::CUnit() : CSolidObject(),
leaveTracks(false),
isIcon(false),
iconRadius(0.0f),
+ maxSpeed(0.0f),
+ maxReverseSpeed(0.0f),
lodCount(0),
- currentLOD(0)
+ currentLOD(0),
+ alphaThreshold(0.1f),
+ cegDamage(1)
#ifdef USE_GML
, lastDrawFrame(-30)
#endif
@@ -593,6 +593,45 @@ void CUnit::ForcedSpin(const float3& newDir)
ForcedMove(pos); // lazy, don't need to update the quadfield, etc...
}
+
+/*
+void CUnit::SetFront(const SyncedFloat3& newDir)
+{
+ frontdir = newDir;
+ frontdir.Normalize();
+ rightdir = frontdir.cross(updir);
+ rightdir.Normalize();
+ updir = rightdir.cross(frontdir);
+ updir.Normalize();
+ heading = GetHeadingFromVector(frontdir.x, frontdir.z);
+ UpdateMidPos();
+}
+
+void CUnit::SetUp(const SyncedFloat3& newDir)
+{
+ updir = newDir;
+ updir.Normalize();
+ frontdir = updir.cross(rightdir);
+ frontdir.Normalize();
+ rightdir = frontdir.cross(updir);
+ rightdir.Normalize();
+ heading = GetHeadingFromVector(frontdir.x, frontdir.z);
+ UpdateMidPos();
+}
+
+void CUnit::SetRight(const SyncedFloat3& newDir)
+{
+ rightdir = newDir;
+ rightdir.Normalize();
+ updir = rightdir.cross(frontdir);
+ updir.Normalize();
+ frontdir = updir.cross(rightdir);
+ frontdir.Normalize();
+ heading = GetHeadingFromVector(frontdir.x, frontdir.z);
+ UpdateMidPos();
+}
+*/
+
void CUnit::SetDirectionFromHeading()
{
if (GetTransporter() == NULL) {
@@ -619,14 +658,6 @@ void CUnit::UpdateMidPos()
(rightdir * relMidPos.x);
}
-void CUnit::MoveMidPos(const float3& deltaPos) {
- midPos += deltaPos;
- pos = midPos -
- (frontdir * relMidPos.z) -
- (updir * relMidPos.y) -
- (rightdir * relMidPos.x);
-}
-
void CUnit::Drop(const float3& parentPos, const float3& parentDir, CUnit* parent)
{
@@ -1054,21 +1085,18 @@ void CUnit::SlowUpdateWeapons() {
void CUnit::DoWaterDamage()
{
- if (mapInfo->water.damage <= 0.0f) {
- return;
- }
- if (!pos.IsInBounds()) {
- return;
- }
-
- const int px = pos.x / (SQUARE_SIZE * 2);
- const int pz = pos.z / (SQUARE_SIZE * 2);
- const bool isFloating = (physicalState == CSolidObject::Floating);
- const bool onGround = (physicalState == CSolidObject::OnGround);
- const bool isWaterSquare = (readmap->mipHeightmap[1][pz * gs->hmapx + px] <= 0.0f);
-
- if ((pos.y <= 0.0f) && isWaterSquare && (isFloating || onGround)) {
- DoDamage(DamageArray(mapInfo->water.damage), 0, ZeroVector, -1);
+ if (uh->waterDamage > 0.0f) {
+ if (pos.IsInBounds()) {
+ const int px = int(pos.x / (SQUARE_SIZE * 2));
+ const int pz = int(pos.z / (SQUARE_SIZE * 2));
+ const bool isFloating = (physicalState == CSolidObject::Floating);
+ const bool onGround = (physicalState == CSolidObject::OnGround);
+ const bool isWaterSquare = (readmap->mipHeightmap[1][pz * gs->hmapx + px] <= 0.0f);
+
+ if ((pos.y <= 0.0f) && isWaterSquare && (isFloating || onGround)) {
+ DoDamage(DamageArray(uh->waterDamage), 0, ZeroVector, -1);
+ }
+ }
}
}
@@ -1128,7 +1156,8 @@ void CUnit::DoDamage(const DamageArray& damages, CUnit* attacker, const float3&
damage = newDamage;
}
- AddImpulse((impulse * impulseMult) / mass);
+ residualImpulse += ((impulse * impulseMult) / mass);
+ moveType->ImpulseAdded();
if (paralyzeTime == 0) { // real damage
if (damage > 0.0f) {
@@ -1149,7 +1178,8 @@ void CUnit::DoDamage(const DamageArray& damages, CUnit* attacker, const float3&
stunned = false;
}
}
- } else { // paralyzation
+ }
+ else { // paralyzation
experienceMod *= 0.1f; // reduced experience
if (damage > 0.0f) {
// paralyzeDamage may not get higher than maxHealth * (paralyzeTime + 1),
@@ -1223,13 +1253,6 @@ void CUnit::Kill(const float3& impulse) {
DoDamage(da, NULL, impulse, -1);
}
-void CUnit::AddImpulse(const float3& addedImpulse) {
- residualImpulse += addedImpulse;
-
- if (addedImpulse.SqLength() >= 0.01f)
- moveType->ImpulseAdded(addedImpulse);
-}
-
/******************************************************************************/
diff --git a/rts/Sim/Units/Unit.h b/rts/Sim/Units/Unit.h
index 3aa74a0..31871cb 100644
--- a/rts/Sim/Units/Unit.h
+++ b/rts/Sim/Units/Unit.h
@@ -3,8 +3,6 @@
#ifndef UNIT_H
#define UNIT_H
-#include "lib/gml/gml.h" // for GML_ENABLE_SIM
-
#include <map>
#include <vector>
#include <string>
@@ -82,7 +80,6 @@ public:
const float3& impulse, int weaponId = -1);
virtual void DoWaterDamage();
virtual void Kill(const float3& impulse);
- virtual void AddImpulse(const float3&);
virtual void FinishedBuilding();
bool AttackGround(const float3& pos, bool wantDGun, bool fpsMode = false);
@@ -150,7 +147,6 @@ public:
void UpdateTerrainType();
void UpdateMidPos();
- void MoveMidPos(const float3&);
bool IsNeutral() const {
return neutral;
diff --git a/rts/Sim/Units/UnitHandler.cpp b/rts/Sim/Units/UnitHandler.cpp
index 2c8326e..ab14579 100644
--- a/rts/Sim/Units/UnitHandler.cpp
+++ b/rts/Sim/Units/UnitHandler.cpp
@@ -1,18 +1,20 @@
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "StdAfx.h"
-#include <cassert>
+#include <assert.h>
#include "mmgr.h"
#include "lib/gml/gml.h"
#include "UnitHandler.h"
#include "Unit.h"
#include "UnitDefHandler.h"
-#include "CommandAI/BuilderCAI.h"
+#include "UnitLoader.h"
#include "CommandAI/Command.h"
+#include "CommandAI/BuilderCAI.h"
#include "Game/GameSetup.h"
#include "Lua/LuaUnsyncedCtrl.h"
#include "Map/Ground.h"
+#include "Map/MapInfo.h"
#include "Map/ReadMap.h"
#include "Sim/Features/Feature.h"
#include "Sim/Features/FeatureDef.h"
@@ -27,6 +29,7 @@
#include "System/LogOutput.h"
#include "System/TimeProfiler.h"
#include "System/myMath.h"
+#include "System/LoadSave/LoadSaveInterface.h"
#include "System/Sync/SyncTracer.h"
#include "System/creg/STL_Deque.h"
#include "System/creg/STL_List.h"
@@ -39,24 +42,29 @@ using std::max;
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
-CUnitHandler* uh = NULL;
+CUnitHandler* uh;
-CR_BIND(CUnitHandler, );
+CR_BIND(CUnitHandler, (true));
CR_REG_METADATA(CUnitHandler, (
CR_MEMBER(activeUnits),
CR_MEMBER(units),
- CR_MEMBER(freeUnitIDs),
- CR_MEMBER(maxUnits),
- CR_MEMBER(maxUnitsPerTeam),
+ CR_MEMBER(freeIDs),
+ CR_MEMBER(waterDamage),
+ CR_MEMBER(unitsPerTeam),
CR_MEMBER(maxUnitRadius),
- CR_MEMBER(unitsToBeRemoved),
+ CR_MEMBER(toBeRemoved),
CR_MEMBER(morphUnitToFeature),
+// CR_MEMBER(toBeRemoved),
CR_MEMBER(builderCAIs),
CR_MEMBER(unitsByDefs),
CR_POSTLOAD(PostLoad),
CR_SERIALIZER(Serialize)
-));
+ ));
+
+void CUnitHandler::Serialize(creg::ISerializer& s)
+{
+}
void CUnitHandler::PostLoad()
@@ -66,55 +74,38 @@ void CUnitHandler::PostLoad()
}
-CUnitHandler::CUnitHandler()
+CUnitHandler::CUnitHandler(bool serializing)
:
maxUnitRadius(0.0f),
morphUnitToFeature(true)
{
- assert(teamHandler->ActiveTeams() > 0);
-
- // note: the number of active teams can change at run-time, so
- // the team unit limit should be recalculated whenever one dies
- // or spawns (but would get complicated)
- maxUnits = std::min(gameSetup->maxUnits * teamHandler->ActiveTeams(), MAX_UNITS);
- maxUnitsPerTeam = maxUnits / teamHandler->ActiveTeams();
-
- // ensure each team can make at least one unit
- assert(maxUnits >= teamHandler->ActiveTeams());
- assert(maxUnitsPerTeam >= 1);
-
- units.resize(maxUnits, NULL);
- unitsByDefs.resize(teamHandler->ActiveTeams(), std::vector<CUnitSet>(unitDefHandler->unitDefs.size()));
+ const size_t maxUnitsTemp = std::min(gameSetup->maxUnits * teamHandler->ActiveTeams(), MAX_UNITS);
+ units.resize(maxUnitsTemp);
+ unitsPerTeam = maxUnitsTemp / teamHandler->ActiveTeams() - 5;
+
+ freeIDs.reserve(units.size()-1);
+ for (size_t a = 1; a < units.size(); a++) {
+ freeIDs.push_back(a);
+ units[a] = NULL;
+ }
+ units[0] = NULL;
- {
- std::vector<unsigned int> freeIDs(units.size());
+ slowUpdateIterator = activeUnits.end();
- // id's are used as indices, so they must lie in [0, units.size() - 1]
- // (furthermore all id's are treated equally, none have special status)
- for (unsigned int id = 0; id < units.size(); id++) {
- freeIDs[id] = id;
- }
+ waterDamage = mapInfo->water.damage;
- // randomize the unit ID's so that Lua widgets can not
- // easily determine enemy unit counts from ID's alone
- // (shuffle twice for good measure)
- SyncedRNG rng;
+ if (!serializing) {
+ airBaseHandler = new CAirBaseHandler;
- std::random_shuffle(freeIDs.begin(), freeIDs.end(), rng);
- std::random_shuffle(freeIDs.begin(), freeIDs.end(), rng);
- std::copy(freeIDs.begin(), freeIDs.end(), std::front_inserter(freeUnitIDs));
+ unitsByDefs.resize(teamHandler->ActiveTeams(), std::vector<CUnitSet>(unitDefHandler->unitDefs.size()));
}
-
- slowUpdateIterator = activeUnits.end();
- airBaseHandler = new CAirBaseHandler();
}
CUnitHandler::~CUnitHandler()
{
for (std::list<CUnit*>::iterator usi = activeUnits.begin(); usi != activeUnits.end(); ++usi) {
- // ~CUnit dereferences featureHandler which is destroyed already
- (*usi)->delayedWreckLevel = -1;
+ (*usi)->delayedWreckLevel = -1; // dont create wreckages since featureHandler may be destroyed already
delete (*usi);
}
@@ -122,44 +113,40 @@ CUnitHandler::~CUnitHandler()
}
-bool CUnitHandler::AddUnit(CUnit *unit)
+int CUnitHandler::AddUnit(CUnit *unit)
{
- if (freeUnitIDs.empty()) {
- // should be unreachable (all code that goes through
- // UnitLoader::LoadUnit --> Unit::PreInit checks the
- // unit limit first)
- assert(false);
- return false;
- }
-
- unit->id = freeUnitIDs.front();
- units[unit->id] = unit;
-
+ int num = (int)(gs->randFloat()) * ((int)activeUnits.size() - 1);
std::list<CUnit*>::iterator ui = activeUnits.begin();
-
- if (ui != activeUnits.end()) {
- // randomize this to make the slow-update order random (good if one
- // builds say many buildings at once and then many mobile ones etc)
- const unsigned int insertionPos = gs->randFloat() * activeUnits.size();
-
- for (unsigned int n = 0; n < insertionPos; ++n) {
- ++ui;
- }
+ for (int a = 0; a < num;++a) {
+ ++ui;
}
+ // randomize this to make the order in slowupdate random (good if one
+ // builds say many buildings at once and then many mobile ones etc)
activeUnits.insert(ui, unit);
- freeUnitIDs.pop_front();
+ // randomize the unitID assignment so that lua widgets can
+ // not easily determine enemy unit counts from unitIDs alone
+ assert(!freeIDs.empty());
+ const unsigned int freeSlot = gs->randInt() % freeIDs.size();
+ const unsigned int freeMax = freeIDs.size() - 1;
+ unit->id = freeIDs[freeSlot]; // set the unit ID
+ freeIDs[freeSlot] = freeIDs[freeMax];
+ freeIDs.resize(freeMax);
+
+ units[unit->id] = unit;
teamHandler->Team(unit->team)->AddUnit(unit, CTeam::AddBuilt);
unitsByDefs[unit->team][unit->unitDef->id].insert(unit);
maxUnitRadius = max(unit->radius, maxUnitRadius);
- return true;
+
+ return unit->id;
}
+
void CUnitHandler::DeleteUnit(CUnit* unit)
{
- unitsToBeRemoved.push_back(unit);
+ toBeRemoved.push_back(unit);
(eventBatchHandler->GetUnitCreatedDestroyedBatch()).dequeue_synced(unit);
}
@@ -187,12 +174,13 @@ void CUnitHandler::DeleteUnitNow(CUnit* delUnit)
activeUnits.erase(usi);
units[delUnit->id] = 0;
- freeUnitIDs.push_back(delUnit->id);
+ freeIDs.push_back(delUnit->id);
teamHandler->Team(delTeam)->RemoveUnit(delUnit, CTeam::RemoveDied);
unitsByDefs[delTeam][delType].erase(delUnit);
delete delUnit;
+
break;
}
}
@@ -215,7 +203,7 @@ void CUnitHandler::Update()
{
GML_STDMUTEX_LOCK(runit); // Update
- if (!unitsToBeRemoved.empty()) {
+ if (!toBeRemoved.empty()) {
GML_RECMUTEX_LOCK(unit); // Update - for anti-deadlock purposes.
GML_RECMUTEX_LOCK(sel); // Update - unit is removed from selectedUnits in ~CObject, which is too late.
GML_RECMUTEX_LOCK(quad); // Update - make sure unit does not get partially deleted before before being removed from the quadfield
@@ -223,9 +211,9 @@ void CUnitHandler::Update()
eventHandler.DeleteSyncedUnits();
- while (!unitsToBeRemoved.empty()) {
- CUnit* delUnit = unitsToBeRemoved.back();
- unitsToBeRemoved.pop_back();
+ while (!toBeRemoved.empty()) {
+ CUnit* delUnit = toBeRemoved.back();
+ toBeRemoved.pop_back();
DeleteUnitNow(delUnit);
}
@@ -237,7 +225,7 @@ void CUnitHandler::Update()
GML_UPDATE_TICKS();
{
- SCOPED_TIMER("Unit::MoveType::Update");
+ SCOPED_TIMER("Unit Movetype update");
std::list<CUnit*>::iterator usi;
for (usi = activeUnits.begin(); usi != activeUnits.end(); ++usi) {
CUnit* unit = *usi;
@@ -252,7 +240,7 @@ void CUnitHandler::Update()
}
{
- SCOPED_TIMER("Unit::Update");
+ SCOPED_TIMER("Unit update");
std::list<CUnit*>::iterator usi;
for (usi = activeUnits.begin(); usi != activeUnits.end(); ++usi) {
CUnit* unit = *usi;
@@ -272,7 +260,7 @@ void CUnitHandler::Update()
}
{
- SCOPED_TIMER("Unit::SlowUpdate");
+ SCOPED_TIMER("Unit slow update");
if (!(gs->frameNum & (UNIT_SLOWUPDATE_RATE - 1))) {
slowUpdateIterator = activeUnits.begin();
}
@@ -285,10 +273,10 @@ void CUnitHandler::Update()
}
-float CUnitHandler::GetBuildHeight(const float3& pos, const UnitDef* unitdef)
+float CUnitHandler::GetBuildHeight(float3 pos, const UnitDef* unitdef)
{
- float minh = -5000.0f;
- float maxh = 5000.0f;
+ float minh=-5000;
+ float maxh=5000;
int numBorder=0;
float borderh=0;
const float* heightmap=readmap->GetHeightmap();
@@ -477,9 +465,10 @@ void CUnitHandler::AddBuilderCAI(CBuilderCAI* b)
{
GML_STDMUTEX_LOCK(cai); // AddBuilderCAI
- builderCAIs.insert(builderCAIs.end(), b);
+ builderCAIs.insert(builderCAIs.end(),b);
}
+
void CUnitHandler::RemoveBuilderCAI(CBuilderCAI* b)
{
GML_STDMUTEX_LOCK(cai); // RemoveBuilderCAI
@@ -488,51 +477,46 @@ void CUnitHandler::RemoveBuilderCAI(CBuilderCAI* b)
}
+void CUnitHandler::LoadSaveUnits(CLoadSaveInterface* file, bool loading)
+{
+}
+
/**
* Returns a build Command that intersects the ray described by pos and dir from
* the command queues of the units 'units' on team number 'team'.
* @brief returns a build Command that intersects the ray described by pos and dir
- * @return the build Command, or a Command with id 0 if none is found
+ * @return the build Command, or a Command wiht id 0 if none is found
*/
-Command CUnitHandler::GetBuildCommand(const float3& pos, const float3& dir) {
+Command CUnitHandler::GetBuildCommand(float3 pos, float3 dir){
float3 tempF1 = pos;
GML_STDMUTEX_LOCK(cai); // GetBuildCommand
CCommandQueue::iterator ci;
- for (std::list<CUnit*>::const_iterator ui = activeUnits.begin(); ui != activeUnits.end(); ++ui) {
- const CUnit* unit = *ui;
-
- if (unit->team != gu->myTeam) {
- continue;
- }
-
- ci = unit->commandAI->commandQue.begin();
-
- for (; ci != unit->commandAI->commandQue.end(); ++ci) {
- const Command& cmd = *ci;
-
- if (cmd.id < 0 && cmd.params.size() >= 3) {
- BuildInfo bi(cmd);
- tempF1 = pos + dir * ((bi.pos.y - pos.y) / dir.y) - bi.pos;
-
- if (bi.def && (bi.GetXSize() / 2) * SQUARE_SIZE > fabs(tempF1.x) && (bi.GetZSize() / 2) * SQUARE_SIZE > fabs(tempF1.z)) {
- return cmd;
+ for(std::list<CUnit*>::iterator ui = this->activeUnits.begin(); ui != this->activeUnits.end(); ++ui){
+ if((*ui)->team == gu->myTeam){
+ ci = (*ui)->commandAI->commandQue.begin();
+ for(; ci != (*ui)->commandAI->commandQue.end(); ++ci){
+ if((*ci).id < 0 && (*ci).params.size() >= 3){
+ BuildInfo bi(*ci);
+ tempF1 = pos + dir*((bi.pos.y - pos.y)/dir.y) - bi.pos;
+ if(bi.def && bi.GetXSize()/2*SQUARE_SIZE > fabs(tempF1.x) && bi.GetZSize()/2*SQUARE_SIZE > fabs(tempF1.z)){
+ return (*ci);
+ }
}
}
}
}
-
Command c;
- c.id = CMD_STOP;
+ c.id = 0;
return c;
}
bool CUnitHandler::CanBuildUnit(const UnitDef* unitdef, int team)
{
- if (teamHandler->Team(team)->units.size() >= maxUnitsPerTeam) {
+ if (teamHandler->Team(team)->units.size() >= unitsPerTeam) {
return false;
}
if (unitsByDefs[team][unitdef->id].size() >= unitdef->maxThisUnit) {
diff --git a/rts/Sim/Units/UnitHandler.h b/rts/Sim/Units/UnitHandler.h
index 0f348d7..407f4c7 100644
--- a/rts/Sim/Units/UnitHandler.h
+++ b/rts/Sim/Units/UnitHandler.h
@@ -24,15 +24,14 @@ class CUnitHandler
CR_DECLARE(CUnitHandler)
public:
- CUnitHandler();
- ~CUnitHandler();
-
void Update();
void DeleteUnit(CUnit* unit);
void DeleteUnitNow(CUnit* unit);
- bool AddUnit(CUnit* unit);
- void Serialize(creg::ISerializer& s) {}
+ int AddUnit(CUnit* unit);
+ CUnitHandler(bool serializing=false);
+ void Serialize(creg::ISerializer& s);
void PostLoad();
+ virtual ~CUnitHandler();
///< test if a unit can be built at specified position
///< return values for the following is
@@ -56,12 +55,20 @@ public:
void AddBuilderCAI(CBuilderCAI*);
void RemoveBuilderCAI(CBuilderCAI*);
- float GetBuildHeight(const float3& pos, const UnitDef* unitdef);
+ float GetBuildHeight(float3 pos, const UnitDef* unitdef);
+
+ void LoadSaveUnits(CLoadSaveInterface* file, bool loading);
+ Command GetBuildCommand(float3 pos, float3 dir);
- Command GetBuildCommand(const float3& pos, const float3& dir);
+ int MaxUnitsPerTeam() const
+ {
+ return unitsPerTeam;
+ };
- unsigned int MaxUnitsPerTeam() const { return maxUnitsPerTeam; }
- unsigned int MaxUnits() const { return maxUnits; }
+ size_t MaxUnits() const
+ {
+ return units.size();
+ };
// note: negative ID's are implicitly converted
@@ -72,19 +79,23 @@ public:
std::vector< std::vector<CUnitSet> > unitsByDefs; ///< units sorted by team and unitDef
std::list<CUnit*> activeUnits; ///< used to get all active units
+ std::vector<int> freeIDs;
std::vector<CUnit*> units; ///< used to get units from IDs (0 if not created)
+
+ std::vector<CUnit*> toBeRemoved; ///< units that will be removed at start of next update
+
+ std::list<CUnit*>::iterator slowUpdateIterator;
+
std::list<CBuilderCAI*> builderCAIs;
+ float waterDamage;
+
float maxUnitRadius; ///< largest radius seen so far
+
bool morphUnitToFeature;
private:
- std::list<unsigned int> freeUnitIDs;
- std::vector<CUnit*> unitsToBeRemoved; ///< units that will be removed at start of next update
- std::list<CUnit*>::iterator slowUpdateIterator;
-
- unsigned int maxUnits;
- unsigned int maxUnitsPerTeam;
+ int unitsPerTeam;
};
extern CUnitHandler* uh;
diff --git a/rts/Sim/Units/UnitLoader.cpp b/rts/Sim/Units/UnitLoader.cpp
index 47210de..fa95845 100644
--- a/rts/Sim/Units/UnitLoader.cpp
+++ b/rts/Sim/Units/UnitLoader.cpp
@@ -315,8 +315,8 @@ void CUnitLoader::GiveUnits(const std::vector<std::string>& args, int team)
}
if (objectName == "all") {
- unsigned int numRequestedUnits = unitDefHandler->unitDefs.size() - 1; /// defid=0 is not valid
- unsigned int currentNumUnits = teamHandler->Team(team)->units.size();
+ int numRequestedUnits = unitDefHandler->unitDefs.size() - 1; /// defid=0 is not valid
+ int currentNumUnits = teamHandler->Team(team)->units.size();
// make sure team unit-limit is not exceeded
if ((currentNumUnits + numRequestedUnits) > uh->MaxUnitsPerTeam()) {
@@ -345,14 +345,11 @@ void CUnitLoader::GiveUnits(const std::vector<std::string>& args, int team)
}
}
} else {
- unsigned int numRequestedUnits = amount;
- unsigned int currentNumUnits = teamHandler->Team(team)->units.size();
+ int numRequestedUnits = amount;
+ int currentNumUnits = teamHandler->Team(team)->units.size();
if (currentNumUnits >= uh->MaxUnitsPerTeam()) {
- logOutput.Print(
- "[%s] unable to give more units to team %d (current: %u, team limit: %u, global limit: %u)",
- __FUNCTION__, team, currentNumUnits, uh->MaxUnitsPerTeam(), uh->MaxUnits()
- );
+ logOutput.Print("[%s] unable to give more units to team %d (current: %d, max: %d)", __FUNCTION__, team, currentNumUnits, uh->MaxUnits());
return;
}
diff --git a/rts/Sim/Units/UnitTypes/TransportUnit.cpp b/rts/Sim/Units/UnitTypes/TransportUnit.cpp
index 72faaa3..470d6f9 100644
--- a/rts/Sim/Units/UnitTypes/TransportUnit.cpp
+++ b/rts/Sim/Units/UnitTypes/TransportUnit.cpp
@@ -77,19 +77,16 @@ void CTransportUnit::Update()
if (unitDef->holdSteady) {
// slave transportee orientation to piece
if (ti->piece >= 0) {
- const CMatrix44f& transMat = GetTransformMatrix(true);
const CMatrix44f& pieceMat = script->GetPieceMatrix(ti->piece);
- const CMatrix44f slaveMat = transMat.Mul(pieceMat);
-
- SyncedFloat3& xdir = transportee->rightdir;
- SyncedFloat3& ydir = transportee->updir;
- SyncedFloat3& zdir = transportee->frontdir;
-
- zdir.x = slaveMat[8]; zdir.y = slaveMat[9]; zdir.z = slaveMat[10];
- xdir.x = slaveMat[0]; xdir.y = slaveMat[1]; xdir.z = slaveMat[ 2];
- ydir.x = slaveMat[4]; ydir.y = slaveMat[5]; ydir.z = slaveMat[ 6];
-
- transportee->heading = GetHeadingFromVector(zdir.x, zdir.z);
+ const float3 pieceDir =
+ frontdir * pieceMat[10] +
+ updir * pieceMat[ 6] +
+ rightdir * pieceMat[ 2];
+
+ transportee->heading = GetHeadingFromVector(pieceDir.x, pieceDir.z);
+ transportee->frontdir = pieceDir;
+ transportee->rightdir = transportee->frontdir.cross(UpVector);
+ transportee->updir = transportee->rightdir.cross(transportee->frontdir);
}
} else {
// slave transportee orientation to body
diff --git a/rts/Sim/Weapons/Weapon.cpp b/rts/Sim/Weapons/Weapon.cpp
index bc60b64..aa7bf15 100644
--- a/rts/Sim/Weapons/Weapon.cpp
+++ b/rts/Sim/Weapons/Weapon.cpp
@@ -474,7 +474,7 @@ bool CWeapon::AttackGround(float3 pos, bool userTarget)
return false;
if (targetUnit) {
DeleteDeathDependence(targetUnit);
- targetUnit = NULL;
+ targetUnit=0;
}
haveUserTarget = userTarget;
@@ -531,7 +531,7 @@ bool CWeapon::AttackUnit(CUnit* unit, bool userTarget)
if (targetUnit) {
DeleteDeathDependence(targetUnit);
- targetUnit = NULL;
+ targetUnit = 0;
}
haveUserTarget = userTarget;
@@ -549,7 +549,7 @@ void CWeapon::HoldFire()
{
if (targetUnit) {
DeleteDeathDependence(targetUnit);
- targetUnit = NULL;
+ targetUnit = 0;
}
targetType = Target_None;
haveUserTarget = false;
@@ -668,7 +668,7 @@ void CWeapon::SlowUpdate(bool noAutoTargetOverride)
// use targets from the thing we are slaved to
if (targetUnit) {
DeleteDeathDependence(targetUnit);
- targetUnit = NULL;
+ targetUnit = 0;
}
targetType = Target_None;
@@ -698,34 +698,22 @@ void CWeapon::SlowUpdate(bool noAutoTargetOverride)
lastTargetRetry = gs->frameNum;
std::multimap<float, CUnit*> targets;
- std::multimap<float, CUnit*>::const_iterator nextTargetIt;
- std::multimap<float, CUnit*>::const_iterator lastTargetIt;
-
helper->GenerateWeaponTargets(this, targetUnit, targets);
- if (!targets.empty())
- lastTargetIt = --targets.end();
+ for (std::multimap<float, CUnit*>::const_iterator ti = targets.begin(); ti != targets.end(); ++ti) {
+ CUnit* nextTarget = ti->second;
- for (nextTargetIt = targets.begin(); nextTargetIt != targets.end(); ++nextTargetIt) {
- CUnit* nextTargetUnit = nextTargetIt->second;
-
- if (nextTargetUnit->neutral && (owner->fireState <= FIRESTATE_FIREATWILL)) {
+ if (nextTarget->neutral && (owner->fireState <= FIRESTATE_FIREATWILL)) {
continue;
}
-
- // when only one target is available, <nextTarget> can equal <targetUnit>
- // and we want to attack whether it is in our bad target category or not
- // (if only bad targets are available and this is the last, just pick it)
- if (nextTargetUnit != targetUnit && (nextTargetUnit->category & badTargetCategory)) {
- if (nextTargetIt != lastTargetIt) {
- continue;
- }
+ if (targetUnit && (nextTarget->category & badTargetCategory)) {
+ continue;
}
- const float weaponLead = weaponDef->targetMoveError * GAME_SPEED * nextTargetUnit->speed.Length();
+ const float weaponLead = weaponDef->targetMoveError * GAME_SPEED * nextTarget->speed.Length();
const float weaponError = weaponLead * (1.0f - owner->limExperience);
- float3 nextTargetPos = nextTargetUnit->midPos + (errorVector * weaponError);
+ float3 nextTargetPos = nextTarget->midPos + (errorVector * weaponError);
const float appHeight = ground->GetApproximateHeight(nextTargetPos.x, nextTargetPos.z) + 2.0f;
@@ -733,13 +721,13 @@ void CWeapon::SlowUpdate(bool noAutoTargetOverride)
nextTargetPos.y = appHeight;
}
- if (TryTarget(nextTargetPos, false, nextTargetUnit)) {
+ if (TryTarget(nextTargetPos, false, nextTarget)) {
if (targetUnit) {
DeleteDeathDependence(targetUnit);
}
targetType = Target_Unit;
- targetUnit = nextTargetUnit;
+ targetUnit = nextTarget;
targetPos = nextTargetPos;
AddDeathDependence(targetUnit);
@@ -755,7 +743,7 @@ void CWeapon::SlowUpdate(bool noAutoTargetOverride)
}
} else {
// if we can't target anything, try switching aim point
- if (useWeaponPosForAim == 1) {
+ if (useWeaponPosForAim && (useWeaponPosForAim == 1)) {
useWeaponPosForAim = 0;
} else {
useWeaponPosForAim = 1;
| ||||||||
Relationships |
||||||
|
||||||
Notes |
|
|
(0006521) abma (administrator) 2011-04-01 00:27 edited on: 2011-04-01 01:10 |
an other one: http://pastebin.com/1149jyvz [^] |
|
(0006522) abma (administrator) 2011-04-01 01:09 edited on: 2011-04-01 01:11 |
damn, memory corruption? http://pastebin.com/Li1AhhSC [^] |
|
(0006523) abma (administrator) 2011-04-01 02:21 edited on: 2011-04-01 02:21 |
a diff-file which lists changes between master and assimp branch before merge, created with this command: $ git diff 5ac4738e8b0a886925e5e49a72cdf9803932f68a dcc943946a693b138dc85a8a391f6b1259c15798 -- rts/Game rts/Rendering rts/Sim rts/system maybe it helps others |
|
(0006524) abma (administrator) 2011-04-01 11:53 |
an other one: (pulseaudio/efx related?) http://pastebin.com/qnKEQstg [^] |
|
(0006547) abma (administrator) 2011-04-09 16:56 edited on: 2011-04-09 17:12 |
git bisect log git bisect start # bad: [078f69eef2811695044aaac271a4b1e3b7d7f461] fix gl.PushAttrib(GL.ALL_ATTRIB_BITS) git bisect bad 078f69eef2811695044aaac271a4b1e3b7d7f461 # good: [66de8f60e863befa61e5addaea539877dd78d064] modularized Watchdog & added Linux implementation * it can now handle any number of threads * it gives threads names - currently "main" (:= render-thread in spring-mt) & "sim" (only in spring-mt) * syntax of the Lua function changed too: Spring.ClearWatchDogTimer() --clears current thread's timer Spring.ClearWatchDogTimer("sim") --clears the timer of the "sim" thread git bisect good d4bc8acf371156afd2255286ae6328a00e7dd203 # good: [d4bc8acf371156afd2255286ae6328a00e7dd203] buildbot: ...and fix the path here too git bisect good d4bc8acf371156afd2255286ae6328a00e7dd203 # bad: [3e60285d073d39a39fa01b7dd3770f166e47f6c5] Fix compile error git bisect bad 3e60285d073d39a39fa01b7dd3770f166e47f6c5 # bad: [49413d80c5b92796b60dc51eff5381c1a7a1c841] Update VCproj git bisect bad 49413d80c5b92796b60dc51eff5381c1a7a1c841 # good: [31800c902f961270e9440efadef8b7b3a9d85ae1] add php frontend for stacktrace_translator git bisect good 31800c902f961270e9440efadef8b7b3a9d85ae1 # bad: [cc7a70b1134f024544d58b1b9a955f61f70f650c] compile git bisect bad cc7a70b1134f024544d58b1b9a955f61f70f650c # good: [04584519dd2257780def04a76bc4e486fa89ae9f] Audio: readd stats of dropped sounds git bisect good 04584519dd2257780def04a76bc4e486fa89ae9f so, the error seems to be there: https://github.com/spring/spring/compare/04584519dd2257780def04a76bc4e486fa89ae9f...cc7a70b1134f024544d58b1b9a955f61f70f650c [^] |
|
(0006551) abma (administrator) 2011-04-11 15:30 |
tried a few times again, 04584519dd2257780def04a76bc4e486fa89ae9f seems to be the last version without this bug. |
|
(0006552) abma (administrator) 2011-04-11 18:55 edited on: 2011-04-11 19:29 |
i tried on the same computer but with windows, crashes too: http://pastebin.com/HtTvHsGN [^] translated: http://pastebin.com/xdP1LHR3 [^] in linux i didn't get "LuaUI::RunCallIn: error = 4, GameFrame, not enough memory" seems to happen only sometimes i've 4GB mem... |
|
(0006553) abma (administrator) 2011-04-11 21:47 edited on: 2011-04-11 21:48 |
an other one: (this time with zk chickens) http://pastebin.com/KYq2emDe [^] translated: http://pastebin.com/vUGQTDGJ [^] |
|
(0006555) abma (administrator) 2011-04-13 20:38 |
ok, it looks like its only an out of memory. To reproduce it faster, this works for me as well: /cheat /give 300 armflea CTRL+A -> crash Tested in BA, "Red Build/Order Menu" has to be enabled |
|
(0006558) jK (developer) 2011-04-16 12:34 edited on: 2011-04-16 12:34 |
k, a short expertise: Lua uses a GarbageCollector, so it allocates more memory than needed. Additionally, Lua has a few quirks. So it does _not_ save a counter for references, to detect unused objects it needs to check the whole environment. Second, it doesn't have a "emergency GC", so Lua won't call the GC when running out of memory even when the environment is full unused/dead objects (will change with next Lua release)! And now the only thing we can control: the way Lua creates tables. There are two ways to create tables in C: lua_newtable & lua_createtable. Both behave similar to std::vectors. The first one just creates a vector/table and the second creates it + calls a .reserve() -> it allocs enough mem to hold all objects w/o the need to resize it. But there is one important difference to c++ std::vectors, Lua uses a GC! So when a table is to small to hold all objects and needs to be resized IT WILL LIKELY CREATE A COMPLETE NEW ONE and LEAVES THE OLD ONE IN THE RAM UNTIL THE GC CATCHES IT! This can create _thousand_ of unused tables in the ram when using lua_newtable & filling the table with ~ 1000 entries (esp. when the GC gets called each ~3sec). - Note: it seems this is only the case for the array part of tables, for the hash one it doesn't need continuous region, so it will just alloc single blocks for those. That's why it gets influenced by rawseti/ settable. |
|
(0006612) jK (developer) 2011-05-07 14:46 |
works now? |
|
(0006619) abma (administrator) 2011-05-07 21:55 |
no... now it crashes after selecting commander. gdb output: http://pastebin.com/GieCGV3M [^] console output: [f=0003296] Segmentation fault (SIGSEGV) in spring 0.82+.4.0 (Debug) [f=0003296] Stacktrace: [f=0003296] <0> /lib/x86_64-linux-gnu/libc.so.6(+0x33d80) [0x7ffff4831d80] [f=0003296] <1> /var/tmp/local/spring/master/bin/spring() [0xa37b4e] [f=0003296] <2> /var/tmp/local/spring/master/bin/spring() [0xa74341] [f=0003296] <3> /var/tmp/local/spring/master/bin/spring() [0xa75785] [f=0003296] <4> /usr/include/c++/4.6/bits/vector.tcc:310 [f=0003296] <5> /usr/include/c++/4.6/bits/vector.tcc:363 [f=0003296] <6> /home/abma/dev/spring/master/rts/Lua/LuaUnitRendering.cpp:442 [f=0003296] <7> /home/abma/dev/spring/master/rts/Lua/LuaUnitRendering.cpp:472 [f=0003296] <8> /home/abma/dev/spring/master/rts/Lua/LuaUnitRendering.cpp:478 [f=0003296] <9> /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xff) [0x7ffff481ceff] [New Thread 0x7fffd9323700 (LWP 4382)] [f=0003296] WARNING: failed to shutdown normally, exit forced [f=0003296] Spring crashed Spring has crashed: Segmentation fault (SIGSEGV). A stacktrace has been written to: /home/abma/.spring/infolog.txt [Thread 0x7fffda425700 (LWP 4363) exited] [Thread 0x7fffdac26700 (LWP 4362) exited] AL lib: ALc.c:1818: alcCloseDevice(): deleting 247 Buffer(s) [Thread 0x7fffdbc62700 (LWP 4361) exited] Program received signal SIGSEGV, Segmentation fault. 0x00007ffff50e5663 in __dynamic_cast () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (gdb) quit A debugging session is active. Inferior 1 [process 4357] will be killed. with current master and "Red Build/Order Menu" is enabled, no menu is displayed, it also sometimes crashes already when selecting the com. infolog.txt of a non-crash start: http://pastebin.com/ZJshK3Vi [^] when "Red Build/Order Menu" is disabled it seems to always work. |
|
(0006626) jK (developer) 2011-05-09 13:25 |
build with DEBUG2 and you should get a clean stacktrace |
|
(0006638) abma (administrator) 2011-05-11 01:33 |
http://pastebin.com/QYv5DwiG [^] |
|
(0006648) SirMaverick (reporter) 2011-05-11 17:57 |
Did you try ZK? It freezes for me in master, when I open the build menu (press b on constructor). Related or separate bug? |
|
(0006681) Kloot (developer) 2011-05-31 23:19 |
Does this still happen after ea431c3d23? |
|
(0006682) abma (administrator) 2011-05-31 23:30 edited on: 2011-05-31 23:44 |
no, doesn't crash, this seems to be fixed, thx! :-) but the zero-k buildmenu / "Red Build/Order Menu" isn't displayed, don't know whats wrong there.... when "Red Build/Order Menu" widget is loaded, the background box can be seen (without buttons) but it fades out and isn't shown again when a builder is selected. gestures in zero-k work, and the default menu is shown! |
|
(0006683) abma (administrator) 2011-05-31 23:47 |
i'll open a new report for that issue, the initial problem is solved, thx! :) |
Issue History |
|||
| Date Modified | Username | Field | Change |
| 2011-04-01 00:20 | abma | New Issue | |
| 2011-04-01 00:27 | abma | Note Added: 0006521 | |
| 2011-04-01 01:09 | abma | Note Added: 0006522 | |
| 2011-04-01 01:10 | abma | Additional Information Updated | |
| 2011-04-01 01:10 | abma | Note Edited: 0006521 | |
| 2011-04-01 01:11 | abma | Note Edited: 0006522 | |
| 2011-04-01 02:20 | abma | File Added: git.diff | |
| 2011-04-01 02:21 | abma | Note Added: 0006523 | |
| 2011-04-01 02:21 | abma | Note Edited: 0006523 | |
| 2011-04-01 03:42 | abma | Summary | crash after assimp merge => crash because of assimp merge (?) |
| 2011-04-01 03:43 | abma | Additional Information Updated | |
| 2011-04-01 11:53 | abma | Note Added: 0006524 | |
| 2011-04-01 11:56 | abma | Description Updated | |
| 2011-04-09 16:56 | abma | Note Added: 0006547 | |
| 2011-04-09 16:57 | abma | Note Edited: 0006547 | |
| 2011-04-09 17:12 | abma | Note Edited: 0006547 | |
| 2011-04-11 15:30 | abma | Note Added: 0006551 | |
| 2011-04-11 15:30 | abma | Summary | crash because of assimp merge (?) => crash/mem corruption(?) after commit 04584519dd2257780def04a76bc4e486fa89ae9f |
| 2011-04-11 18:55 | abma | Note Added: 0006552 | |
| 2011-04-11 18:57 | abma | Note Edited: 0006552 | |
| 2011-04-11 19:29 | abma | Note Edited: 0006552 | |
| 2011-04-11 21:47 | abma | Note Added: 0006553 | |
| 2011-04-11 21:48 | abma | Note Edited: 0006553 | |
| 2011-04-13 20:38 | abma | Note Added: 0006555 | |
| 2011-04-13 20:39 | abma | Summary | crash/mem corruption(?) after commit 04584519dd2257780def04a76bc4e486fa89ae9f => Crash in spring master with "Red Build/Order Menu" and >300 Units when pressing CTRL+A |
| 2011-04-13 20:39 | abma | Summary | Crash in spring master with "Red Build/Order Menu" and >300 Units when pressing CTRL+A => Crash in spring master with "Red Build/Order Menu" and >300 Units when pressing CTRL+A (Out of Memory) |
| 2011-04-13 20:39 | abma | Reproducibility | sometimes => always |
| 2011-04-16 12:34 | jK | Note Added: 0006558 | |
| 2011-04-16 12:34 | jK | Note Edited: 0006558 | |
| 2011-05-07 14:46 | jK | Note Added: 0006612 | |
| 2011-05-07 21:55 | abma | Note Added: 0006619 | |
| 2011-05-09 13:25 | jK | Note Added: 0006626 | |
| 2011-05-11 01:33 | abma | Note Added: 0006638 | |
| 2011-05-11 17:57 | SirMaverick | Note Added: 0006648 | |
| 2011-05-15 21:13 | abma | Relationship added | related to 0002430 |
| 2011-05-31 15:16 | abma | Summary | Crash in spring master with "Red Build/Order Menu" and >300 Units when pressing CTRL+A (Out of Memory) => (master) crash with "Red Build/Order Menu" and >300 Units when pressing CTRL+A (Out of Memory) |
| 2011-05-31 23:19 | Kloot | Note Added: 0006681 | |
| 2011-05-31 23:19 | Kloot | Status | new => feedback |
| 2011-05-31 23:30 | abma | Note Added: 0006682 | |
| 2011-05-31 23:31 | abma | Note Edited: 0006682 | |
| 2011-05-31 23:42 | abma | Note Edited: 0006682 | |
| 2011-05-31 23:44 | abma | Note Edited: 0006682 | |
| 2011-05-31 23:44 | abma | Note Edited: 0006682 | |
| 2011-05-31 23:47 | abma | Note Added: 0006683 | |
| 2011-05-31 23:47 | abma | Status | feedback => resolved |
| 2011-05-31 23:47 | abma | Resolution | open => fixed |
| 2011-05-31 23:47 | abma | Assigned To | => abma |
| Copyright © 2000 - 2013 MantisBT Team |



