Exemplo n.º 1
0
void BaseMapGen::ScanTerrain2Meshes ()
{
  csHash<uint, csString> baseMapWriteCounts;

   // Get the terrain node
  csRef<iDocumentNodeIterator> sectors = rootnode->GetNodes("sector");
  while (sectors->HasNext())
  {
    csRef<iDocumentNode> sector = sectors->Next();
    csRef<iDocumentNodeIterator> it = sector->GetNodes("meshobj");
    while (it->HasNext())
    {
      csRef<iDocumentNode> current = it->Next();
    
      csRef<iDocumentNode> pluginNode = current->GetNode ("plugin");
      if (!pluginNode.IsValid()) continue;
      const char* plugin = GetPluginSCFID (pluginNode->GetContentsValue());
      if ((plugin == 0)
	  || (strcmp (plugin, "crystalspace.mesh.loader.terrain2") != 0))
	continue;
    
      csString name = current->GetAttributeValue("name");
      if ((meshRE != 0) && (meshRE->Match (name) != csrxNoError))
	continue;
    
      csRef<iDocumentNode> params = current->GetNode ("params");
      if (!params) continue;
      csRef<iDocumentNode> factoryNode = params->GetNode ("factory");
      if (!factoryNode) continue;
      
      const char* factname = factoryNode->GetContentsValue();
      Terrain2Factory* factory = terrain2Factories.Get (factname,
        (Terrain2Factory*)0);
      if (!factory) continue;
    
      csPrintf ("Found terrain '%s' ...\n", name.GetData());
      fflush (stdout);
      
      // Get the materialpalette.
      csRef<iDocumentNode> materialpalette = params->GetNode ("materialpalette");
      if (!materialpalette) continue;
    
      MaterialLayers mlayers;
      // Get the materials.
      csRef<iDocumentNodeIterator> it = materialpalette->GetNodes("material");
      while (it->HasNext())
      {
	csRef<iDocumentNode> pal = it->Next();
	const char* matname = pal->GetContentsValue();
	MaterialLayer* layer = materials.Get (matname, (MaterialLayer*)0);
	mlayers.Push (layer);
      } // while
    
      if (mlayers.GetSize() > 0)
        csPrintf ("Found %zu materials in materialpalette...\n", mlayers.GetSize());
        
      csRef<iDocumentNode> cells = params->GetNode ("cells");
      if (!cells) continue;
      
      csRef<iDocumentNodeIterator> cellsIt (cells->GetNodes ("cell"));
      while (cellsIt->HasNext())
      {
	csRef<iDocumentNode> cellNode = cellsIt->Next();
	
	csRef<iDocumentNode> nameNode = cellNode->GetNode ("name");
	if (!nameNode) continue;
	const char* cellName = nameNode->GetContentsValue();
	
	Terrain2Cell* factoryCell = factory->cells.Get (cellName,
	  (Terrain2Cell*)0);
	if (!factoryCell) continue;
	
	Terrain2Cell cell (*factoryCell);
	if (!cell.Parse (cellNode)) continue;
	
	MaterialLayer* mat = materials.Get (cell.baseMaterial, (MaterialLayer*)0);
	if (!mat) continue;
	
	if (!cell.alphaLayers.IsValid())
	  cell.ApplyMaterialMap (mlayers);

	// Get the resolution.
	int basemap_w = csFindNearestPowerOf2 (cell.alphaLayers->GetWidth());
	int basemap_h = csFindNearestPowerOf2 (cell.alphaLayers->GetHeight());
      
	// Get the resolution from the commandline.
	csString res = cmdline->GetOption ("resolution");
	if (!res.IsEmpty())
	{
	  int basemap_res = csFindNearestPowerOf2 (atoi(res));
	  basemap_w = basemap_h = basemap_res;
	}
      
	csPrintf ("Basemap resolution: %dx%d\n", basemap_w, basemap_h); fflush (stdout);
	
	csRef<iImage> basemap = CreateBasemap (basemap_w, basemap_h,
	  *(cell.alphaLayers), cell.alphaMaterials);
	if (!basemap) continue;
	const char* texfile = textureFiles.Get (mat->texture_name, (const char*)0);
	if (texfile == 0) continue;
	
	SaveImage (basemap, texfile);
	
	baseMapWriteCounts.GetOrCreate (texfile, 0)++;
      }
    } // while meshobj
  } // while sector
  
  csHash<uint, csString>::GlobalIterator countIt (baseMapWriteCounts.GetIterator());
  while (countIt.HasNext())
  {
    csString key;
    uint count = countIt.Next (key);
    if (count > 1)
      csPrintf ("Wrote %u times to texture %s - \n"
        "that indicates this basemap is used for multiple cells. Is that right?\n",
        count, key.GetData());
  }
}
Exemplo n.º 2
0
void HeightMapGen::Start ()
{
  csRef<iImageIO> imageio = csQueryRegistry<iImageIO> (object_reg);
  csRef<iVFS> VFS = csQueryRegistry<iVFS> (object_reg);
  csString meshname = cfgmgr->GetStr ("HeightMapGen.MeshInput", "");
  iMeshWrapper* mesh = engine->FindMeshObject (meshname);
  if (!mesh)
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.heightmapgen",
    	"Can't find mesh %s!", CS::Quote::Single (meshname.GetData ()));
    return;
  }

  csBox3 box = mesh->GetWorldBoundingBox ();
  csPrintf ("box=%g,%g,%g   %g,%g,%g\n",
  	box.MinX (), box.MinY (), box.MinZ (),
  	box.MaxX (), box.MaxY (), box.MaxZ ());

  csRef<iCollideSystem> cdsys = csQueryRegistry<iCollideSystem> (object_reg);
  csColliderHelper::InitializeCollisionWrapper (cdsys, mesh);
  iSector* sector = mesh->GetMovable ()->GetSectors ()->Get (0);

  // Heightmap resolution.
  int heightmap_res = cfgmgr->GetInt ("HeightMapGen.HeightmapResolution", 513);
  int num_texture_layers = cfgmgr->GetInt ("HeightMapGen.NumTextureLayers", 3);
  csArray<TextureLayer> txt_layers;
  txt_layers.SetSize (num_texture_layers);
  int i;
  for (i = 0 ; i < num_texture_layers ; i++)
  {
    csString str;
    str.Format ("HeightMapGen.Layer%d.", i);
    txt_layers[i].min_height = cfgmgr->GetInt ((str+"MinHeight").GetData ());
    txt_layers[i].max_height = cfgmgr->GetInt ((str+"MaxHeight").GetData ());
    txt_layers[i].texture_name = cfgmgr->GetStr (
    	(str+"TextureName").GetData (), "");
    txt_layers[i].texture_file = cfgmgr->GetStr (
    	(str+"TextureFile").GetData (), "");
  }

  csRef<csImageMemory> heightmap_img;
  heightmap_img.AttachNew (new csImageMemory (
  	heightmap_res, heightmap_res));
  csRef<csImageMemory> basetexture_img;
  basetexture_img.AttachNew (new csImageMemory (
  	heightmap_res, heightmap_res));

  csString materialmap_input = cfgmgr->GetStr (
  	"HeightMapGen.MaterialMapInput", "");
  csRef<iImage> materialmap_img;
  {
    csRef<iDataBuffer> buf = VFS->ReadFile (materialmap_input, false);
    materialmap_img = imageio->Load (buf, CS_IMGFMT_PALETTED8);
  }

  //csRef<csImageMemory> materialmap_img;
  //materialmap_img.AttachNew (new csImageMemory (
  	//heightmap_res, heightmap_res, CS_IMGFMT_PALETTED8));
  //materialmap_img->GetPalette ()[0].Set (0, 0, 0);
  //materialmap_img->GetPalette ()[1].Set (255, 255, 255);
  //materialmap_img->GetPalette ()[2].Set (255, 0, 0);
  //materialmap_img->GetPalette ()[3].Set (0, 255, 0);
  //materialmap_img->GetPalette ()[4].Set (0, 0, 255);
  //materialmap_img->GetPalette ()[5].Set (255, 0, 255);
  //materialmap_img->GetPalette ()[6].Set (255, 255, 0);
  //materialmap_img->GetPalette ()[7].Set (0, 255, 255);

  for (i = 0 ; i < num_texture_layers ; i++)
  {
    csRef<iDataBuffer> buf = VFS->ReadFile (txt_layers[i].texture_file, false);
    if (!buf)
    {
      csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.heightmapgen",
	"Failed to read texture file %s!", CS::Quote::Single (txt_layers[i].texture_file.GetData()));
      return;
    }
    txt_layers[i].image = imageio->Load (buf, CS_IMGFMT_TRUECOLOR);
    csRGBpixel* img = (csRGBpixel*)(txt_layers[i].image->GetImageData ());
    int w = txt_layers[i].image->GetWidth ();
    int h = txt_layers[i].image->GetHeight ();
    long r = 0, g = 0, b = 0;
    int x, y;
    for (y = 0 ; y < h ; y++)
      for (x = 0 ; x < w ; x++)
      {
        r += img->red;
        g += img->green;
        b += img->blue;
	img++;
      }
    txt_layers[i].average.Set (
    	float (r / (w*h)) / 255.0,
    	float (g / (w*h)) / 255.0,
    	float (b / (w*h)) / 255.0);
    csPrintf ("Average color for %s: %g,%g,%g\n",
    	txt_layers[i].texture_file.GetData(),
	txt_layers[i].average.red,
	txt_layers[i].average.green,
	txt_layers[i].average.blue);
    fflush (stdout);
  }

  csRGBpixel* hmap_dst = (csRGBpixel*)(heightmap_img->GetImageData ());
  float* height = new float[heightmap_res*heightmap_res];
  float* height_dst = height;

  // Create the heightmap first.
  CreateHeightmap (heightmap_res, cdsys, sector, hmap_dst, height_dst, box);

  // Now create the base texture and material map.
  csRGBpixel* basemap_dst = (csRGBpixel*)(basetexture_img->GetImageData ());
  uint8* matmap_dst = (uint8*)(materialmap_img->GetImageData ());
  CreateBasemap (heightmap_res, basemap_dst, matmap_dst, height_dst, 
    txt_layers);

  delete[] height;

  csString heightmap_output_file = cfgmgr->GetStr (
    	"HeightMapGen.HeightMapOutput", "");
  csString basemap_name = cfgmgr->GetStr (
    	"HeightMapGen.BaseMapName", "basemap");
  csString basemap_output_file = cfgmgr->GetStr (
    	"HeightMapGen.BaseMapOutput", "");
  csString terrain_meshfactname = cfgmgr->GetStr (
    	"HeightMapGen.TerrainFactoryName", "TerrainFact");
  csString terrain_meshname = cfgmgr->GetStr (
    	"HeightMapGen.TerrainObjectName", "Terrain");
  csString addon_name = cfgmgr->GetStr (
    	"HeightMapGen.TerrainAddonName", "simple");
  csString sector_name = cfgmgr->GetStr (
    	"HeightMapGen.SectorName", "room");
  csString world_name = cfgmgr->GetStr (
  	"HeightMapGen.WorldOutput", "/this/world");

  csPrintf ("Writing images...\n"); fflush (stdout);
  csRef<iDataBuffer> db = imageio->Save (heightmap_img,
    	"image/png", "progressive");
  if (db)
  {
    if (!VFS->WriteFile (heightmap_output_file,
        (const char*)db->GetData (), db->GetSize ()))
    {
      csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.heightmapgen",
	"Failed to write file %s!", CS::Quote::Single (heightmap_output_file.GetData ()));
      return;
    }
  }
  else
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.heightmapgen",
	"Failed to save png image for heightmap!");
    return;
  }

  csRef<iDataBuffer> db_base = imageio->Save (basetexture_img,
    	"image/png", "progressive");
  if (db_base)
  {
    if (!VFS->WriteFile (basemap_output_file,
    	(const char*)db_base->GetData (), db_base->GetSize ()))
    {
      csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.heightmapgen",
	"Failed to write file %s!", CS::Quote::Single (basemap_output_file.GetData ()));
      return;
    }
  }
  else
  {
    csReport (object_reg, CS_REPORTER_SEVERITY_ERROR,
    	"crystalspace.application.heightmapgen",
	"Failed to save png image for basemap!");
    return;
  }

  csPrintf ("Writing world...\n"); fflush (stdout);
  csRef<iDocumentSystem> docsys;
  docsys.AttachNew (new csTinyDocumentSystem ());
  csRef<iDocument> doc = docsys->CreateDocument ();
  csRef<iDocumentNode> root = doc->CreateRoot ();
  csRef<iDocumentNode> world = CreateNode (root, "world");

  //========================================================================
  // Textures
  //========================================================================
  {
    csRef<iDocumentNode> node_textures = CreateNode (world, "textures");
    for (i = 0 ; i < num_texture_layers ; i++)
    {
      csRef<iDocumentNode> node_texture = CreateNode (node_textures, "texture");
      node_texture->SetAttribute ("name", txt_layers[i].texture_name);
      CreateNode (node_texture, "file", txt_layers[i].texture_file);
    }
    csRef<iDocumentNode> node_texture = CreateNode (node_textures, "texture");
    node_texture->SetAttribute ("name", basemap_name);
    CreateNode (node_texture, "file", basemap_output_file);
  }
  //========================================================================
  // Shaders
  //========================================================================
  {
    csRef<iDocumentNode> node_shaders = CreateNode (world, "shaders");
    csRef<iDocumentNode> node_shader1 = CreateNode (node_shaders, "shader");
    CreateNode (node_shader1, "file", "/shader/terrain_fixed_base.xml");
    csRef<iDocumentNode> node_shader2 = CreateNode (node_shaders, "shader");
    CreateNode (node_shader2, "file", "/shader/terrain_fixed_splatting.xml");
  }
  //========================================================================
  // Materials
  //========================================================================
  {
    csRef<iDocumentNode> node_materials = CreateNode (world, "materials");
    for (i = 0 ; i < num_texture_layers ; i++)
    {
      csRef<iDocumentNode> node_material = CreateNode (node_materials,
      	"material");
      node_material->SetAttribute ("name", txt_layers[i].texture_name);
      CreateNode (node_material, "texture", txt_layers[i].texture_name);
      csRef<iDocumentNode> node_shadervar = CreateNode (node_material,
      	"shadervar", "16,16");
      node_shadervar->SetAttribute ("name", "texture scale");
      node_shadervar->SetAttribute ("type", "vector2");
      csRef<iDocumentNode> node_shader = CreateNode (node_material,
      	"shader", "terrain_fixed_splatting");
      node_shader->SetAttribute ("type", "terrain splat");
    }
    csRef<iDocumentNode> node_material = CreateNode (node_materials,
      	"material");
    node_material->SetAttribute ("name", basemap_name);
    CreateNode (node_material, "texture", basemap_name);
    csRef<iDocumentNode> node_shader = CreateNode (node_material,
      	"shader", "terrain_fixed_base");
    node_shader->SetAttribute ("type", "ambient");
  }
  //========================================================================
  // Renderloop addon.
  //========================================================================
  {
    csRef<iDocumentNode> node_addon = CreateNode (world, "addon");
    CreateNode (node_addon, "plugin", "crystalspace.renderloop.loop.loader");
    csRef<iDocumentNode> node_params = CreateNode (node_addon, "params");
    CreateNode (node_params, "name", "TerrainLoop");
    csRef<iDocumentNode> node_steps = CreateNode (node_params, "steps");

    csRef<iDocumentNode> node_step_amb = CreateNode (node_steps, "step");
    node_step_amb->SetAttribute ("plugin",
    	"crystalspace.renderloop.step.generic");
    CreateNode (node_step_amb, "shadertype", "ambient");
    CreateNode (node_step_amb, "zoffset", "yes");
    CreateNode (node_step_amb, "portaltraversal");
    CreateNode (node_step_amb, "zuse");

    csRef<iDocumentNode> node_step_splat = CreateNode (node_steps, "step");
    node_step_splat->SetAttribute ("plugin",
    	"crystalspace.renderloop.step.generic");
    CreateNode (node_step_splat, "shadertype", "terrain splat");
    CreateNode (node_step_splat, "zoffset", "no");
    CreateNode (node_step_splat, "zuse");

    csRef<iDocumentNode> node_step_geom = CreateNode (node_steps, "step");
    node_step_geom->SetAttribute ("plugin",
    	"crystalspace.renderloop.step.generic");
    CreateNode (node_step_geom, "shadertype", "standard");
    CreateNode (node_step_geom, "zoffset", "no");
    CreateNode (node_step_geom, "zuse");
  }
  //========================================================================
  // Settings
  //========================================================================
  {
    csRef<iDocumentNode> node_settings = CreateNode (world, "settings");
    CreateNode (node_settings, "clearzbuf", "yes");
    CreateNode (node_settings, "clearscreen", "yes");
  }
  //========================================================================
  // Start
  //========================================================================
  {
    csRef<iDocumentNode> node_start = CreateNode (world, "start");
    CreateNode (node_start, "sector", sector_name);
    csRef<iDocumentNode> node_pos = CreateNode (node_start, "position");
    node_pos->SetAttributeAsInt ("x",
    	cfgmgr->GetInt("HeightMapGen.WorldStart.x",0));
    node_pos->SetAttributeAsInt ("y",
    	cfgmgr->GetInt("HeightMapGen.WorldStart.y",0));
    node_pos->SetAttributeAsInt ("z",
    	cfgmgr->GetInt("HeightMapGen.WorldStart.z",0));
  }
  //========================================================================
  // TerraFormer addon.
  //========================================================================
  {
    csRef<iDocumentNode> node_addon = CreateNode (world, "addon");
    CreateNode (node_addon, "plugin", "crystalspace.terraformer.simple.loader");
    csRef<iDocumentNode> node_params = CreateNode (node_addon, "params");
    CreateNode (node_params, "name", addon_name);
    CreateNode (node_params, "heightmap", heightmap_output_file);
    csRef<iDocumentNode> node_scale = CreateNode (node_params, "scale");
    node_scale->SetAttributeAsFloat ("x", (box.MaxX ()-box.MinX ())/2.0f);
    node_scale->SetAttributeAsFloat ("y", box.MaxY ()-box.MinY ());
    node_scale->SetAttributeAsFloat ("z", (box.MaxZ ()-box.MinZ ())/2.0f);
  }
  //========================================================================
  // Terrain factory.
  //========================================================================
  {
    csRef<iDocumentNode> node_fact = CreateNode (world, "meshfact");
    node_fact->SetAttribute ("name", terrain_meshfactname);
    CreateNode (node_fact, "plugin",
    	"crystalspace.mesh.loader.factory.terrain");
    csRef<iDocumentNode> node_params = CreateNode (node_fact, "params");
    CreateNode (node_params, "plugin",
    	"crystalspace.mesh.object.terrain.bruteblock");
    CreateNode (node_params, "terraformer", addon_name);
    csRef<iDocumentNode> node_sample = CreateNode (node_params, "sampleregion");
    csRef<iDocumentNode> node_min = CreateNode (node_sample, "min");
    node_min->SetAttributeAsFloat ("x", box.MinX ());
    node_min->SetAttributeAsFloat ("y", box.MinZ ());
    csRef<iDocumentNode> node_max = CreateNode (node_sample, "max");
    node_max->SetAttributeAsFloat ("x", box.MaxX ());
    node_max->SetAttributeAsFloat ("y", box.MaxZ ());
  }
  //========================================================================
  // Sector.
  //========================================================================
  {
    csRef<iDocumentNode> node_sector = CreateNode (world, "sector");
    node_sector->SetAttribute ("name", sector_name);
    CreateNode (node_sector, "renderloop", "TerrainLoop");
    csRef<iDocumentNode> node_obj = CreateNode (node_sector, "meshobj");
    node_obj->SetAttribute ("name", terrain_meshname);
    CreateNode (node_obj, "plugin", "crystalspace.mesh.loader.terrain");
    csRef<iDocumentNode> node_params = CreateNode (node_obj, "params");
    CreateNode (node_params, "factory", terrain_meshfactname);
    CreateNode (node_params, "material", basemap_name);
    csRef<iDocumentNode> node_pal = CreateNode (node_params, "materialpalette");
    for (i = 0 ; i < num_texture_layers ; i++)
    {
      CreateNode (node_pal, "material", txt_layers[i].texture_name);
    }
    CreateNode (node_params, "lodvalue", cfgmgr->GetStr (
    	"HeightMapGen.LodSplattingDistance", "250"))
    	->SetAttribute ("name", "splatting distance");
    CreateNode (node_params, "lodvalue", cfgmgr->GetStr (
    	"HeightMapGen.LodBlockResolution", "16"))
    	->SetAttribute ("name", "block resolution");
    CreateNode (node_params, "lodvalue", cfgmgr->GetStr (
    	"HeightMapGen.LodBlockSplitDistance", "8"))
    	->SetAttribute ("name", "block split distance");
    CreateNode (node_params, "lodvalue", cfgmgr->GetStr (
    	"HeightMapGen.LodMinimumBlockSize", "32"))
    	->SetAttribute ("name", "minimum block size");
    CreateNode (node_params, "lodvalue", cfgmgr->GetStr (
    	"HeightMapGen.LodCDResolution", "256"))
    	->SetAttribute ("name", "cd resolution");
    CreateNode (node_params, "lodvalue", cfgmgr->GetStr (
    	"HeightMapGen.LodLMResolution", "257"))
    	->SetAttribute ("name", "lightmap resolution");
    CreateNode (node_params, "materialmap")
    	->SetAttribute ("image", materialmap_input);
    CreateNode (node_params, "staticlighting",
    	cfgmgr->GetStr ("HeightMapGen.StaticLighting", "yes"));
    CreateNode (node_params, "castshadows",
    	cfgmgr->GetStr ("HeightMapGen.CastShadows", "yes"));

    csRef<iDocumentNode> node_move = CreateNode (node_obj, "move");
    csRef<iDocumentNode> node_v = CreateNode (node_move, "v");
    node_v->SetAttributeAsFloat ("x", (box.MaxX ()+box.MinX ()));
    node_v->SetAttributeAsFloat ("y", box.MinY ());
    node_v->SetAttributeAsFloat ("z", (box.MaxZ ()+box.MinZ ()));

#if 0
    csRef<iDocumentNode> node_light = CreateNode (node_sector, "light");
    node_light->SetAttribute ("name", "sun");
    csRef<iDocumentNode> node_center = CreateNode (node_light, "center");
    node_center->SetAttribute ("x", "0");
    node_center->SetAttribute ("y", "10000");
    node_center->SetAttribute ("z", "0");
    csRef<iDocumentNode> node_color = CreateNode (node_light, "color");
    node_color->SetAttribute ("red", "1");
    node_color->SetAttribute ("green", "1");
    node_color->SetAttribute ("blue", "1");
    CreateNode (node_light, "radius", "100000");
#endif
  }

  const char* err = doc->Write (VFS, world_name);
  if (err != 0) csPrintf ("%s\n", err);
}