1
0
forked from 0ad/0ad

Heightmap importing in Atlas

This was SVN commit r12308.
This commit is contained in:
myconid 2012-08-07 18:49:46 +00:00
parent e488eb4d6f
commit c9abf6f68c
4 changed files with 119 additions and 0 deletions

View File

@ -309,6 +309,7 @@ enum
ID_Open,
ID_Save,
ID_SaveAs,
ID_ImportHeightmap,
ID_Wireframe,
ID_MessageTrace,
@ -332,6 +333,7 @@ BEGIN_EVENT_TABLE(ScenarioEditor, wxFrame)
EVT_MENU(ID_Open, ScenarioEditor::OnOpen)
EVT_MENU(ID_Save, ScenarioEditor::OnSave)
EVT_MENU(ID_SaveAs, ScenarioEditor::OnSaveAs)
EVT_MENU(ID_ImportHeightmap, ScenarioEditor::OnImportHeightmap)
EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, ScenarioEditor::OnMRUFile)
EVT_MENU(ID_Quit, ScenarioEditor::OnQuit)
@ -418,6 +420,8 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent, ScriptInterface& scriptInterfac
menuFile->Append(ID_Save, _("&Save"));
menuFile->Append(ID_SaveAs, _("Save &As..."));
menuFile->AppendSeparator();//-----------
menuFile->Append(ID_ImportHeightmap, _("&Import Heightmap..."));
menuFile->AppendSeparator();//-----------
menuFile->Append(ID_Quit, _("E&xit"));
m_FileHistory.UseMenu(menuFile);//-------
m_FileHistory.AddFilesToMenu();
@ -713,6 +717,28 @@ void ScenarioEditor::OnOpen(wxCommandEvent& WXUNUSED(event))
// TODO: Make this a non-undoable command
}
void ScenarioEditor::OnImportHeightmap(wxCommandEvent& WXUNUSED(event))
{
wxFileDialog dlg (NULL, wxFileSelectorPromptStr,
_T(""), _T(""),
_T("Valid Image files|*.png;*.jpg;*.bmp|All files (*.*)|*.*"),
wxFD_OPEN);
// Set default filter
dlg.SetFilterIndex(0);
wxString cwd = wxFileName::GetCwd();
if (dlg.ShowModal() != wxID_OK)
return;
OpenFile(_T("_default"), _T(""));
std::wstring image(dlg.GetPath().wc_str());
POST_MESSAGE(ImportHeightmap, (image));
// TODO: Make this a non-undoable command
}
void ScenarioEditor::OnMRUFile(wxCommandEvent& event)
{
wxString filename(m_FileHistory.GetHistoryFile(event.GetId() - wxID_FILE1));

View File

@ -42,6 +42,7 @@ public:
void OnOpen(wxCommandEvent& event);
void OnSave(wxCommandEvent& event);
void OnSaveAs(wxCommandEvent& event);
void OnImportHeightmap(wxCommandEvent& event);
void OnMRUFile(wxCommandEvent& event);
void OnQuit(wxCommandEvent& event);

View File

@ -28,6 +28,12 @@
#include "graphics/Terrain.h"
#include "graphics/TerrainTextureEntry.h"
#include "graphics/TerrainTextureManager.h"
#include "lib/bits.h"
#include "lib/file/file.h"
#include "lib/tex/tex.h"
#include "maths/MathUtil.h"
#include "ps/CLogger.h"
#include "ps/Filesystem.h"
#include "ps/Game.h"
#include "ps/Loader.h"
#include "ps/World.h"
@ -135,6 +141,88 @@ MESSAGEHANDLER(LoadMap)
StartGame(attrs);
}
MESSAGEHANDLER(ImportHeightmap)
{
CStrW src = *msg->filename;
size_t fileSize;
shared_ptr<u8> fileData;
// read in image file
File file;
if (file.Open(src, O_RDONLY) < 0)
{
LOGERROR(L"Failed to load heightmap.");
return;
}
fileSize = lseek(file.Descriptor(), 0, SEEK_END);
lseek(file.Descriptor(), 0, SEEK_SET);
fileData = shared_ptr<u8>(new u8[fileSize]);
if (read(file.Descriptor(), fileData.get(), fileSize) < 0)
{
LOGERROR(L"Failed to read heightmap image.");
file.Close();
return;
}
file.Close();
// decode to a raw pixel format
Tex tex;
if (tex_decode(fileData, fileSize, &tex) < 0)
{
LOGERROR(L"Failed to decode heightmap.");
return;
}
// Convert to uncompressed BGRA with no mipmaps
if (tex_transform_to(&tex, (tex.flags | TEX_BGR | TEX_ALPHA) & ~(TEX_DXT | TEX_MIPMAPS)) < 0)
{
LOGERROR(L"Failed to transform heightmap.");
tex_free(&tex);
return;
}
// pick smallest side of texture; truncate if not divisible by PATCH_SIZE
ssize_t terrainSize = std::min(tex.w, tex.h);
terrainSize -= terrainSize % PATCH_SIZE;
// resize terrain to heightmap size
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
terrain->Resize(terrainSize / PATCH_SIZE);
// copy heightmap data into map
u16* heightmap = g_Game->GetWorld()->GetTerrain()->GetHeightMap();
ssize_t hmSize = g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide();
u8* mapdata = tex_get_data(&tex);
ssize_t bytesPP = tex.bpp / 8;
ssize_t mapLineSkip = tex.w * bytesPP;
for (ssize_t y = 0; y < terrainSize; ++y)
{
for (ssize_t x = 0; x < terrainSize; ++x)
{
int offset = y * mapLineSkip + x * bytesPP;
// pick colour channel with highest value
u16 value = std::max(mapdata[offset+bytesPP*2], std::max(mapdata[offset], mapdata[offset+bytesPP]));
heightmap[(terrainSize-y-1) * hmSize + x] = clamp(value * 256, 0, 65535);
}
}
tex_free(&tex);
// update simulation
CmpPtr<ICmpTerrain> cmpTerrain(*g_Game->GetSimulation2(), SYSTEM_ENTITY);
if (cmpTerrain) cmpTerrain->ReloadTerrain();
g_Game->GetView()->GetLOSTexture().MakeDirty();
}
MESSAGEHANDLER(SaveMap)
{
CMapWriter writer;

View File

@ -146,6 +146,10 @@ QUERY(GenerateMap,
((int, status))
);
MESSAGE(ImportHeightmap,
((std::wstring, filename))
);
MESSAGE(LoadMap,
((std::wstring, filename))
);