Files
Webcam/include/engine/core/terrain_nml.cpp

195 lines
5.6 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "core/terrain.h"
#include "core/engine.h"
#include "core/embedded_resource_handler_interface.h"
#include "picture/pict_io.h"
#include "filesystem/filesystem.h"
#include "platform.h"
#include "log/log.h"
using namespace GS::Core;
using GS::NML::Tag;
//------------------------------------------------------------------------------
bool Terrain::LoadHeightmap(const char *uri)
{
if (Platform::Get().io->FileSize(uri) != (size_t)(4 * heightmap_w * heightmap_h))
__ERR__(__LOG_W__ << "Corrupt heightmap data in " << uri << ", incorrect data size.\n", false)
AutoPtr <IO::Handle> h(Platform::Get().io->Open(uri));
if (h.IsNull())
return false;
float *ph = heightmap;
for (int v = 0; v < heightmap_h; ++v)
{
h->Read(ph, heightmap_w * 4);
ph += heightmap_w;
ph[0] = ph[-1];
ph++;
}
for (int u = 0; u < heightmap_w; ++u)
{
ph[0] = ph[-(heightmap_w + 1)];
ph++;
}
return true;
}
bool Terrain::SaveHeightmap(const char *uri)
{
AutoPtr <IO::Handle> h(Platform::Get().io->Open(uri, IO::ModeWrite));
if (h.IsNull())
return false;
float *ph = heightmap;
for (int v = 0; v < heightmap_h; ++v)
{
h->Write(ph, heightmap_w * 4);
ph += heightmap_w + 1;
}
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
bool Terrain::FromMetaTag(Tag &tag)
{
if (tag.name != "Terrain")
__ERR__(__LOG_E__ << "Could not parse terrain, incorrect root tag (" << tag.name << ").\n", false)
NMLTagForeach(pt, tag)
{
if (pt->name == "Item")
Item::FromMetaTag(*pt);
else if (pt->name == "Width")
width = pt->GetReal();
else if (pt->name == "Height")
depth = pt->GetReal();
else if (pt->name == "Material") // Legacy path, embedded material.
IEmbeddedResourceHandler::Get()->ExtractEmbeddedMaterial(material, *pt, "terrain", 0);
else if (pt->name == "MaterialName")
material = pt->GetString();
else if (pt->name == "Layers")
{
NMLTagForeach(layer_tag, *pt)
if (layer_tag->name == "Layer")
{
Tag *index_tag = layer_tag->GetTag("Index");
Layer &l = layer[index_tag ? index_tag->GetInteger() : 0];
if (layer_tag->GetTag("Enabled;"))
l.enabled = true;
if (Tag *map = layer_tag->GetTag("Diffuse;"))
l.diffuse = map->GetString();
if (Tag *map = layer_tag->GetTag("Normal;"))
l.normal = map->GetString();
if (Tag *map = layer_tag->GetTag("Specular;"))
l.specular = map->GetString();
if (Tag *map = layer_tag->GetTag("Self;"))
l.self = map->GetString();
if (Tag *map = layer_tag->GetTag("UVAngle;"))
l.angle = map->GetReal();
if (Tag *map = layer_tag->GetTag("UVTiling;"))
l.tiling = map->GetReal();
}
}
else if (pt->name == "Shader")
shader_path = pt->GetString();
else if (pt->name == "Blendmap")
blendmap_path = pt->GetString();
else if (pt->name == "Heightmap")
{
Tag *w_tag = pt->GetTypedTag("Width;", Variant::VariantInteger),
*h_tag = pt->GetTypedTag("Height;", Variant::VariantInteger),
*d_tag = pt->GetTypedTag("Data;", Variant::VariantString),
*r_tag = pt->GetTypedTag("Resolution;", Variant::VariantFloat);
if (w_tag && h_tag && d_tag && r_tag)
if (Allocate(w_tag->GetInteger(), h_tag->GetInteger(), r_tag->GetReal()))
heightmap_path = d_tag->GetString();
}
else
__LOG_W__ << "Unknown tag '" << pt->name << "' in <Terrain>.\n";
}
return true;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Tag *Terrain::LayerAsMetaTag(int index)
{
Layer &l = layer[index];
Tag *layer_tag = new Tag("Layer");
if (!layer_tag)
__ERR__(__LOG_E__ << "Failed to serialize terrain layer " << index << ".\n", NULL)
layer_tag->AddChild("Index", index);
if (l.enabled)
layer_tag->AddChild(new Tag("Enabled"));
if (!l.diffuse.IsEmpty())
layer_tag->AddChild("Diffuse", l.diffuse.toUtf8());
if (!l.normal.IsEmpty())
layer_tag->AddChild("Normal", l.normal.toUtf8());
if (!l.specular.IsEmpty())
layer_tag->AddChild("Specular", l.specular.toUtf8());
if (!l.self.IsEmpty())
layer_tag->AddChild("Self", l.self.toUtf8());
layer_tag->AddChild("UVAngle", l.angle);
layer_tag->AddChild("UVTiling", l.tiling);
return layer_tag;
}
Tag *Terrain::AsMetaTag()
{
Tag *root = new Tag("Terrain");
if (!root)
__ERR__(__LOG_E__ << "Could not serialize terrain. Failed to create root tag.\n", NULL)
// Store item.
root->AddChild(Item::AsMetaTag());
// Store terrain.
root->AddChild("Width", width);
root->AddChild("Height", depth);
if (!material.IsEmpty())
root->AddChild("MaterialName", material.c_str());
// Store layers.
if (Tag *layers_tag = root->AddChild("Layers"))
for (int n = 0; n < 4; ++n)
layers_tag->AddChild(LayerAsMetaTag(n));
root->AddChild("Blendmap", blendmap_path.c_str());
root->AddChild("Shader", shader_path.c_str());
// Store heightmap.
if (Tag *height_tag = root->AddChild("Heightmap"))
{
height_tag->AddChild("Width", heightmap_w);
height_tag->AddChild("Height", heightmap_h);
height_tag->AddChild("Resolution", unit);
// Note: The terrain heightmap is saved by the editor.
height_tag->AddChild("Data", heightmap_path.c_str());
}
return root;
}
//------------------------------------------------------------------------------