/* ----------------------------------------------------------------------------- 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 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 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 .\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; } //------------------------------------------------------------------------------