Cleaned up all compiler warnings
This commit is contained in:
parent
2012b7e22c
commit
ff60b09158
|
@ -74,6 +74,7 @@ if $(WX_AVAILABLE) = "yes" {
|
||||||
}
|
}
|
||||||
|
|
||||||
### Viewer ###
|
### Viewer ###
|
||||||
|
if $(WX_AVAILABLE) = "yes" {
|
||||||
SubDir TOP g3d_viewer ;
|
SubDir TOP g3d_viewer ;
|
||||||
|
|
||||||
GLEST_VIEWER_DIRS = . ;
|
GLEST_VIEWER_DIRS = . ;
|
||||||
|
@ -85,6 +86,7 @@ if $(WX_AVAILABLE) = "yes" {
|
||||||
LinkWith glest_g3dviewer : glestlib ;
|
LinkWith glest_g3dviewer : glestlib ;
|
||||||
ExternalLibs glest_g3dviewer : SDL GL GLU WX ;
|
ExternalLibs glest_g3dviewer : SDL GL GLU WX ;
|
||||||
IncludeDir glest_g3dviewer : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_VIEWER_DIRS) ;
|
IncludeDir glest_g3dviewer : ../shared_lib/include/$(LIB_INCLUDE_DIRS) $(GLEST_VIEWER_DIRS) ;
|
||||||
|
}
|
||||||
|
|
||||||
### Configurator ###
|
### Configurator ###
|
||||||
SubDir TOP configurator ;
|
SubDir TOP configurator ;
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "graphics_factory_gl.h"
|
//#include "graphics_factory_gl.h"
|
||||||
|
#include "model_gl.h"
|
||||||
#include "graphics_interface.h"
|
#include "graphics_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "conversion.h"
|
#include "conversion.h"
|
||||||
|
|
|
@ -3,14 +3,11 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <wx/wx.h>
|
#include <wx/wx.h>
|
||||||
#include <wx/glcanvas.h>
|
#include <wx/glcanvas.h>
|
||||||
|
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
//#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
//using Shared::Platform::Window;
|
|
||||||
//using Shared::Platform::MouseState;
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
||||||
#include "opengl.h"
|
|
||||||
//#include "texture_gl.h"
|
|
||||||
#include "graphics_factory_gl.h"
|
#include "graphics_factory_gl.h"
|
||||||
#include "graphics_interface.h"
|
#include "graphics_interface.h"
|
||||||
|
|
||||||
//#include "factory_repository.h"
|
|
||||||
|
|
||||||
using namespace Shared::Graphics;
|
using namespace Shared::Graphics;
|
||||||
using namespace Shared::Graphics::Gl;
|
using namespace Shared::Graphics::Gl;
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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 ¢er, 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
|
|
@ -9,8 +9,6 @@
|
||||||
// License, or (at your option) any later version
|
// License, or (at your option) any later version
|
||||||
// ==============================================================
|
// ==============================================================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -94,7 +94,7 @@ void Mesh::updateInterpolationVertices(float t, bool cycle) const{
|
||||||
void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
|
void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
//read header
|
//read header
|
||||||
MeshHeaderV2 meshHeader;
|
MeshHeaderV2 meshHeader;
|
||||||
fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
|
size_t readBytes = fread(&meshHeader, sizeof(MeshHeaderV2), 1, f);
|
||||||
|
|
||||||
|
|
||||||
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
|
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
|
||||||
|
@ -129,21 +129,21 @@ void Mesh::loadV2(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
}
|
}
|
||||||
|
|
||||||
//read data
|
//read data
|
||||||
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
readBytes = fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||||
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
readBytes = fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||||
if(textures[mtDiffuse]!=NULL){
|
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);
|
readBytes = fread(&diffuseColor, sizeof(Vec3f), 1, f);
|
||||||
fread(&opacity, sizeof(float32), 1, f);
|
readBytes = fread(&opacity, sizeof(float32), 1, f);
|
||||||
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
|
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){
|
void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
//read header
|
//read header
|
||||||
MeshHeaderV3 meshHeader;
|
MeshHeaderV3 meshHeader;
|
||||||
fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
|
size_t readBytes = fread(&meshHeader, sizeof(MeshHeaderV3), 1, f);
|
||||||
|
|
||||||
|
|
||||||
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
|
if(meshHeader.normalFrameCount!=meshHeader.vertexFrameCount){
|
||||||
|
@ -174,23 +174,23 @@ void Mesh::loadV3(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
}
|
}
|
||||||
|
|
||||||
//read data
|
//read data
|
||||||
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
readBytes = fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||||
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
readBytes = fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||||
if(textures[mtDiffuse]!=NULL){
|
if(textures[mtDiffuse]!=NULL){
|
||||||
for(int i=0; i<meshHeader.texCoordFrameCount; ++i){
|
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);
|
readBytes = fread(&diffuseColor, sizeof(Vec3f), 1, f);
|
||||||
fread(&opacity, sizeof(float32), 1, f);
|
readBytes = fread(&opacity, sizeof(float32), 1, f);
|
||||||
fseek(f, sizeof(Vec4f)*(meshHeader.colorFrameCount-1), SEEK_CUR);
|
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){
|
void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
//read header
|
//read header
|
||||||
MeshHeader meshHeader;
|
MeshHeader meshHeader;
|
||||||
fread(&meshHeader, sizeof(MeshHeader), 1, f);
|
size_t readBytes = fread(&meshHeader, sizeof(MeshHeader), 1, f);
|
||||||
|
|
||||||
//init
|
//init
|
||||||
frameCount= meshHeader.frameCount;
|
frameCount= meshHeader.frameCount;
|
||||||
|
@ -214,7 +214,7 @@ void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
for(int i=0; i<meshTextureCount; ++i){
|
for(int i=0; i<meshTextureCount; ++i){
|
||||||
if((meshHeader.textures & flag) && textureManager!=NULL){
|
if((meshHeader.textures & flag) && textureManager!=NULL){
|
||||||
uint8 cMapPath[mapPathSize];
|
uint8 cMapPath[mapPathSize];
|
||||||
fread(cMapPath, mapPathSize, 1, f);
|
readBytes = fread(cMapPath, mapPathSize, 1, f);
|
||||||
string mapPath= toLower(reinterpret_cast<char*>(cMapPath));
|
string mapPath= toLower(reinterpret_cast<char*>(cMapPath));
|
||||||
|
|
||||||
string mapFullPath= dir + "/" + mapPath;
|
string mapFullPath= dir + "/" + mapPath;
|
||||||
|
@ -232,12 +232,12 @@ void Mesh::load(const string &dir, FILE *f, TextureManager *textureManager){
|
||||||
}
|
}
|
||||||
|
|
||||||
//read data
|
//read data
|
||||||
fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
readBytes = fread(vertices, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||||
fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
readBytes = fread(normals, sizeof(Vec3f)*frameCount*vertexCount, 1, f);
|
||||||
if(meshHeader.textures!=0){
|
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
|
//tangents
|
||||||
if(textures[mtNormal]!=NULL){
|
if(textures[mtNormal]!=NULL){
|
||||||
|
@ -440,7 +440,7 @@ void Model::loadG3d(const string &path){
|
||||||
|
|
||||||
//file header
|
//file header
|
||||||
FileHeader fileHeader;
|
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){
|
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]);
|
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
|
//model header
|
||||||
ModelHeader modelHeader;
|
ModelHeader modelHeader;
|
||||||
fread(&modelHeader, sizeof(ModelHeader), 1, f);
|
readBytes = fread(&modelHeader, sizeof(ModelHeader), 1, f);
|
||||||
meshCount= modelHeader.meshCount;
|
meshCount= modelHeader.meshCount;
|
||||||
if(modelHeader.type!=mtMorphMesh){
|
if(modelHeader.type!=mtMorphMesh){
|
||||||
throw runtime_error("Invalid model type");
|
throw runtime_error("Invalid model type");
|
||||||
|
@ -469,7 +469,7 @@ void Model::loadG3d(const string &path){
|
||||||
//version 3
|
//version 3
|
||||||
else if(fileHeader.version==3){
|
else if(fileHeader.version==3){
|
||||||
|
|
||||||
fread(&meshCount, sizeof(meshCount), 1, f);
|
readBytes = fread(&meshCount, sizeof(meshCount), 1, f);
|
||||||
meshes= new Mesh[meshCount];
|
meshes= new Mesh[meshCount];
|
||||||
for(uint32 i=0; i<meshCount; ++i){
|
for(uint32 i=0; i<meshCount; ++i){
|
||||||
meshes[i].loadV3(dir, f, textureManager);
|
meshes[i].loadV3(dir, f, textureManager);
|
||||||
|
@ -479,7 +479,7 @@ void Model::loadG3d(const string &path){
|
||||||
//version 2
|
//version 2
|
||||||
else if(fileHeader.version==2){
|
else if(fileHeader.version==2){
|
||||||
|
|
||||||
fread(&meshCount, sizeof(meshCount), 1, f);
|
readBytes = fread(&meshCount, sizeof(meshCount), 1, f);
|
||||||
meshes= new Mesh[meshCount];
|
meshes= new Mesh[meshCount];
|
||||||
for(uint32 i=0; i<meshCount; ++i){
|
for(uint32 i=0; i<meshCount; ++i){
|
||||||
meshes[i].loadV2(dir, f, textureManager);
|
meshes[i].loadV2(dir, f, textureManager);
|
||||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue