Cleaned up all compiler warnings

This commit is contained in:
Mark Vejvoda 2010-03-13 22:00:01 +00:00
parent 2012b7e22c
commit ff60b09158
12 changed files with 3140 additions and 37 deletions

View File

@ -74,6 +74,7 @@ if $(WX_AVAILABLE) = "yes" {
}
### Viewer ###
if $(WX_AVAILABLE) = "yes" {
SubDir TOP g3d_viewer ;
GLEST_VIEWER_DIRS = . ;
@ -85,6 +86,7 @@ if $(WX_AVAILABLE) = "yes" {
LinkWith glest_g3dviewer : glestlib ;
ExternalLibs glest_g3dviewer : SDL GL GLU WX ;
IncludeDir glest_g3dviewer : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_VIEWER_DIRS) ;
}
### Configurator ###
SubDir TOP configurator ;

View File

@ -2,7 +2,8 @@
#include <stdexcept>
#include "graphics_factory_gl.h"
//#include "graphics_factory_gl.h"
#include "model_gl.h"
#include "graphics_interface.h"
#include "util.h"
#include "conversion.h"

View File

@ -3,14 +3,11 @@
#include <string>
#include <wx/wx.h>
#include <wx/glcanvas.h>
#include <wx/wx.h>
#include <wx/glcanvas.h>
#include "renderer.h"
//#include "util.h"
//using Shared::Platform::Window;
//using Shared::Platform::MouseState;
#include "util.h"
using std::string;

View File

@ -1,12 +1,8 @@
#include "renderer.h"
#include "opengl.h"
//#include "texture_gl.h"
#include "graphics_factory_gl.h"
#include "graphics_interface.h"
//#include "factory_repository.h"
using namespace Shared::Graphics;
using namespace Shared::Graphics::Gl;

View File

@ -0,0 +1,646 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2005 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "menu_state_custom_game.h"
#include "renderer.h"
#include "sound_renderer.h"
#include "core_data.h"
#include "config.h"
#include "menu_state_new_game.h"
#include "metrics.h"
#include "network_manager.h"
#include "network_message.h"
#include "client_interface.h"
#include "conversion.h"
#include "socket.h"
#include "game.h"
#include "leak_dumper.h"
#include <time.h>
namespace Glest{ namespace Game{
using namespace Shared::Util;
// =====================================================
// class MenuStateCustomGame
// =====================================================
MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, bool openNetworkSlots):
MenuState(program, mainMenu, "new-game")
{
Lang &lang= Lang::getInstance();
NetworkManager &networkManager= NetworkManager::getInstance();
needToSetChangedGameSettings = false;
lastSetChangedGameSettings = time(NULL);;
vector<string> glestMaps, megaMaps, teamItems, controlItems;
//create
buttonReturn.init(350, 140, 125);
buttonPlayNow.init(525, 140, 125);
//map listBox
findAll("maps/*.gbm", glestMaps, true, true);
findAll("maps/*.mgm", megaMaps, true, false);
mapFiles.resize(glestMaps.size() + megaMaps.size());
if (!glestMaps.empty()) {
copy(glestMaps.begin(), glestMaps.end(), mapFiles.begin());
}
if (!megaMaps.empty()) {
copy(megaMaps.begin(), megaMaps.end(), mapFiles.begin() + glestMaps.size());
}
if(mapFiles.size()==0){
throw runtime_error("There are no maps");
}
vector<string> results;
for(int i= 0; i < mapFiles.size(); ++i){
results.push_back(formatString(mapFiles[i]));
}
listBoxMap.init(200, 260, 150);
listBoxMap.setItems(results);
labelMap.init(200, 290);
labelMapInfo.init(200, 230, 200, 40);
//tileset listBox
findAll("tilesets/*.", results);
if(results.size()==0){
throw runtime_error("There is no tile set");
}
tilesetFiles= results;
for(int i= 0; i<results.size(); ++i){
results[i]= formatString(results[i]);
}
listBoxTileset.init(400, 260, 150);
listBoxTileset.setItems(results);
labelTileset.init(400, 290);
//tech Tree listBox
findAll("techs/*.", results);
if(results.size()==0){
throw runtime_error("There is no tech tree");
}
techTreeFiles= results;
for(int i= 0; i<results.size(); ++i){
results[i]= formatString(results[i]);
}
listBoxTechTree.init(600, 260, 150);
listBoxTechTree.setItems(results);
labelTechTree.init(600, 290);
//list boxes
for(int i=0; i<GameConstants::maxPlayers; ++i){
labelPlayers[i].init(200, 550-i*30);
listBoxControls[i].init(300, 550-i*30);
listBoxFactions[i].init(500, 550-i*30);
listBoxTeams[i].init(700, 550-i*30, 60);
labelNetStatus[i].init(800, 550-i*30, 60);
}
labelControl.init(300, 600, GraphicListBox::defW, GraphicListBox::defH, true);
labelFaction.init(500, 600, GraphicListBox::defW, GraphicListBox::defH, true);
labelTeam.init(700, 600, 60, GraphicListBox::defH, true);
//texts
buttonReturn.setText(lang.get("Return"));
buttonPlayNow.setText(lang.get("PlayNow"));
controlItems.push_back(lang.get("Closed"));
controlItems.push_back(lang.get("CpuEasy"));
controlItems.push_back(lang.get("Cpu"));
controlItems.push_back(lang.get("CpuUltra"));
controlItems.push_back(lang.get("CpuMega"));
controlItems.push_back(lang.get("Network"));
controlItems.push_back(lang.get("Human"));
teamItems.push_back("1");
teamItems.push_back("2");
teamItems.push_back("3");
teamItems.push_back("4");
teamItems.push_back("5");
teamItems.push_back("6");
teamItems.push_back("7");
teamItems.push_back("8");
reloadFactions();
findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results);
if(results.size()==0){
throw runtime_error("There is no factions for this tech tree");
}
for(int i=0; i<GameConstants::maxPlayers; ++i){
labelPlayers[i].setText(lang.get("Player")+" "+intToStr(i));
listBoxTeams[i].setItems(teamItems);
listBoxTeams[i].setSelectedItemIndex(i);
listBoxControls[i].setItems(controlItems);
labelNetStatus[i].setText("");
}
labelMap.setText(lang.get("Map"));
labelTileset.setText(lang.get("Tileset"));
labelTechTree.setText(lang.get("TechTree"));
labelControl.setText(lang.get("Control"));
labelFaction.setText(lang.get("Faction"));
labelTeam.setText(lang.get("Team"));
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
labelMapInfo.setText(mapInfo.desc);
//initialize network interface
networkManager.init(nrServer);
//init controllers
listBoxControls[0].setSelectedItemIndex(ctHuman);
if(openNetworkSlots){
for(int i= 1; i<mapInfo.players; ++i){
listBoxControls[i].setSelectedItemIndex(ctNetwork);
}
}
else{
listBoxControls[1].setSelectedItemIndex(ctCpu);
}
updateControlers();
updateNetworkSlots();
//chatManager.init(&console, world.getThisTeamIndex());
chatManager.init(&console, -1);
}
void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton){
CoreData &coreData= CoreData::getInstance();
SoundRenderer &soundRenderer= SoundRenderer::getInstance();
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
if(buttonReturn.mouseClick(x,y)){
soundRenderer.playFx(coreData.getClickSoundA());
mainMenu->setState(new MenuStateNewGame(program, mainMenu));
}
else if(buttonPlayNow.mouseClick(x,y) && buttonPlayNow.getEnabled()) {
closeUnusedSlots();
soundRenderer.playFx(coreData.getClickSoundC());
GameSettings gameSettings;
loadGameSettings(&gameSettings);
// Send the game settings to each client if we have at least one networked client
if( hasNetworkGameSettings() == true &&
needToSetChangedGameSettings == true)
{
serverInterface->setGameSettings(&gameSettings,true);
needToSetChangedGameSettings = false;
lastSetChangedGameSettings = time(NULL);
}
bool bOkToStart = serverInterface->launchGame(&gameSettings);
if(bOkToStart == true)
{
program->setState(new Game(program, &gameSettings));
}
}
else if(listBoxMap.mouseClick(x, y)){
printf("%s\n", mapFiles[listBoxMap.getSelectedItemIndex()].c_str());
loadMapInfo(Map::getMapPath(mapFiles[listBoxMap.getSelectedItemIndex()]), &mapInfo);
labelMapInfo.setText(mapInfo.desc);
updateControlers();
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxTileset.mouseClick(x, y)){
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxTechTree.mouseClick(x, y)){
reloadFactions();
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else
{
for(int i=0; i<mapInfo.players; ++i)
{
//ensure thet only 1 human player is present
if(listBoxControls[i].mouseClick(x, y))
{
//look for human players
int humanIndex1= -1;
int humanIndex2= -1;
for(int j=0; j<GameConstants::maxPlayers; ++j){
ControlType ct= static_cast<ControlType>(listBoxControls[j].getSelectedItemIndex());
if(ct==ctHuman){
if(humanIndex1==-1){
humanIndex1= j;
}
else{
humanIndex2= j;
}
}
}
//no human
if(humanIndex1==-1 && humanIndex2==-1){
listBoxControls[i].setSelectedItemIndex(ctHuman);
}
//2 humans
if(humanIndex1!=-1 && humanIndex2!=-1){
listBoxControls[humanIndex1==i? humanIndex2: humanIndex1].setSelectedItemIndex(ctClosed);
}
updateNetworkSlots();
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxFactions[i].mouseClick(x, y)){
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
else if(listBoxTeams[i].mouseClick(x, y))
{
if(hasNetworkGameSettings() == true)
{
needToSetChangedGameSettings = true;
lastSetChangedGameSettings = time(NULL);;
}
}
}
}
}
void MenuStateCustomGame::mouseMove(int x, int y, const MouseState *ms){
buttonReturn.mouseMove(x, y);
buttonPlayNow.mouseMove(x, y);
for(int i=0; i<GameConstants::maxPlayers; ++i){
listBoxControls[i].mouseMove(x, y);
listBoxFactions[i].mouseMove(x, y);
listBoxTeams[i].mouseMove(x, y);
}
listBoxMap.mouseMove(x, y);
listBoxTileset.mouseMove(x, y);
listBoxTechTree.mouseMove(x, y);
}
void MenuStateCustomGame::render(){
Renderer &renderer= Renderer::getInstance();
int i;
renderer.renderButton(&buttonReturn);
renderer.renderButton(&buttonPlayNow);
for(i=0; i<GameConstants::maxPlayers; ++i){
renderer.renderLabel(&labelPlayers[i]);
renderer.renderListBox(&listBoxControls[i]);
if(listBoxControls[i].getSelectedItemIndex()!=ctClosed){
renderer.renderListBox(&listBoxFactions[i]);
renderer.renderListBox(&listBoxTeams[i]);
renderer.renderLabel(&labelNetStatus[i]);
}
}
renderer.renderLabel(&labelMap);
renderer.renderLabel(&labelTileset);
renderer.renderLabel(&labelTechTree);
renderer.renderLabel(&labelControl);
renderer.renderLabel(&labelFaction);
renderer.renderLabel(&labelTeam);
renderer.renderLabel(&labelMapInfo);
renderer.renderListBox(&listBoxMap);
renderer.renderListBox(&listBoxTileset);
renderer.renderListBox(&listBoxTechTree);
renderer.renderChatManager(&chatManager);
renderer.renderConsole(&console);
}
void MenuStateCustomGame::update()
{
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
Lang& lang= Lang::getInstance();
bool haveAtLeastOneNetworkClientConnected = false;
for(int i= 0; i<mapInfo.players; ++i)
{
if(listBoxControls[i].getSelectedItemIndex() == ctNetwork)
{
//if(Socket::enableDebugText) printf("In [%s::%s] START - ctNetwork\n",__FILE__,__FUNCTION__);
ConnectionSlot* connectionSlot= serverInterface->getSlot(i);
assert(connectionSlot!=NULL);
//if(Socket::enableDebugText) printf("In [%s::%s] A - ctNetwork\n",__FILE__,__FUNCTION__);
if(connectionSlot->isConnected())
{
haveAtLeastOneNetworkClientConnected = true;
//if(Socket::enableDebugText) printf("In [%s::%s] B - ctNetwork\n",__FILE__,__FUNCTION__);
string label = connectionSlot->getName();
if(connectionSlot->getAllowDownloadDataSynch() == true &&
connectionSlot->getAllowGameDataSynchCheck() == true)
{
if(connectionSlot->getNetworkGameDataSynchCheckOk() == false)
{
label = connectionSlot->getName() + " - waiting to synch:";
if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false)
{
label = label + " map";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false)
{
label = label + " tile";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false)
{
label = label + " techtree";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
label = label + " FogOfWar == false";
}
}
else
{
label = connectionSlot->getName() + " - data synch is ok";
}
}
else
{
label = connectionSlot->getName();
if(connectionSlot->getAllowGameDataSynchCheck() == true)
{
label += " - warning synch mismatch for:";
if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false)
{
label = label + " map";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false)
{
label = label + " tile";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false)
{
label = label + " techtree";
}
if(connectionSlot->getNetworkGameDataSynchCheckOkFogOfWar() == false)
{
label = label + " FogOfWar == false";
}
}
}
labelNetStatus[i].setText(label);
}
else
{
//if(Socket::enableDebugText) printf("In [%s::%s] C - ctNetwork\n",__FILE__,__FUNCTION__);
labelNetStatus[i].setText(lang.get("NotConnected"));
}
//if(Socket::enableDebugText) printf("In [%s::%s] END - ctNetwork\n",__FILE__,__FUNCTION__);
}
else{
labelNetStatus[i].setText("");
}
}
// Send the game settings to each client if we have at least one networked client
if( serverInterface->getAllowDownloadDataSynch() == true &&
haveAtLeastOneNetworkClientConnected == true &&
needToSetChangedGameSettings == true &&
difftime(time(NULL),lastSetChangedGameSettings) >= 2)
{
GameSettings gameSettings;
loadGameSettings(&gameSettings);
serverInterface->setGameSettings(&gameSettings);
needToSetChangedGameSettings = false;
lastSetChangedGameSettings = time(NULL);
}
//call the chat manager
chatManager.updateNetwork();
//console
console.update();
}
void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings)
{
//if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__);
int factionCount= 0;
gameSettings->setDescription(formatString(mapFiles[listBoxMap.getSelectedItemIndex()]));
gameSettings->setMap(mapFiles[listBoxMap.getSelectedItemIndex()]);
gameSettings->setTileset(tilesetFiles[listBoxTileset.getSelectedItemIndex()]);
gameSettings->setTech(techTreeFiles[listBoxTechTree.getSelectedItemIndex()]);
gameSettings->setDefaultUnits(true);
gameSettings->setDefaultResources(true);
gameSettings->setDefaultVictoryConditions(true);
for(int i=0; i<mapInfo.players; ++i)
{
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
if(ct != ctClosed)
{
if(ct == ctHuman)
{
gameSettings->setThisFactionIndex(factionCount);
}
gameSettings->setFactionControl(factionCount, ct);
gameSettings->setTeam(factionCount, listBoxTeams[i].getSelectedItemIndex());
gameSettings->setStartLocationIndex(factionCount, i);
gameSettings->setFactionTypeName(factionCount, factionFiles[listBoxFactions[i].getSelectedItemIndex()]);
factionCount++;
}
}
gameSettings->setFactionCount(factionCount);
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTileset() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTileset().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getTech() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getTech().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] gameSettings->getMap() = [%s]\n",__FILE__,__FUNCTION__,gameSettings->getMap().c_str());
//if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__);
}
// ============ PRIVATE ===========================
bool MenuStateCustomGame::hasNetworkGameSettings()
{
bool hasNetworkSlot = false;
for(int i=0; i<mapInfo.players; ++i)
{
ControlType ct= static_cast<ControlType>(listBoxControls[i].getSelectedItemIndex());
if(ct != ctClosed)
{
if(ct == ctNetwork)
{
hasNetworkSlot = true;
break;
}
}
}
return hasNetworkSlot;
}
void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo){
struct MapFileHeader{
int32 version;
int32 maxPlayers;
int32 width;
int32 height;
int32 altFactor;
int32 waterLevel;
int8 title[128];
};
Lang &lang= Lang::getInstance();
try{
FILE *f= fopen(file.c_str(), "rb");
if(f==NULL)
throw runtime_error("Can't open file");
MapFileHeader header;
size_t readBytes = fread(&header, sizeof(MapFileHeader), 1, f);
mapInfo->size.x= header.width;
mapInfo->size.y= header.height;
mapInfo->players= header.maxPlayers;
mapInfo->desc= lang.get("MaxPlayers")+": "+intToStr(mapInfo->players)+"\n";
mapInfo->desc+=lang.get("Size")+": "+intToStr(mapInfo->size.x) + " x " + intToStr(mapInfo->size.y);
fclose(f);
}
catch(exception e){
throw runtime_error("Error loading map file: "+file+'\n'+e.what());
}
}
void MenuStateCustomGame::reloadFactions(){
vector<string> results;
findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results);
if(results.size()==0){
throw runtime_error("There is no factions for this tech tree");
}
factionFiles= results;
for(int i= 0; i<results.size(); ++i){
results[i]= formatString(results[i]);
}
for(int i=0; i<GameConstants::maxPlayers; ++i){
listBoxFactions[i].setItems(results);
listBoxFactions[i].setSelectedItemIndex(i % results.size());
}
}
void MenuStateCustomGame::updateControlers(){
bool humanPlayer= false;
for(int i= 0; i<mapInfo.players; ++i){
if(listBoxControls[i].getSelectedItemIndex() == ctHuman){
humanPlayer= true;
}
}
if(!humanPlayer){
listBoxControls[0].setSelectedItemIndex(ctHuman);
}
for(int i= mapInfo.players; i<GameConstants::maxPlayers; ++i){
listBoxControls[i].setSelectedItemIndex(ctClosed);
}
}
void MenuStateCustomGame::closeUnusedSlots(){
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
for(int i= 0; i<mapInfo.players; ++i){
if(listBoxControls[i].getSelectedItemIndex()==ctNetwork){
if(!serverInterface->getSlot(i)->isConnected()){
listBoxControls[i].setSelectedItemIndex(ctClosed);
}
}
}
updateNetworkSlots();
}
void MenuStateCustomGame::updateNetworkSlots()
{
ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface();
for(int i= 0; i<GameConstants::maxPlayers; ++i)
{
if(serverInterface->getSlot(i) == NULL && listBoxControls[i].getSelectedItemIndex() == ctNetwork)
{
serverInterface->addSlot(i);
}
if(serverInterface->getSlot(i) != NULL && listBoxControls[i].getSelectedItemIndex() != ctNetwork)
{
serverInterface->removeSlot(i);
}
}
}
void MenuStateCustomGame::keyDown(char key)
{
//send key to the chat manager
chatManager.keyDown(key);
}
void MenuStateCustomGame::keyPress(char c)
{
chatManager.keyPress(c);
}
}}//end namespace

View File

@ -0,0 +1,704 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "map.h"
#include <cassert>
#include "tileset.h"
#include "unit.h"
#include "resource.h"
#include "logger.h"
#include "tech_tree.h"
#include "config.h"
#include "leak_dumper.h"
#include "util.h"
using namespace Shared::Graphics;
using namespace Shared::Util;
namespace Glest{ namespace Game{
// =====================================================
// class Cell
// =====================================================
Cell::Cell(){
//game data
for(int i=0; i<fieldCount; ++i){
units[i]= NULL;
}
height= 0;
}
// ==================== misc ====================
//returns if the cell is free
bool Cell::isFree(Field field) const{
return getUnit(field)==NULL || getUnit(field)->isPutrefacting();
}
// =====================================================
// class SurfaceCell
// =====================================================
SurfaceCell::SurfaceCell(){
object= NULL;
vertex= Vec3f(0.f);
normal= Vec3f(0.f, 1.f, 0.f);
surfaceType= -1;
surfaceTexture= NULL;
}
SurfaceCell::~SurfaceCell(){
delete object;
}
bool SurfaceCell::isFree() const{
return object==NULL || object->getWalkable();
}
void SurfaceCell::deleteResource(){
delete object;
object= NULL;
}
void SurfaceCell::setExplored(int teamIndex, bool explored){
this->explored[teamIndex]= explored;
}
void SurfaceCell::setVisible(int teamIndex, bool visible){
this->visible[teamIndex]= visible;
}
// =====================================================
// class Map
// =====================================================
// ===================== PUBLIC ========================
const int Map::cellScale= 2;
const int Map::mapScale= 2;
Map::Map(){
cells= NULL;
surfaceCells= NULL;
startLocations= NULL;
}
Map::~Map(){
Logger::getInstance().add("Cells", true);
delete [] cells;
delete [] surfaceCells;
delete [] startLocations;
}
void Map::load(const string &path, TechTree *techTree, Tileset *tileset){
struct MapFileHeader{
int32 version;
int32 maxPlayers;
int32 width;
int32 height;
int32 altFactor;
int32 waterLevel;
int8 title[128];
int8 author[128];
int8 description[256];
};
try{
FILE *f= fopen(path.c_str(), "rb");
if(f!=NULL){
//read header
MapFileHeader header;
size_t readBytes = fread(&header, sizeof(MapFileHeader), 1, f);
if(next2Power(header.width) != header.width){
throw runtime_error("Map width is not a power of 2");
}
if(next2Power(header.height) != header.height){
throw runtime_error("Map height is not a power of 2");
}
heightFactor= header.altFactor;
waterLevel= static_cast<float>((header.waterLevel-0.01f)/heightFactor);
title= header.title;
maxPlayers= header.maxPlayers;
surfaceW= header.width;
surfaceH= header.height;
w= surfaceW*cellScale;
h= surfaceH*cellScale;
//start locations
startLocations= new Vec2i[maxPlayers];
for(int i=0; i<maxPlayers; ++i){
int x, y;
readBytes = fread(&x, sizeof(int32), 1, f);
readBytes = fread(&y, sizeof(int32), 1, f);
startLocations[i]= Vec2i(x, y)*cellScale;
}
//cells
cells= new Cell[w*h];
surfaceCells= new SurfaceCell[surfaceW*surfaceH];
//read heightmap
for(int j=0; j<surfaceH; ++j){
for(int i=0; i<surfaceW; ++i){
float32 alt;
readBytes = fread(&alt, sizeof(float32), 1, f);
SurfaceCell *sc= getSurfaceCell(i, j);
sc->setVertex(Vec3f(i*mapScale, alt / heightFactor, j*mapScale));
}
}
//read surfaces
for(int j=0; j<surfaceH; ++j){
for(int i=0; i<surfaceW; ++i){
int8 surf;
readBytes = fread(&surf, sizeof(int8), 1, f);
getSurfaceCell(i, j)->setSurfaceType(surf-1);
}
}
//read objects and resources
for(int j=0; j<h; j+= cellScale){
for(int i=0; i<w; i+= cellScale){
int8 objNumber;
readBytes = fread(&objNumber, sizeof(int8), 1, f);
SurfaceCell *sc= getSurfaceCell(toSurfCoords(Vec2i(i, j)));
if(objNumber==0){
sc->setObject(NULL);
}
else if(objNumber <= Tileset::objCount){
Object *o= new Object(tileset->getObjectType(objNumber-1), sc->getVertex());
sc->setObject(o);
for(int k=0; k<techTree->getResourceTypeCount(); ++k){
const ResourceType *rt= techTree->getResourceType(k);
if(rt->getClass()==rcTileset && rt->getTilesetObject()==objNumber){
o->setResource(rt, Vec2i(i, j));
}
}
}
else{
const ResourceType *rt= techTree->getTechResourceType(objNumber - Tileset::objCount) ;
Object *o= new Object(NULL, sc->getVertex());
o->setResource(rt, Vec2i(i, j));
sc->setObject(o);
}
}
}
}
else{
throw runtime_error("Can't open file");
}
fclose(f);
}
catch(const exception &e){
throw runtime_error("Error loading map: "+ path+ "\n"+ e.what());
}
}
void Map::init(){
Logger::getInstance().add("Heightmap computations", true);
smoothSurface();
computeNormals();
computeInterpolatedHeights();
computeNearSubmerged();
computeCellColors();
}
// ==================== is ====================
bool Map::isInside(int x, int y) const{
return x>=0 && y>=0 && x<w && y<h;
}
bool Map::isInside(const Vec2i &pos) const{
return isInside(pos.x, pos.y);
}
bool Map::isInsideSurface(int sx, int sy) const{
return sx>=0 && sy>=0 && sx<surfaceW && sy<surfaceH;
}
bool Map::isInsideSurface(const Vec2i &sPos) const{
return isInsideSurface(sPos.x, sPos.y);
}
//returns if there is a resource next to a unit, in "resourcePos" is stored the relative position of the resource
bool Map::isResourceNear(const Vec2i &pos, const ResourceType *rt, Vec2i &resourcePos) const{
for(int i=-1; i<=1; ++i){
for(int j=-1; j<=1; ++j){
if(isInside(pos.x+i, pos.y+j)){
Resource *r= getSurfaceCell(toSurfCoords(Vec2i(pos.x+i, pos.y+j)))->getResource();
if(r!=NULL){
if(r->getType()==rt){
resourcePos= pos + Vec2i(i,j);
return true;
}
}
}
}
}
return false;
}
// ==================== free cells ====================
bool Map::isFreeCell(const Vec2i &pos, Field field) const{
return
isInside(pos) &&
getCell(pos)->isFree(field) &&
(field==fAir || getSurfaceCell(toSurfCoords(pos))->isFree()) &&
(field!=fLand || !getDeepSubmerged(getCell(pos)));
}
bool Map::isFreeCellOrHasUnit(const Vec2i &pos, Field field, const Unit *unit) const{
if(isInside(pos)){
Cell *c= getCell(pos);
if(c->getUnit(unit->getCurrField())==unit){
return true;
}
else{
return isFreeCell(pos, field);
}
}
return false;
}
bool Map::isAproxFreeCell(const Vec2i &pos, Field field, int teamIndex) const{
if(isInside(pos)){
const SurfaceCell *sc= getSurfaceCell(toSurfCoords(pos));
if(sc->isVisible(teamIndex)){
return isFreeCell(pos, field);
}
else if(sc->isExplored(teamIndex)){
return field==fLand? sc->isFree() && !getDeepSubmerged(getCell(pos)): true;
}
else{
return true;
}
}
return false;
}
bool Map::isFreeCells(const Vec2i & pos, int size, Field field) const{
for(int i=pos.x; i<pos.x+size; ++i){
for(int j=pos.y; j<pos.y+size; ++j){
if(!isFreeCell(Vec2i(i,j), field)){
return false;
}
}
}
return true;
}
bool Map::isFreeCellsOrHasUnit(const Vec2i &pos, int size, Field field, const Unit *unit) const{
for(int i=pos.x; i<pos.x+size; ++i){
for(int j=pos.y; j<pos.y+size; ++j){
if(!isFreeCellOrHasUnit(Vec2i(i,j), field, unit)){
return false;
}
}
}
return true;
}
bool Map::isAproxFreeCells(const Vec2i &pos, int size, Field field, int teamIndex) const{
for(int i=pos.x; i<pos.x+size; ++i){
for(int j=pos.y; j<pos.y+size; ++j){
if(!isAproxFreeCell(Vec2i(i, j), field, teamIndex)){
return false;
}
}
}
return true;
}
// ==================== unit placement ====================
//checks if a unit can move from between 2 cells
bool Map::canMove(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2) const{
int size= unit->getType()->getSize();
for(int i=pos2.x; i<pos2.x+size; ++i){
for(int j=pos2.y; j<pos2.y+size; ++j){
if(isInside(i, j)){
if(getCell(i, j)->getUnit(unit->getCurrField())!=unit){
if(!isFreeCell(Vec2i(i, j), unit->getCurrField())){
return false;
}
}
}
else{
return false;
}
}
}
return true;
}
//checks if a unit can move from between 2 cells using only visible cells (for pathfinding)
bool Map::aproxCanMove(const Unit *unit, const Vec2i &pos1, const Vec2i &pos2) const{
int size= unit->getType()->getSize();
int teamIndex= unit->getTeam();
Field field= unit->getCurrField();
//single cell units
if(size==1){
if(!isAproxFreeCell(pos2, field, teamIndex)){
return false;
}
if(pos1.x!=pos2.x && pos1.y!=pos2.y){
if(!isAproxFreeCell(Vec2i(pos1.x, pos2.y), field, teamIndex)){
return false;
}
if(!isAproxFreeCell(Vec2i(pos2.x, pos1.y), field, teamIndex)){
return false;
}
}
return true;
}
//multi cell units
else{
for(int i=pos2.x; i<pos2.x+size; ++i){
for(int j=pos2.y; j<pos2.y+size; ++j){
if(isInside(i, j)){
if(getCell(i, j)->getUnit(unit->getCurrField())!=unit){
if(!isAproxFreeCell(Vec2i(i, j), field, teamIndex)){
return false;
}
}
}
else{
return false;
}
}
}
return true;
}
}
//put a units into the cells
void Map::putUnitCells(Unit *unit, const Vec2i &pos){
assert(unit!=NULL);
const UnitType *ut= unit->getType();
for(int i=0; i<ut->getSize(); ++i){
for(int j=0; j<ut->getSize(); ++j){
Vec2i currPos= pos + Vec2i(i, j);
assert(isInside(currPos));
if(!ut->hasCellMap() || unit->getCellMapCell(i, j)){
assert(getCell(currPos)->getUnit(unit->getCurrField())==NULL);
getCell(currPos)->setUnit(unit->getCurrField(), unit);
}
}
}
unit->setPos(pos);
}
//removes a unit from cells
void Map::clearUnitCells(Unit *unit, const Vec2i &pos){
assert(unit!=NULL);
const UnitType *ut= unit->getType();
for(int i=0; i<ut->getSize(); ++i){
for(int j=0; j<ut->getSize(); ++j){
Vec2i currPos= pos + Vec2i(i, j);
assert(isInside(currPos));
if(!ut->hasCellMap() || unit->getCellMapCell(i, j)){
assert(getCell(currPos)->getUnit(unit->getCurrField())==unit);
getCell(currPos)->setUnit(unit->getCurrField(), NULL);
}
}
}
}
// ==================== misc ====================
//returnis if unit is next to pos
bool Map::isNextTo(const Vec2i &pos, const Unit *unit) const{
for(int i=-1; i<=1; ++i){
for(int j=-1; j<=1; ++j){
if(isInside(pos.x+i, pos.y+j)) {
if(getCell(pos.x+i, pos.y+j)->getUnit(fLand)==unit){
return true;
}
}
}
}
return false;
}
void Map::clampPos(Vec2i &pos) const{
if(pos.x<0){
pos.x=0;
}
if(pos.y<0){
pos.y=0;
}
if(pos.x>=w){
pos.x=w-1;
}
if(pos.y>=h){
pos.y=h-1;
}
}
void Map::prepareTerrain(const Unit *unit){
flatternTerrain(unit);
computeNormals();
computeInterpolatedHeights();
}
// ==================== PRIVATE ====================
// ==================== compute ====================
void Map::flatternTerrain(const Unit *unit){
float refHeight= getSurfaceCell(toSurfCoords(unit->getCenteredPos()))->getHeight();
for(int i=-1; i<=unit->getType()->getSize(); ++i){
for(int j=-1; j<=unit->getType()->getSize(); ++j){
Vec2i pos= unit->getPos()+Vec2i(i, j);
Cell *c= getCell(pos);
SurfaceCell *sc= getSurfaceCell(toSurfCoords(pos));
//we change height if pos is inside world, if its free or ocupied by the currenty building
if(isInside(pos) && sc->getObject()==NULL && (c->getUnit(fLand)==NULL || c->getUnit(fLand)==unit)){
sc->setHeight(refHeight);
}
}
}
}
//compute normals
void Map::computeNormals(){
//compute center normals
for(int i=1; i<surfaceW-1; ++i){
for(int j=1; j<surfaceH-1; ++j){
getSurfaceCell(i, j)->setNormal(
getSurfaceCell(i, j)->getVertex().normal(getSurfaceCell(i, j-1)->getVertex(),
getSurfaceCell(i+1, j)->getVertex(),
getSurfaceCell(i, j+1)->getVertex(),
getSurfaceCell(i-1, j)->getVertex()));
}
}
}
void Map::computeInterpolatedHeights(){
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
getCell(i, j)->setHeight(getSurfaceCell(toSurfCoords(Vec2i(i, j)))->getHeight());
}
}
for(int i=1; i<surfaceW-1; ++i){
for(int j=1; j<surfaceH-1; ++j){
for(int k=0; k<cellScale; ++k){
for(int l=0; l<cellScale; ++l){
if(k==0 && l==0){
getCell(i*cellScale, j*cellScale)->setHeight(getSurfaceCell(i, j)->getHeight());
}
else if(k!=0 && l==0){
getCell(i*cellScale+k, j*cellScale)->setHeight((
getSurfaceCell(i, j)->getHeight()+
getSurfaceCell(i+1, j)->getHeight())/2.f);
}
else if(l!=0 && k==0){
getCell(i*cellScale, j*cellScale+l)->setHeight((
getSurfaceCell(i, j)->getHeight()+
getSurfaceCell(i, j+1)->getHeight())/2.f);
}
else{
getCell(i*cellScale+k, j*cellScale+l)->setHeight((
getSurfaceCell(i, j)->getHeight()+
getSurfaceCell(i, j+1)->getHeight()+
getSurfaceCell(i+1, j)->getHeight()+
getSurfaceCell(i+1, j+1)->getHeight())/4.f);
}
}
}
}
}
}
void Map::smoothSurface(){
float *oldHeights= new float[surfaceW*surfaceH];
for(int i=0; i<surfaceW*surfaceH; ++i){
oldHeights[i]= surfaceCells[i].getHeight();
}
for(int i=1; i<surfaceW-1; ++i){
for(int j=1; j<surfaceH-1; ++j){
float height= 0.f;
for(int k=-1; k<=1; ++k){
for(int l=-1; l<=1; ++l){
height+= oldHeights[(j+k)*surfaceW+(i+l)];
}
}
height/= 9.f;
getSurfaceCell(i, j)->setHeight(height);
Object *object= getSurfaceCell(i, j)->getObject();
if(object!=NULL){
object->setHeight(height);
}
}
}
delete [] oldHeights;
}
void Map::computeNearSubmerged(){
for(int i=0; i<surfaceW-1; ++i){
for(int j=0; j<surfaceH-1; ++j){
bool anySubmerged= false;
for(int k=-1; k<=2; ++k){
for(int l=-1; l<=2; ++l){
Vec2i pos= Vec2i(i+k, j+l);
if(isInsideSurface(pos)){
if(getSubmerged(getSurfaceCell(pos)))
anySubmerged= true;
}
}
}
getSurfaceCell(i, j)->setNearSubmerged(anySubmerged);
}
}
}
void Map::computeCellColors(){
for(int i=0; i<surfaceW; ++i){
for(int j=0; j<surfaceH; ++j){
SurfaceCell *sc= getSurfaceCell(i, j);
if(getDeepSubmerged(sc)){
float factor= clamp(waterLevel-sc->getHeight()*1.5f, 1.f, 1.5f);
sc->setColor(Vec3f(1.0f, 1.0f, 1.0f)/factor);
}
else{
sc->setColor(Vec3f(1.0f, 1.0f, 1.0f));
}
}
}
}
// static
string Map::getMapPath(const string &mapName) {
string mega = "maps/" + mapName + ".mgm";
string glest = "maps/" + mapName + ".gbm";
if (fileExists(mega)) {
return mega;
} else if (fileExists(glest)) {
return glest;
} else {
throw runtime_error("Map " + mapName + " not found.");
}
}
// =====================================================
// class PosCircularIterator
// =====================================================
PosCircularIterator::PosCircularIterator(const Map *map, const Vec2i &center, int radius){
this->map= map;
this->radius= radius;
this->center= center;
pos= center - Vec2i(radius, radius);
pos.x-= 1;
}
bool PosCircularIterator::next(){
//iterate while dont find a cell that is inside the world
//and at less or equal distance that the radius
do{
pos.x++;
if(pos.x > center.x+radius){
pos.x= center.x-radius;
pos.y++;
}
if(pos.y>center.y+radius)
return false;
}
while(floor(pos.dist(center)) >= (radius+1) || !map->isInside(pos));
//while(!(pos.dist(center) <= radius && map->isInside(pos)));
return true;
}
const Vec2i &PosCircularIterator::getPos(){
return pos;
}
// =====================================================
// class PosQuadIterator
// =====================================================
PosQuadIterator::PosQuadIterator(const Map *map, const Quad2i &quad, int step){
this->map= map;
this->quad= quad;
this->boundingRect= quad.computeBoundingRect();
this->step= step;
pos= boundingRect.p[0];
--pos.x;
pos.x= (pos.x/step)*step;
pos.y= (pos.y/step)*step;
}
bool PosQuadIterator::next(){
do{
pos.x+= step;
if(pos.x > boundingRect.p[1].x){
pos.x= (boundingRect.p[0].x/step)*step;
pos.y+= step;
}
if(pos.y>boundingRect.p[1].y)
return false;
}
while(!quad.isInside(pos));
return true;
}
void PosQuadIterator::skipX(){
pos.x+= step;
}
const Vec2i &PosQuadIterator::getPos(){
return pos;
}
}}//end namespace

View File

@ -9,8 +9,6 @@
// License, or (at your option) any later version
// ==============================================================
#include "main.h"
#include <ctime>

View File

@ -0,0 +1,756 @@
// ==============================================================
// This file is part of Glest (www.glest.org)
//
// Copyright (C) 2001-2008 Marti<74>o Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "map.h"
#include <cmath>
#include <stdexcept>
using namespace Shared::Util;
using namespace std;
namespace MapEditor {
// ===============================================
// class Map
// ===============================================
// ================== PUBLIC =====================
Map::Map() {
altFactor = 3;
waterLevel = 4;
cells = NULL;
startLocations = NULL;
reset(64, 64, 10.f, 1);
resetFactions(8);
title = "";
desc = "";
author = "";
refAlt = 10;
}
Map::~Map() {
delete [] startLocations;
for (int i = 0; i < h; i++) {
delete cells[i];
}
delete cells;
}
float Map::getHeight(int x, int y) const {
return cells[x][y].height;
}
int Map::getSurface(int x, int y) const {
return cells[x][y].surface;
}
int Map::getObject(int x, int y) const {
return cells[x][y].object;
}
int Map::getResource(int x, int y) const {
return cells[x][y].resource;
}
int Map::getStartLocationX(int index) const {
return startLocations[index].x;
}
int Map::getStartLocationY(int index) const {
return startLocations[index].y;
}
static int get_dist(int delta_x, int delta_y) {
float dx = delta_x;
float dy = delta_y;
return static_cast<int>(sqrtf(dx * dx + dy * dy));
}
void Map::glestChangeHeight(int x, int y, int height, int radius) {
for (int i = x - radius + 1; i < x + radius; i++) {
for (int j = y - radius + 1; j < y + radius; j++) {
if (inside(i, j)) {
int dist = get_dist(i - x, j - y);
if (radius > dist) {
int oldAlt = static_cast<int>(cells[i][j].height);
int altInc = height * (radius - dist - 1) / radius;
if (height > 0) {
altInc++;
}
if (height < 0) {
altInc--;
}
int newAlt = refAlt + altInc;
if ((height > 0 && newAlt > oldAlt) || (height < 0 && newAlt < oldAlt) || height == 0) {
if (newAlt >= 0 && newAlt <= 20) {
cells[i][j].height = static_cast<float>(newAlt);
}
}
}
}
}
}
}
void Map::pirateChangeHeight(int x, int y, int height, int radius) {
// Make sure not to try and blanket change the height over the bounds
// Find our goal height for the centre of the brush
int goalAlt;
int overBounds = refAlt + height;
if (overBounds > 20) {
goalAlt = 20;
}
else if (overBounds < 0) {
goalAlt = 0;
} else {
goalAlt = overBounds;
}
// If the radius is 1 don't bother doing any calculations
if (radius == 1) {
cells[x][y].height = goalAlt;
return;
}
// Get Old height reference points and compute gradients
// from the heights of the sides and corners of the brush to the centre goal height
float gradient[3][3]; // [i][j]
int indexI = 0;
for (int i = x - radius; i <= x + radius; i += radius) {
int indexJ = 0;
for (int j = y - radius; j <= y + radius; j += radius) {
// round off the corners
int ti, tj;
if (abs(i - x) == abs(j - y)) {
ti = (i - x) * 0.707 + x + 0.5;
tj = (j - y) * 0.707 + y + 0.5;
} else {
ti = i;
tj = j;
}
if (inside(ti, tj)) {
gradient[indexI][indexJ] = (cells[ti][tj].height - goalAlt) / radius;
//} else if (dist == 0) {
//gradient[indexI][indexJ] = 0;
} else {
// assume outside the map bounds is height 10
gradient[indexI][indexJ] = (10.0 - goalAlt) / radius;
}
//std::cout << "gradient[" << indexI << "][" << indexJ << "] = " << gradient[indexI][indexJ] << std::endl;
//std::cout << "derived from height " << cells[ti][tj].height << " at " << ti << " " << tj << std::endl;
indexJ++;
}
indexI++;
}
//std::cout << endl;
// A brush with radius n cells should have a true radius of n-1 distance
radius -= 1;
for (int i = x - radius; i <= x + radius; i++) {
for (int j = y - radius; j <= y + radius; j++) {
int dist = get_dist(i - x, j - y);
if (inside(i, j) && dist < radius) {
// Normalize di and dj and round them to an int so they can be used as indicies
float normIf = (float(i - x)/ radius);
float normJf = (float(j - y)/ radius);
int normI[2];
int normJ[2];
float usedGrad;
// Build a search box to find the gradients we are concerned about
// Find the nearest i indices
if (normIf < -0.33) {
normI[0] = 0;
if (normIf == 0) {
normI[1] = 0;
} else {
normI[1] = 1;
}
} else if (normIf < 0.33) {
normI[0] = 1;
if (normIf > 0) {
normI[1] = 2;
} else if (normIf < 0) {
normI[1] = 0;
} else /*(normIf == 0)*/ {
normI[1] = 1;
}
} else {
normI[0] = 2;
if (normIf == 1) {
normI[1] = 2;
} else {
normI[1] = 1;
}
}
// find nearest j indices
if (normJf < -0.33) {
normJ[0] = 0;
if (normJf == 0) {
normJ[1] = 0;
} else {
normJ[1] = 1;
}
} else if (normJf < 0.33) {
normJ[0] = 1;
if (normJf > 0) {
normJ[1] = 2;
} else if (normJf < 0) {
normJ[1] = 0;
} else /*(normJf == 0)*/ {
normJ[1] = 1;
}
} else {
normJ[0] = 2;
if (normJf == 1) {
normJ[1] = 2;
} else {
normJ[1] = 1;
}
}
// Determine which gradients to use and take a weighted average
if (abs(normIf) > abs(normJf)) {
usedGrad =
gradient[normI[0]] [normJ[0]] * abs(normJf) +
gradient[normI[0]] [normJ[1]] * (1 - abs(normJf));
} else if (abs(normIf) < abs(normJf)) {
usedGrad =
gradient[normI[0]] [normJ[0]] * abs(normIf) +
gradient[normI[1]] [normJ[0]] * (1 - abs(normIf));
} else {
usedGrad =
gradient[normI[0]] [normJ[0]];
}
float newAlt = usedGrad * dist + goalAlt;
// if the change in height and what is supposed to be the change in height
// are the same sign then we can change the height
if ( ((newAlt - cells[i][j].height) > 0 && height > 0) ||
((newAlt - cells[i][j].height) < 0 && height < 0) ||
height == 0) {
cells[i][j].height = newAlt;
}
}
}
}
}
void Map::setHeight(int x, int y, float height) {
cells[x][y].height = height;
}
void Map::setRefAlt(int x, int y) {
if (inside(x, y)) {
refAlt = static_cast<int>(cells[x][y].height);
}
}
void Map::flipX() {
Cell **oldCells = cells;
cells = new Cell*[w];
for (int i = 0; i < w; i++) {
cells[i] = new Cell[h];
for (int j = 0; j < h; j++) {
cells[i][j].height = oldCells[w-i-1][j].height;
cells[i][j].object = oldCells[w-i-1][j].object;
cells[i][j].resource = oldCells[w-i-1][j].resource;
cells[i][j].surface = oldCells[w-i-1][j].surface;
}
}
for (int i = 0; i < maxFactions; ++i) {
startLocations[i].x = w - startLocations[i].x - 1;
}
for (int i = 0; i < w; i++) {
delete oldCells[i];
}
delete oldCells;
}
void Map::flipY() {
Cell **oldCells = cells;
cells = new Cell*[w];
for (int i = 0; i < w; i++) {
cells[i] = new Cell[h];
for (int j = 0; j < h; j++) {
cells[i][j].height = oldCells[i][h-j-1].height;
cells[i][j].object = oldCells[i][h-j-1].object;
cells[i][j].resource = oldCells[i][h-j-1].resource;
cells[i][j].surface = oldCells[i][h-j-1].surface;
}
}
for (int i = 0; i < maxFactions; ++i) {
startLocations[i].y = h - startLocations[i].y - 1;
}
for (int i = 0; i < w; i++) {
delete oldCells[i];
}
delete oldCells;
}
void Map::changeSurface(int x, int y, int surface, int radius) {
int i, j;
int dist;
for (i = x - radius + 1; i < x + radius; i++) {
for (j = y - radius + 1; j < y + radius; j++) {
if (inside(i, j)) {
dist = get_dist(i - x, j - y);
if (radius >= dist) {
cells[i][j].surface = surface;
}
}
}
}
}
void Map::setSurface(int x, int y, int surface) {
cells[x][y].surface = surface;
}
void Map::changeObject(int x, int y, int object, int radius) {
int i, j;
int dist;
for (i = x - radius + 1; i < x + radius; i++) {
for (j = y - radius + 1; j < y + radius; j++) {
if (inside(i, j)) {
dist = get_dist(i - x, j - y);
if (radius >= dist) {
cells[i][j].object = object;
cells[i][j].resource = 0;
}
}
}
}
}
void Map::setObject(int x, int y, int object) {
cells[x][y].object = object;
if (object != 0) cells[x][y].resource = 0;
}
void Map::changeResource(int x, int y, int resource, int radius) {
int i, j;
int dist;
for (i = x - radius + 1; i < x + radius; i++) {
for (j = y - radius + 1; j < y + radius; j++) {
if (inside(i, j)) {
dist = get_dist(i - x, j - y);
if (radius >= dist) {
cells[i][j].resource = resource;
cells[i][j].object = 0;
}
}
}
}
}
void Map::setResource(int x, int y, int resource) {
cells[x][y].resource = resource;
if (resource != 0) cells[x][y].object = 0;
}
void Map::changeStartLocation(int x, int y, int faction) {
if ((faction - 1) < maxFactions && inside(x, y)) {
startLocations[faction].x = x;
startLocations[faction].y = y;
}
}
bool Map::inside(int x, int y) {
return (x >= 0 && x < w && y >= 0 && y < h);
}
void Map::reset(int w, int h, float alt, int surf) {
if (w < 16 || h < 16) {
throw runtime_error("Size of map must be at least 16x16");
return;
}
if (w > 1024 || h > 1024) {
throw runtime_error("Size of map can be at most 1024x1024");
return;
}
if (alt < 0 || alt > 20) {
throw runtime_error("Height must be in the range 0-20");
return;
}
if (surf < 1 || surf > 5) {
throw runtime_error("Surface must be in the range 1-5");
return;
}
if (cells != NULL) {
for (int i = 0; i < this->w; i++) {
delete cells[i];
}
delete cells;
}
this->w = w;
this->h = h;
this->maxFactions = maxFactions;
cells = new Cell*[w];
for (int i = 0; i < w; i++) {
cells[i] = new Cell[h];
for (int j = 0; j < h; j++) {
cells[i][j].height = alt;
cells[i][j].object = 0;
cells[i][j].resource = 0;
cells[i][j].surface = surf;
}
}
}
void Map::resize(int w, int h, float alt, int surf) {
if (w < 16 || h < 16) {
throw runtime_error("Size of map must be at least 16x16");
return;
}
if (w > 1024 || h > 1024) {
throw runtime_error("Size of map can be at most 1024x1024");
return;
}
if (alt < 0 || alt > 20) {
throw runtime_error("Height must be in the range 0-20");
return;
}
if (surf < 1 || surf > 5) {
throw runtime_error("Surface must be in the range 1-5");
return;
}
int oldW = this->w;
int oldH = this->h;
this->w = w;
this->h = h;
this->maxFactions = maxFactions;
//create new cells
Cell **oldCells = cells;
cells = new Cell*[w];
for (int i = 0; i < w; i++) {
cells[i] = new Cell[h];
for (int j = 0; j < h; j++) {
cells[i][j].height = alt;
cells[i][j].object = 0;
cells[i][j].resource = 0;
cells[i][j].surface = surf;
}
}
int wOffset = w < oldW ? 0 : (w - oldW) / 2;
int hOffset = h < oldH ? 0 : (h - oldH) / 2;
//assign old values to cells
for (int i = 0; i < oldW; i++) {
for (int j = 0; j < oldH; j++) {
if (i + wOffset < w && j + hOffset < h) {
cells[i+wOffset][j+hOffset].height = oldCells[i][j].height;
cells[i+wOffset][j+hOffset].object = oldCells[i][j].object;
cells[i+wOffset][j+hOffset].resource = oldCells[i][j].resource;
cells[i+wOffset][j+hOffset].surface = oldCells[i][j].surface;
}
}
}
for (int i = 0; i < maxFactions; ++i) {
startLocations[i].x += wOffset;
startLocations[i].y += hOffset;
}
//delete old cells
if (oldCells != NULL) {
for (int i = 0; i < oldW; i++)
delete oldCells[i];
delete oldCells;
}
}
void Map::resetFactions(int maxPlayers) {
if (maxPlayers<1 || maxPlayers>8){
throw runtime_error("Max Players must be in the range 1-8");
}
if (startLocations != NULL)
delete startLocations;
maxFactions = maxPlayers;
startLocations = new StartLocation[maxFactions];
for (int i = 0; i < maxFactions; i++) {
startLocations[i].x = 0;
startLocations[i].y = 0;
}
}
void Map::setTitle(const string &title) {
this->title = title;
}
void Map::setDesc(const string &desc) {
this->desc = desc;
}
void Map::setAuthor(const string &author) {
this->author = author;
}
void Map::setAdvanced(int altFactor, int waterLevel) {
this->altFactor = altFactor;
this->waterLevel = waterLevel;
}
int Map::getHeightFactor() const {
return altFactor;
}
int Map::getWaterLevel() const {
return waterLevel;
}
void Map::randomizeHeights() {
resetHeights(random.randRange(8, 10));
sinRandomize(0);
decalRandomize(4);
sinRandomize(1);
}
void Map::randomize() {
randomizeHeights();
int slPlaceFactorX = random.randRange(0, 1);
int slPlaceFactorY = random.randRange(0, 1) * 2;
for (int i = 0; i < maxFactions; ++i) {
StartLocation sl;
float slNoiseFactor = random.randRange(0.5f, 0.8f);
sl.x = static_cast<int>(w * slNoiseFactor * ((i + slPlaceFactorX) % 2) + w * (1.f - slNoiseFactor) / 2.f);
sl.y = static_cast<int>(h * slNoiseFactor * (((i + slPlaceFactorY) / 2) % 2) + h * (1.f - slNoiseFactor) / 2.f);
startLocations[i] = sl;
}
}
void Map::switchSurfaces(int surf1, int surf2) {
if (surf1 > 0 && surf1 <= 5 && surf2 > 0 && surf2 <= 5) {
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
if (cells[i][j].surface == surf1) {
cells[i][j].surface = surf2;
} else if (cells[i][j].surface == surf2) {
cells[i][j].surface = surf1;
}
}
}
} else {
throw runtime_error("Incorrect surfaces");
}
}
void Map::loadFromFile(const string &path) {
FILE *f1 = fopen(path.c_str(), "rb");
if (f1 != NULL) {
//read header
MapFileHeader header;
size_t readBytes = fread(&header, sizeof(MapFileHeader), 1, f1);
altFactor = header.altFactor;
waterLevel = header.waterLevel;
title = header.title;
author = header.author;
desc = header.description;
//read start locations
resetFactions(header.maxFactions);
for (int i = 0; i < maxFactions; ++i) {
readBytes = fread(&startLocations[i].x, sizeof(int32), 1, f1);
readBytes = fread(&startLocations[i].y, sizeof(int32), 1, f1);
}
//read Heights
reset(header.width, header.height, 10, 1);
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
readBytes = fread(&cells[i][j].height, sizeof(float), 1, f1);
}
}
//read surfaces
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
readBytes = fread(&cells[i][j].surface, sizeof(int8), 1, f1);
}
}
//read objects
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
int8 obj;
readBytes = fread(&obj, sizeof(int8), 1, f1);
if (obj <= 10) {
cells[i][j].object = obj;
} else {
cells[i][j].resource = obj - 10;
}
}
}
fclose(f1);
} else {
throw runtime_error("error opening map file: " + path);
}
}
void Map::saveToFile(const string &path) {
FILE *f1 = fopen(path.c_str(), "wb");
if (f1 != NULL) {
//write header
MapFileHeader header;
header.version = 1;
header.maxFactions = maxFactions;
header.width = w;
header.height = h;
header.altFactor = altFactor;
header.waterLevel = waterLevel;
strncpy(header.title, title.c_str(), 128);
strncpy(header.author, author.c_str(), 128);
strncpy(header.description, desc.c_str(), 256);
fwrite(&header, sizeof(MapFileHeader), 1, f1);
//write start locations
for (int i = 0; i < maxFactions; ++i) {
fwrite(&startLocations[i].x, sizeof(int32), 1, f1);
fwrite(&startLocations[i].y, sizeof(int32), 1, f1);
}
//write Heights
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
fwrite(&cells[i][j].height, sizeof(float32), 1, f1);
}
}
//write surfaces
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
fwrite(&cells[i][j].surface, sizeof(int8), 1, f1);
}
}
//write objects
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
if (cells[i][j].resource == 0)
fwrite(&cells[i][j].object, sizeof(int8), 1, f1);
else {
int8 res = cells[i][j].resource + 10;
fwrite(&res, sizeof(int8), 1, f1);
}
}
}
fclose(f1);
} else {
throw runtime_error("Error opening map file: " + path);
}
void randomHeight(int x, int y, int height);
}
// ==================== PRIVATE ====================
void Map::resetHeights(int height) {
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
cells[i][j].height = static_cast<float>(height);
}
}
}
void Map::sinRandomize(int strenght) {
float sinH1 = random.randRange(5.f, 40.f);
float sinH2 = random.randRange(5.f, 40.f);
float sinV1 = random.randRange(5.f, 40.f);
float sinV2 = random.randRange(5.f, 40.f);
float ah = static_cast<float>(10 + random.randRange(-2, 2));
float bh = static_cast<float>((maxHeight - minHeight) / random.randRange(2, 3));
float av = static_cast<float>(10 + random.randRange(-2, 2));
float bv = static_cast<float>((maxHeight - minHeight) / random.randRange(2, 3));
for (int i = 0; i < w; ++i) {
for (int j = 0; j < h; ++j) {
float normH = static_cast<float>(i) / w;
float normV = static_cast<float>(j) / h;
float sh = (sinf(normH * sinH1) + sin(normH * sinH2)) / 2.f;
float sv = (sinf(normV * sinV1) + sin(normV * sinV2)) / 2.f;
float newHeight = (ah + bh * sh + av + bv * sv) / 2.f;
applyNewHeight(newHeight, i, j, strenght);
}
}
}
void Map::decalRandomize(int strenght) {
//first row
int lastHeight = 10;
for (int i = 0; i < w; ++i) {
lastHeight += random.randRange(-1, 1);
lastHeight = clamp(lastHeight, minHeight, maxHeight);
applyNewHeight(static_cast<float>(lastHeight), i, 0, strenght);
}
//other rows
for (int j = 1; j < h; ++j) {
int height = static_cast<int>(cells[0][j-1].height + random.randRange(-1, 1));
applyNewHeight(static_cast<float>(clamp(height, minHeight, maxHeight)), 0, j, strenght);
for (int i = 1; i < w; ++i) {
height = static_cast<int>((cells[i][j-1].height + cells[i-1][j].height) / 2.f + random.randRange(-1, 1));
float newHeight = static_cast<float>(clamp(height, minHeight, maxHeight));
applyNewHeight(newHeight, i, j, strenght);
}
}
}
void Map::applyNewHeight(float newHeight, int x, int y, int strenght) {
cells[x][y].height = static_cast<float>(((cells[x][y].height * strenght) + newHeight) / (strenght + 1));
}
}// end namespace

View File

@ -0,0 +1,57 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2005 Matthias Braun <matze@braunis.de>
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _SHARED_PLATFORM_GLWRAP_H_
#define _SHARED_PLATFORM_GLWRAP_H_
#include <SDL.h>
#define GL_GLEXT_PROTOTYPES
#include <SDL_opengl.h>
#include <string>
#include "font.h"
#include "types.h"
using std::string;
using Shared::Graphics::FontMetrics;
namespace Shared{ namespace Platform{
// =====================================================
// class PlatformContextGl
// =====================================================
class PlatformContextGl {
public:
virtual ~PlatformContextGl() {}
virtual void init(int colorBits, int depthBits, int stencilBits);
virtual void end();
virtual void makeCurrent();
virtual void swapBuffers();
DeviceContextHandle getHandle() const { return 0; }
};
// =====================================================
// Global Fcs
// =====================================================
void createGlFontBitmaps(uint32 &base, const string &type, int size, int width, int charCount, FontMetrics &metrics);
void createGlFontOutlines(uint32 &base, const string &type, int width, float depth, int charCount, FontMetrics &metrics);
const char *getPlatformExtensions(const PlatformContextGl *pcgl);
void* getGlProcAddress(const char *procName);
}}//end namespace
#endif

View File

@ -94,7 +94,7 @@ void Mesh::updateInterpolationVertices(float t, bool cycle) const{
void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeaderV2 meshHeader;
fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
size_t readBytes = fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
@ -129,21 +129,21 @@ void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
readBytes = fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
readBytes = fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(textures[mtDiffuse]!=NULL){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
readBytes = fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
fread(&diffuseColor, sizeof(Vec3f), 1, f);
fread(&opacity, sizeof(float32), 1, f);
readBytes = fread(&diffuseColor, sizeof(Vec3f), 1, f);
readBytes = fread(&opacity, sizeof(float32), 1, f);
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
fread(indices, sizeof(uint32)*indexCount, 1, f);
readBytes = fread(indices, sizeof(uint32)*indexCount, 1, f);
}
void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeaderV3 meshHeader;
fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
size_t readBytes = fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
@ -174,23 +174,23 @@ void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
readBytes = fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
readBytes = fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(textures[mtDiffuse]!=NULL){
for(int i=0; i<meshHeader.texCoordFrameCount; ++i){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
readBytes = fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
}
fread(&diffuseColor, sizeof(Vec3f), 1, f);
fread(&opacity, sizeof(float32), 1, f);
readBytes = fread(&diffuseColor, sizeof(Vec3f), 1, f);
readBytes = fread(&opacity, sizeof(float32), 1, f);
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
fread(indices, sizeof(uint32)*indexCount, 1, f);
readBytes = fread(indices, sizeof(uint32)*indexCount, 1, f);
}
void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
//read header
MeshHeader meshHeader;
fread(&meshHeader, sizeof(MeshHeader), 1, f);
size_t readBytes = fread(&meshHeader, sizeof(MeshHeader), 1, f);
//init
frameCount= meshHeader.frameCount;
@ -214,7 +214,7 @@ void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
for(int i=0; i<meshTextureCount; ++i){
if((meshHeader.textures & flag) && textureManager!=NULL){
uint8 cMapPath[mapPathSize];
fread(cMapPath, mapPathSize, 1, f);
readBytes = fread(cMapPath, mapPathSize, 1, f);
string mapPath= toLower(reinterpret_cast<char*>(cMapPath));
string mapFullPath= dir + "/" + mapPath;
@ -232,12 +232,12 @@ void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
}
//read data
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
readBytes = fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
readBytes = fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
if(meshHeader.textures!=0){
fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
readBytes = fread(texCoords, sizeof(Vec2f)*vertexCount, 1, f);
}
fread(indices, sizeof(uint32)*indexCount, 1, f);
readBytes = fread(indices, sizeof(uint32)*indexCount, 1, f);
//tangents
if(textures[mtNormal]!=NULL){
@ -440,7 +440,7 @@ void Model::loadG3d(const string &path){
//file header
FileHeader fileHeader;
fread(&fileHeader, sizeof(FileHeader), 1, f);
size_t readBytes = fread(&fileHeader, sizeof(FileHeader), 1, f);
if(strncmp(reinterpret_cast<char*>(fileHeader.id), "G3D", 3)!=0){
printf("In [%s::%s] file = [%s] fileheader.id = [%s][%c]\n",__FILE__,__FUNCTION__,path.c_str(),reinterpret_cast<char*>(fileHeader.id),fileHeader.id[0]);
@ -453,7 +453,7 @@ void Model::loadG3d(const string &path){
//model header
ModelHeader modelHeader;
fread(&modelHeader, sizeof(ModelHeader), 1, f);
readBytes = fread(&modelHeader, sizeof(ModelHeader), 1, f);
meshCount= modelHeader.meshCount;
if(modelHeader.type!=mtMorphMesh){
throw runtime_error("Invalid model type");
@ -469,7 +469,7 @@ void Model::loadG3d(const string &path){
//version 3
else if(fileHeader.version==3){
fread(&meshCount, sizeof(meshCount), 1, f);
readBytes = fread(&meshCount, sizeof(meshCount), 1, f);
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].loadV3(dir, f, textureManager);
@ -479,7 +479,7 @@ void Model::loadG3d(const string &path){
//version 2
else if(fileHeader.version==2){
fread(&meshCount, sizeof(meshCount), 1, f);
readBytes = fread(&meshCount, sizeof(meshCount), 1, f);
meshes= new Mesh[meshCount];
for(uint32 i=0; i<meshCount; ++i){
meshes[i].loadV2(dir, f, textureManager);

View File

@ -0,0 +1,876 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "pixmap.h"
#include <stdexcept>
#include <cstdio>
#include <cassert>
#include "util.h"
#include "math_util.h"
#include "random.h"
#include "leak_dumper.h"
using namespace Shared::Util;
using namespace std;
namespace Shared{ namespace Graphics{
using namespace Util;
// =====================================================
// file structs
// =====================================================
#pragma pack(push, 1)
struct BitmapFileHeader{
uint8 type1;
uint8 type2;
uint32 size;
uint16 reserved1;
uint16 reserved2;
uint32 offsetBits;
};
struct BitmapInfoHeader{
uint32 size;
int32 width;
int32 height;
uint16 planes;
uint16 bitCount;
uint32 compression;
uint32 sizeImage;
int32 xPelsPerMeter;
int32 yPelsPerMeter;
uint32 clrUsed;
uint32 clrImportant;
};
struct TargaFileHeader{
int8 idLength;
int8 colourMapType;
int8 dataTypeCode;
int16 colourMapOrigin;
int16 colourMapLength;
int8 colourMapDepth;
int16 xOrigin;
int16 yOrigin;
int16 width;
int16 height;
int8 bitsPerPixel;
int8 imageDescriptor;
};
#pragma pack(pop)
const int tgaUncompressedRgb= 2;
const int tgaUncompressedBw= 3;
// =====================================================
// class PixmapIoTga
// =====================================================
PixmapIoTga::PixmapIoTga(){
file= NULL;
}
PixmapIoTga::~PixmapIoTga(){
if(file!=NULL){
fclose(file);
}
}
void PixmapIoTga::openRead(const string &path){
file= fopen(path.c_str(),"rb");
if (file==NULL){
throw runtime_error("Can't open TGA file: "+ path);
}
//read header
TargaFileHeader fileHeader;
size_t readBytes = fread(&fileHeader, sizeof(TargaFileHeader), 1, file);
//check that we can load this tga file
if(fileHeader.idLength!=0){
throw runtime_error(path + ": id field is not 0");
}
if(fileHeader.dataTypeCode!=tgaUncompressedRgb && fileHeader.dataTypeCode!=tgaUncompressedBw){
throw runtime_error(path + ": only uncompressed BW and RGB targa images are supported");
}
//check bits per pixel
if(fileHeader.bitsPerPixel!=8 && fileHeader.bitsPerPixel!=24 && fileHeader.bitsPerPixel!=32){
throw runtime_error(path + ": only 8, 24 and 32 bit targa images are supported");
}
h= fileHeader.height;
w= fileHeader.width;
components= fileHeader.bitsPerPixel/8;
}
void PixmapIoTga::read(uint8 *pixels){
read(pixels, components);
}
void PixmapIoTga::read(uint8 *pixels, int components){
for(int i=0; i<h*w*components; i+=components){
uint8 r, g, b, a, l;
if(this->components==1){
size_t readBytes = fread(&l, 1, 1, file);
r= l;
g= l;
b= l;
a= 255;
}
else{
size_t readBytes = fread(&b, 1, 1, file);
readBytes = fread(&g, 1, 1, file);
readBytes = fread(&r, 1, 1, file);
if(this->components==4){
readBytes = fread(&a, 1, 1, file);
}
else{
a= 255;
}
l= (r+g+b)/3;
}
switch(components){
case 1:
pixels[i]= l;
break;
case 3:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
break;
case 4:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
pixels[i+3]= a;
break;
}
}
}
void PixmapIoTga::openWrite(const string &path, int w, int h, int components){
this->w= w;
this->h= h;
this->components= components;
file= fopen(path.c_str(),"wb");
if (file==NULL){
throw runtime_error("Can't open TGA file: "+ path);
}
TargaFileHeader fileHeader;
memset(&fileHeader, 0, sizeof(TargaFileHeader));
fileHeader.dataTypeCode= components==1? tgaUncompressedBw: tgaUncompressedRgb;
fileHeader.bitsPerPixel= components*8;
fileHeader.width= w;
fileHeader.height= h;
fileHeader.imageDescriptor= components==4? 8: 0;
fwrite(&fileHeader, sizeof(TargaFileHeader), 1, file);
}
void PixmapIoTga::write(uint8 *pixels){
if(components==1){
fwrite(pixels, h*w, 1, file);
}
else{
for(int i=0; i<h*w*components; i+=components){
fwrite(&pixels[i+2], 1, 1, file);
fwrite(&pixels[i+1], 1, 1, file);
fwrite(&pixels[i], 1, 1, file);
if(components==4){
fwrite(&pixels[i+3], 1, 1, file);
}
}
}
}
// =====================================================
// class PixmapIoBmp
// =====================================================
PixmapIoBmp::PixmapIoBmp(){
file= NULL;
}
PixmapIoBmp::~PixmapIoBmp(){
if(file!=NULL){
fclose(file);
}
}
void PixmapIoBmp::openRead(const string &path){
file= fopen(path.c_str(),"rb");
if (file==NULL){
throw runtime_error("Can't open BMP file: "+ path);
}
//read file header
BitmapFileHeader fileHeader;
size_t readBytes = fread(&fileHeader, sizeof(BitmapFileHeader), 1, file);
if(fileHeader.type1!='B' || fileHeader.type2!='M'){
throw runtime_error(path +" is not a bitmap");
}
//read info header
BitmapInfoHeader infoHeader;
readBytes = fread(&infoHeader, sizeof(BitmapInfoHeader), 1, file);
if(infoHeader.bitCount!=24){
throw runtime_error(path+" is not a 24 bit bitmap");
}
h= infoHeader.height;
w= infoHeader.width;
components= 3;
}
void PixmapIoBmp::read(uint8 *pixels){
read(pixels, 3);
}
void PixmapIoBmp::read(uint8 *pixels, int components){
for(int i=0; i<h*w*components; i+=components){
uint8 r, g, b;
size_t readBytes = fread(&b, 1, 1, file);
readBytes = fread(&g, 1, 1, file);
readBytes = fread(&r, 1, 1, file);
switch(components){
case 1:
pixels[i]= (r+g+b)/3;
break;
case 3:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
break;
case 4:
pixels[i]= r;
pixels[i+1]= g;
pixels[i+2]= b;
pixels[i+3]= 255;
break;
}
}
}
void PixmapIoBmp::openWrite(const string &path, int w, int h, int components){
this->w= w;
this->h= h;
this->components= components;
file= fopen(path.c_str(),"wb");
if (file==NULL){
throw runtime_error("Can't open BMP file for writting: "+ path);
}
BitmapFileHeader fileHeader;
fileHeader.type1='B';
fileHeader.type2='M';
fileHeader.offsetBits=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader);
fileHeader.size=sizeof(BitmapFileHeader)+sizeof(BitmapInfoHeader)+3*h*w;
fwrite(&fileHeader, sizeof(BitmapFileHeader), 1, file);
//info header
BitmapInfoHeader infoHeader;
infoHeader.bitCount=24;
infoHeader.clrImportant=0;
infoHeader.clrUsed=0;
infoHeader.compression=0;
infoHeader.height= h;
infoHeader.planes=1;
infoHeader.size=sizeof(BitmapInfoHeader);
infoHeader.sizeImage=0;
infoHeader.width= w;
infoHeader.xPelsPerMeter= 0;
infoHeader.yPelsPerMeter= 0;
fwrite(&infoHeader, sizeof(BitmapInfoHeader), 1, file);
}
void PixmapIoBmp::write(uint8 *pixels){
for (int i=0; i<h*w*components; i+=components){
fwrite(&pixels[i+2], 1, 1, file);
fwrite(&pixels[i+1], 1, 1, file);
fwrite(&pixels[i], 1, 1, file);
}
}
// =====================================================
// class Pixmap1D
// =====================================================
// ===================== PUBLIC ========================
Pixmap1D::Pixmap1D(){
w= -1;
components= -1;
pixels= NULL;
}
Pixmap1D::Pixmap1D(int components){
init(components);
}
Pixmap1D::Pixmap1D(int w, int components){
init(w, components);
}
void Pixmap1D::init(int components){
this->w= -1;
this->components= components;
pixels= NULL;
}
void Pixmap1D::init(int w, int components){
this->w= w;
this->components= components;
pixels= new uint8[w*components];
}
Pixmap1D::~Pixmap1D(){
delete [] pixels;
}
void Pixmap1D::load(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
loadBmp(path);
}
else if(extension=="tga"){
loadTga(path);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap1D::loadBmp(const string &path){
PixmapIoBmp plb;
plb.openRead(path);
//init
if(plb.getH()==1){
w= plb.getW();
}
else if(plb.getW()==1){
w= plb.getH();
}
else{
throw runtime_error("One of the texture dimensions must be 1");
}
if(components==-1){
components= 3;
}
if(pixels==NULL){
pixels= new uint8[w*components];
}
//data
plb.read(pixels, components);
}
void Pixmap1D::loadTga(const string &path){
PixmapIoTga plt;
plt.openRead(path);
//init
if(plt.getH()==1){
w= plt.getW();
}
else if(plt.getW()==1){
w= plt.getH();
}
else{
throw runtime_error("One of the texture dimensions must be 1");
}
int fileComponents= plt.getComponents();
if(components==-1){
components= fileComponents;
}
if(pixels==NULL){
pixels= new uint8[w*components];
}
//read data
plt.read(pixels, components);
}
// =====================================================
// class Pixmap2D
// =====================================================
// ===================== PUBLIC ========================
Pixmap2D::Pixmap2D(){
h= -1;
w= -1;
components= -1;
pixels= NULL;
}
Pixmap2D::Pixmap2D(int components){
init(components);
}
Pixmap2D::Pixmap2D(int w, int h, int components){
init(w, h, components);
}
void Pixmap2D::init(int components){
this->w= -1;
this->h= -1;
this->components= components;
pixels= NULL;
}
void Pixmap2D::init(int w, int h, int components){
this->w= w;
this->h= h;
this->components= components;
pixels= new uint8[h*w*components];
}
Pixmap2D::~Pixmap2D(){
delete [] pixels;
}
void Pixmap2D::load(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
loadBmp(path);
}
else if(extension=="tga"){
loadTga(path);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap2D::loadBmp(const string &path){
PixmapIoBmp plb;
plb.openRead(path);
//init
w= plb.getW();
h= plb.getH();
if(components==-1){
components= 3;
}
if(pixels==NULL){
pixels= new uint8[w*h*components];
}
//data
plb.read(pixels, components);
}
void Pixmap2D::loadTga(const string &path){
PixmapIoTga plt;
plt.openRead(path);
w= plt.getW();
h= plt.getH();
//header
int fileComponents= plt.getComponents();
//init
if(components==-1){
components= fileComponents;
}
if(pixels==NULL){
pixels= new uint8[w*h*components];
}
//read data
plt.read(pixels, components);
}
void Pixmap2D::save(const string &path){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
saveBmp(path);
}
else if(extension=="tga"){
saveTga(path);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap2D::saveBmp(const string &path){
PixmapIoBmp psb;
psb.openWrite(path, w, h, components);
psb.write(pixels);
}
void Pixmap2D::saveTga(const string &path){
PixmapIoTga pst;
pst.openWrite(path, w, h, components);
pst.write(pixels);
}
void Pixmap2D::getPixel(int x, int y, uint8 *value) const{
for(int i=0; i<components; ++i){
value[i]= pixels[(w*y+x)*components+i];
}
}
void Pixmap2D::getPixel(int x, int y, float32 *value) const{
for(int i=0; i<components; ++i){
value[i]= pixels[(w*y+x)*components+i]/255.f;
}
}
void Pixmap2D::getComponent(int x, int y, int component, uint8 &value) const{
value= pixels[(w*y+x)*components+component];
}
void Pixmap2D::getComponent(int x, int y, int component, float32 &value) const{
value= pixels[(w*y+x)*components+component]/255.f;
}
//vector get
Vec4f Pixmap2D::getPixel4f(int x, int y) const{
Vec4f v(0.f);
for(int i=0; i<components && i<4; ++i){
v.ptr()[i]= pixels[(w*y+x)*components+i]/255.f;
}
return v;
}
Vec3f Pixmap2D::getPixel3f(int x, int y) const{
Vec3f v(0.f);
for(int i=0; i<components && i<3; ++i){
v.ptr()[i]= pixels[(w*y+x)*components+i]/255.f;
}
return v;
}
float Pixmap2D::getPixelf(int x, int y) const{
return pixels[(w*y+x)*components]/255.f;
}
float Pixmap2D::getComponentf(int x, int y, int component) const{
float c;
getComponent(x, y, component, c);
return c;
}
void Pixmap2D::setPixel(int x, int y, const uint8 *value){
for(int i=0; i<components; ++i){
pixels[(w*y+x)*components+i]= value[i];
}
}
void Pixmap2D::setPixel(int x, int y, const float32 *value){
for(int i=0; i<components; ++i){
pixels[(w*y+x)*components+i]= static_cast<uint8>(value[i]*255.f);
}
}
void Pixmap2D::setComponent(int x, int y, int component, uint8 value){
pixels[(w*y+x)*components+component]= value;
}
void Pixmap2D::setComponent(int x, int y, int component, float32 value){
pixels[(w*y+x)*components+component]= static_cast<uint8>(value*255.f);
}
//vector set
void Pixmap2D::setPixel(int x, int y, const Vec3f &p){
for(int i=0; i<components && i<3; ++i){
pixels[(w*y+x)*components+i]= static_cast<uint8>(p.ptr()[i]*255.f);
}
}
void Pixmap2D::setPixel(int x, int y, const Vec4f &p){
for(int i=0; i<components && i<4; ++i){
pixels[(w*y+x)*components+i]= static_cast<uint8>(p.ptr()[i]*255.f);
}
}
void Pixmap2D::setPixel(int x, int y, float p){
pixels[(w*y+x)*components]= static_cast<uint8>(p*255.f);
}
void Pixmap2D::setPixels(const uint8 *value){
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setPixel(i, j, value);
}
}
}
void Pixmap2D::setPixels(const float32 *value){
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setPixel(i, j, value);
}
}
}
void Pixmap2D::setComponents(int component, uint8 value){
assert(component<components);
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setComponent(i, j, component, value);
}
}
}
void Pixmap2D::setComponents(int component, float32 value){
assert(component<components);
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setComponent(i, j, component, value);
}
}
}
float splatDist(Vec2i a, Vec2i b){
return (max(abs(a.x-b.x),abs(a.y- b.y)) + 3.f*a.dist(b))/4.f;
}
void Pixmap2D::splat(const Pixmap2D *leftUp, const Pixmap2D *rightUp, const Pixmap2D *leftDown, const Pixmap2D *rightDown){
Random random;
assert(components==3 || components==4);
if(
!doDimensionsAgree(leftUp) ||
!doDimensionsAgree(rightUp) ||
!doDimensionsAgree(leftDown) ||
!doDimensionsAgree(rightDown))
{
throw runtime_error("Pixmap2D::splat: pixmap dimensions don't agree");
}
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
float avg= (w+h)/2.f;
float distLu= splatDist(Vec2i(i, j), Vec2i(0, 0));
float distRu= splatDist(Vec2i(i, j), Vec2i(w, 0));
float distLd= splatDist(Vec2i(i, j), Vec2i(0, h));
float distRd= splatDist(Vec2i(i, j), Vec2i(w, h));
const float powFactor= 2.0f;
distLu= pow(distLu, powFactor);
distRu= pow(distRu, powFactor);
distLd= pow(distLd, powFactor);
distRd= pow(distRd, powFactor);
avg= pow(avg, powFactor);
float lu= distLu>avg? 0: ((avg-distLu))*random.randRange(0.5f, 1.0f);
float ru= distRu>avg? 0: ((avg-distRu))*random.randRange(0.5f, 1.0f);
float ld= distLd>avg? 0: ((avg-distLd))*random.randRange(0.5f, 1.0f);
float rd= distRd>avg? 0: ((avg-distRd))*random.randRange(0.5f, 1.0f);
float total= lu+ru+ld+rd;
Vec4f pix= (leftUp->getPixel4f(i, j)*lu+
rightUp->getPixel4f(i, j)*ru+
leftDown->getPixel4f(i, j)*ld+
rightDown->getPixel4f(i, j)*rd)*(1.0f/total);
setPixel(i, j, pix);
}
}
}
void Pixmap2D::lerp(float t, const Pixmap2D *pixmap1, const Pixmap2D *pixmap2){
if(
!doDimensionsAgree(pixmap1) ||
!doDimensionsAgree(pixmap2))
{
throw runtime_error("Pixmap2D::lerp: pixmap dimensions don't agree");
}
for(int i=0; i<w; ++i){
for(int j=0; j<h; ++j){
setPixel(i, j, pixmap1->getPixel4f(i, j).lerp(t, pixmap2->getPixel4f(i, j)));
}
}
}
void Pixmap2D::copy(const Pixmap2D *sourcePixmap){
assert(components==sourcePixmap->getComponents());
if(w!=sourcePixmap->getW() || h!=sourcePixmap->getH()){
throw runtime_error("Pixmap2D::copy() dimensions must agree");
}
memcpy(pixels, sourcePixmap->getPixels(), w*h*sourcePixmap->getComponents());
}
void Pixmap2D::subCopy(int x, int y, const Pixmap2D *sourcePixmap){
assert(components==sourcePixmap->getComponents());
if(w<sourcePixmap->getW() && h<sourcePixmap->getH()){
throw runtime_error("Pixmap2D::subCopy(), bad dimensions");
}
uint8 *pixel= new uint8[components];
for(int i=0; i<sourcePixmap->getW(); ++i){
for(int j=0; j<sourcePixmap->getH(); ++j){
sourcePixmap->getPixel(i, j, pixel);
setPixel(i+x, j+y, pixel);
}
}
delete pixel;
}
bool Pixmap2D::doDimensionsAgree(const Pixmap2D *pixmap){
return pixmap->getW() == w && pixmap->getH() == h;
}
// =====================================================
// class Pixmap3D
// =====================================================
Pixmap3D::Pixmap3D(){
w= -1;
h= -1;
d= -1;
components= -1;
}
Pixmap3D::Pixmap3D(int w, int h, int d, int components){
init(w, h, d, components);
}
Pixmap3D::Pixmap3D(int d, int components){
init(d, components);
}
void Pixmap3D::init(int w, int h, int d, int components){
this->w= w;
this->h= h;
this->d= d;
this->components= components;
pixels= new uint8[h*w*d*components];;
}
void Pixmap3D::init(int d, int components){
this->w= -1;
this->h= -1;
this->d= d;
this->components= components;
pixels= NULL;
}
Pixmap3D::~Pixmap3D(){
delete [] pixels;
}
void Pixmap3D::loadSlice(const string &path, int slice){
string extension= path.substr(path.find_last_of('.')+1);
if(extension=="bmp"){
loadSliceBmp(path, slice);
}
else if(extension=="tga"){
loadSliceTga(path, slice);
}
else{
throw runtime_error("Unknown pixmap extension: "+extension);
}
}
void Pixmap3D::loadSliceBmp(const string &path, int slice){
PixmapIoBmp plb;
plb.openRead(path);
//init
w= plb.getW();
h= plb.getH();
if(components==-1){
components= 3;
}
if(pixels==NULL){
pixels= new uint8[w*h*d*components];
}
//data
plb.read(&pixels[slice*w*h*components], components);
}
void Pixmap3D::loadSliceTga(const string &path, int slice){
PixmapIoTga plt;
plt.openRead(path);
//header
int fileComponents= plt.getComponents();
//init
w= plt.getW();
h= plt.getH();
if(components==-1){
components= fileComponents;
}
if(pixels==NULL){
pixels= new uint8[w*h*d*components];
}
//read data
plt.read(&pixels[slice*w*h*components], components);
}
// =====================================================
// class PixmapCube
// =====================================================
void PixmapCube::init(int w, int h, int components){
for(int i=0; i<6; ++i){
faces[i].init(w, h, components);
}
}
//load & save
void PixmapCube::loadFace(const string &path, int face){
faces[face].load(path);
}
void PixmapCube::loadFaceBmp(const string &path, int face){
faces[face].loadBmp(path);
}
void PixmapCube::loadFaceTga(const string &path, int face){
faces[face].loadTga(path);
}
}}//end namespace

View File

@ -0,0 +1,70 @@
// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#include "checksum.h"
#include <cassert>
#include <stdexcept>
#include "util.h"
#include "leak_dumper.h"
using namespace std;
namespace Shared{ namespace Util{
// =====================================================
// class Checksum
// =====================================================
Checksum::Checksum(){
sum= 0;
r= 55665;
c1= 52845;
c2= 22719;
}
void Checksum::addByte(int8 value){
int32 cipher= (value ^ (r >> 8));
r= (cipher + r) * c1 + c2;
sum+= cipher;
}
void Checksum::addString(const string &value){
for(int i= 0; i<value.size(); ++i){
addByte(value[i]);
}
}
void Checksum::addFile(const string &path){
FILE* file= fopen(path.c_str(), "rb");
if(file!=NULL){
addString(lastFile(path));
while(!feof(file)){
int8 byte= 0;
size_t readBytes = fread(&byte, 1, 1, file);
addByte(byte);
}
}
else
{
throw runtime_error("Can not open file: " + path);
}
fclose(file);
}
}}//end namespace