aboutsummaryrefslogtreecommitdiff
path: root/src/heightmap.cpp
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-02-05 14:55:16 +0200
committerPerttu Ahola <celeron55@gmail.com>2011-02-05 14:55:16 +0200
commitea6740e9002839f79053cf9d8cd78eb3fcae1b47 (patch)
treedc8a6c8c0df0ef2d50a0874a74549ccd2022e874 /src/heightmap.cpp
parent7f2aa30bf29ed1c8b363bd948916d4c027b0192f (diff)
downloadminetest-ea6740e9002839f79053cf9d8cd78eb3fcae1b47.tar.gz
minetest-ea6740e9002839f79053cf9d8cd78eb3fcae1b47.tar.bz2
minetest-ea6740e9002839f79053cf9d8cd78eb3fcae1b47.zip
mapgen stuff
Diffstat (limited to 'src/heightmap.cpp')
-rw-r--r--src/heightmap.cpp1060
1 files changed, 0 insertions, 1060 deletions
diff --git a/src/heightmap.cpp b/src/heightmap.cpp
deleted file mode 100644
index bb7f2a1d1..000000000
--- a/src/heightmap.cpp
+++ /dev/null
@@ -1,1060 +0,0 @@
-/*
-Minetest-c55
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
-
-This program is free software; you can redistribute it 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.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-/*
-(c) 2010 Perttu Ahola <celeron55@gmail.com>
-*/
-
-#include "heightmap.h"
-
-// For MAP_BLOCKSIZE
-#include "mapblock.h"
-
-/*
- ValueGenerator
-*/
-
-ValueGenerator* ValueGenerator::deSerialize(std::string line)
-{
- std::istringstream ss(line);
- //ss.imbue(std::locale("C"));
-
- std::string name;
- std::getline(ss, name, ' ');
-
- if(name == "constant")
- {
- f32 value;
- ss>>value;
-
- return new ConstantGenerator(value);
- }
- else if(name == "linear")
- {
- f32 height;
- v2f slope;
-
- ss>>height;
- ss>>slope.X;
- ss>>slope.Y;
-
- return new LinearGenerator(height, slope);
- }
- else if(name == "power")
- {
- f32 height;
- v2f slope;
- f32 power;
-
- ss>>height;
- ss>>slope.X;
- ss>>slope.Y;
- ss>>power;
-
- return new PowerGenerator(height, slope, power);
- }
- else
- {
- throw SerializationError
- ("Invalid heightmap generator (deSerialize)");
- }
-}
-
-/*
- FixedHeightmap
-*/
-
-f32 FixedHeightmap::avgNeighbours(v2s16 p, s16 d)
-{
- v2s16 dirs[4] = {
- v2s16(1,0),
- v2s16(0,1),
- v2s16(-1,0),
- v2s16(0,-1)
- };
- f32 sum = 0.0;
- f32 count = 0.0;
- for(u16 i=0; i<4; i++){
- v2s16 p2 = p + dirs[i] * d;
- f32 n = getGroundHeightParent(p2);
- if(n < GROUNDHEIGHT_VALID_MINVALUE)
- continue;
- sum += n;
- count += 1.0;
- }
- assert(count > 0.001);
- return sum / count;
-}
-
-f32 FixedHeightmap::avgDiagNeighbours(v2s16 p, s16 d)
-{
- v2s16 dirs[4] = {
- v2s16(1,1),
- v2s16(-1,-1),
- v2s16(-1,1),
- v2s16(1,-1)
- };
- f32 sum = 0.0;
- f32 count = 0.0;
- for(u16 i=0; i<4; i++){
- v2s16 p2 = p + dirs[i] * d;
- f32 n = getGroundHeightParent(p2);
- if(n < GROUNDHEIGHT_VALID_MINVALUE)
- continue;
- sum += n;
- count += 1.0;
- }
- assert(count > 0.001);
- return sum / count;
-}
-
-/*
- Adds a point to transform into a diamond pattern
- center = Center of the diamond phase (center of a square)
- a = Side length of the existing square (2, 4, 8, ...)
-
- Adds the center points of the next squares to next_squares as
- dummy "true" values.
-*/
-void FixedHeightmap::makeDiamond(
- v2s16 center,
- s16 a,
- f32 randmax,
- core::map<v2s16, bool> &next_squares)
-{
- /*dstream<<"makeDiamond(): center="
- <<"("<<center.X<<","<<center.Y<<")"
- <<", a="<<a<<", randmax="<<randmax
- <<", next_squares.size()="<<next_squares.size()
- <<std::endl;*/
-
- f32 n = avgDiagNeighbours(center, a/2);
- // Add (-1.0...1.0) * randmax
- n += ((float)myrand() / (float)(MYRAND_MAX/2) - 1.0)*randmax;
- bool worked = setGroundHeightParent(center, n);
-
- if(a >= 2 && worked)
- {
- next_squares[center + a/2*v2s16(-1,0)] = true;
- next_squares[center + a/2*v2s16(1,0)] = true;
- next_squares[center + a/2*v2s16(0,-1)] = true;
- next_squares[center + a/2*v2s16(0,1)] = true;
- }
-}
-
-/*
- Adds a point to transform into a square pattern
- center = The point that is added. The center of a diamond.
- a = Diameter of the existing diamond. (2, 4, 8, 16, ...)
-
- Adds center points of the next diamonds to next_diamonds.
-*/
-void FixedHeightmap::makeSquare(
- v2s16 center,
- s16 a,
- f32 randmax,
- core::map<v2s16, bool> &next_diamonds)
-{
- /*dstream<<"makeSquare(): center="
- <<"("<<center.X<<","<<center.Y<<")"
- <<", a="<<a<<", randmax="<<randmax
- <<", next_diamonds.size()="<<next_diamonds.size()
- <<std::endl;*/
-
- f32 n = avgNeighbours(center, a/2);
- // Add (-1.0...1.0) * randmax
- n += ((float)myrand() / (float)(MYRAND_MAX/2) - 1.0)*randmax;
- bool worked = setGroundHeightParent(center, n);
-
- if(a >= 4 && worked)
- {
- next_diamonds[center + a/4*v2s16(1,1)] = true;
- next_diamonds[center + a/4*v2s16(-1,1)] = true;
- next_diamonds[center + a/4*v2s16(-1,-1)] = true;
- next_diamonds[center + a/4*v2s16(1,-1)] = true;
- }
-}
-
-void FixedHeightmap::DiamondSquare(f32 randmax, f32 randfactor)
-{
- u16 a;
- if(W < H)
- a = W-1;
- else
- a = H-1;
-
- // Check that a is a power of two
- if((a & (a-1)) != 0)
- throw;
-
- core::map<v2s16, bool> next_diamonds;
- core::map<v2s16, bool> next_squares;
-
- next_diamonds[v2s16(a/2, a/2)] = true;
-
- while(a >= 2)
- {
- next_squares.clear();
-
- for(core::map<v2s16, bool>::Iterator
- i = next_diamonds.getIterator();
- i.atEnd() == false; i++)
- {
- v2s16 p = i.getNode()->getKey();
- makeDiamond(p, a, randmax, next_squares);
- }
-
- //print();
-
- next_diamonds.clear();
-
- for(core::map<v2s16, bool>::Iterator
- i = next_squares.getIterator();
- i.atEnd() == false; i++)
- {
- v2s16 p = i.getNode()->getKey();
- makeSquare(p, a, randmax, next_diamonds);
- }
-
- //print();
-
- a /= 2;
- randmax *= randfactor;
- }
-}
-
-void FixedHeightmap::generateContinued(f32 randmax, f32 randfactor,
- f32 *corners)
-{
- DSTACK(__FUNCTION_NAME);
- /*dstream<<"FixedHeightmap("<<m_pos_on_master.X
- <<","<<m_pos_on_master.Y
- <<")::generateContinued()"<<std::endl;*/
-
- // Works only with blocksize=2,4,8,16,32,64,...
- s16 a = m_blocksize;
-
- // Check that a is a power of two
- assert((a & (a-1)) == 0);
-
- // Overwrite with GROUNDHEIGHT_NOTFOUND_SETVALUE
- for(s16 y=0; y<=a; y++){
- for(s16 x=0; x<=a; x++){
- v2s16 p(x,y);
- setGroundHeight(p, GROUNDHEIGHT_NOTFOUND_SETVALUE);
- }
- }
-
- /*
- Fill with corners[] (if not already set)
- */
- v2s16 dirs[4] = {
- v2s16(0,0),
- v2s16(1,0),
- v2s16(1,1),
- v2s16(0,1),
- };
- for(u16 i=0; i<4; i++){
- v2s16 npos = dirs[i] * a;
- // Don't replace already seeded corners
- f32 h = getGroundHeight(npos);
- if(h > GROUNDHEIGHT_VALID_MINVALUE)
- continue;
- setGroundHeight(dirs[i] * a, corners[i]);
- }
-
- /*dstream<<"corners filled:"<<std::endl;
- print();*/
-
- DiamondSquare(randmax, randfactor);
-}
-
-u32 FixedHeightmap::serializedLength(u8 version, u16 blocksize)
-{
- if(!ser_ver_supported(version))
- throw VersionMismatchException("ERROR: FixedHeightmap format not supported");
-
- // Any version
- {
- /*// [0] s32 blocksize
- // [4] v2s16 pos_on_master
- // [8] s32 data[W*H] (W=H=blocksize+1)
- return 4 + 4 + (blocksize+1)*(blocksize+1)*4;*/
-
- // [8] s32 data[W*H] (W=H=blocksize+1)
- return (blocksize+1)*(blocksize+1)*4;
- }
-}
-
-u32 FixedHeightmap::serializedLength(u8 version)
-{
- return serializedLength(version, m_blocksize);
-}
-
-void FixedHeightmap::serialize(u8 *dest, u8 version)
-{
- //dstream<<"FixedHeightmap::serialize"<<std::endl;
-
- if(!ser_ver_supported(version))
- throw VersionMismatchException("ERROR: FixedHeightmap format not supported");
-
- // Any version
- {
- /*writeU32(&dest[0], m_blocksize);
- writeV2S16(&dest[4], m_pos_on_master);
- u32 nodecount = W*H;
- for(u32 i=0; i<nodecount; i++)
- {
- writeS32(&dest[8+i*4], (s32)(m_data[i]*1000.0));
- }*/
-
- u32 nodecount = W*H;
- for(u32 i=0; i<nodecount; i++)
- {
- writeS32(&dest[i*4], (s32)(m_data[i]*1000.0));
- }
- }
-}
-
-void FixedHeightmap::deSerialize(u8 *source, u8 version)
-{
- /*dstream<<"FixedHeightmap::deSerialize m_blocksize="
- <<m_blocksize<<std::endl;*/
-
- if(!ser_ver_supported(version))
- throw VersionMismatchException("ERROR: FixedHeightmap format not supported");
-
- // Any version
- {
- u32 nodecount = (m_blocksize+1)*(m_blocksize+1);
- for(u32 i=0; i<nodecount; i++)
- {
- m_data[i] = ((f32)readS32(&source[i*4]))/1000.0;
- }
-
- /*printf("source[0,1,2,3]=%x,%x,%x,%x\n",
- (int)source[0]&0xff,
- (int)source[1]&0xff,
- (int)source[2]&0xff,
- (int)source[3]&0xff);
-
- dstream<<"m_data[0]="<<m_data[0]<<", "
- <<"readS32(&source[0])="<<readS32(&source[0])
- <<std::endl;
- dstream<<"m_data[4*4]="<<m_data[4*4]<<", "
- <<"readS32(&source[4*4])="<<readS32(&source[4*4])
- <<std::endl;*/
- }
-}
-
-
-void setcolor(f32 h, f32 rangemin, f32 rangemax)
-{
-#ifndef _WIN32
- const char *colors[] =
- {
- "\x1b[40m",
- "\x1b[44m",
- "\x1b[46m",
- "\x1b[42m",
- "\x1b[43m",
- "\x1b[41m",
- };
- u16 colorcount = sizeof(colors)/sizeof(colors[0]);
- f32 scaled = (h - rangemin) / (rangemax - rangemin);
- u8 color = scaled * colorcount;
- if(color > colorcount-1)
- color = colorcount-1;
- /*printf("rangemin=%f, rangemax=%f, h=%f -> color=%i\n",
- rangemin,
- rangemax,
- h,
- color);*/
- printf("%s", colors[color]);
- //printf("\x1b[31;40m");
- //printf("\x1b[44;1m");
-#endif
-}
-void resetcolor()
-{
-#ifndef _WIN32
- printf("\x1b[0m");
-#endif
-}
-
-/*
- UnlimitedHeightmap
-*/
-
-void UnlimitedHeightmap::print()
-{
- s16 minx = 10000;
- s16 miny = 10000;
- s16 maxx = -10000;
- s16 maxy = -10000;
- core::map<v2s16, FixedHeightmap*>::Iterator i;
- i = m_heightmaps.getIterator();
- if(i.atEnd()){
- printf("UnlimitedHeightmap::print(): empty.\n");
- return;
- }
- for(; i.atEnd() == false; i++)
- {
- v2s16 p = i.getNode()->getValue()->getPosOnMaster();
- if(p.X < minx) minx = p.X;
- if(p.Y < miny) miny = p.Y;
- if(p.X > maxx) maxx = p.X;
- if(p.Y > maxy) maxy = p.Y;
- }
- minx = minx * m_blocksize;
- miny = miny * m_blocksize;
- maxx = (maxx+1) * m_blocksize;
- maxy = (maxy+1) * m_blocksize;
- printf("UnlimitedHeightmap::print(): from (%i,%i) to (%i,%i)\n",
- minx, miny, maxx, maxy);
-
- // Calculate range
- f32 rangemin = 1e10;
- f32 rangemax = -1e10;
- for(s32 y=miny; y<=maxy; y++){
- for(s32 x=minx; x<=maxx; x++){
- f32 h = getGroundHeight(v2s16(x,y), false);
- if(h < GROUNDHEIGHT_VALID_MINVALUE)
- continue;
- if(h < rangemin)
- rangemin = h;
- if(h > rangemax)
- rangemax = h;
- }
- }
-
- printf(" ");
- for(s32 x=minx; x<=maxx; x++){
- printf("% .3d ", x);
- }
- printf("\n");
-
- for(s32 y=miny; y<=maxy; y++){
- printf("% .3d ", y);
- for(s32 x=minx; x<=maxx; x++){
- f32 n = getGroundHeight(v2s16(x,y), false);
- if(n < GROUNDHEIGHT_VALID_MINVALUE)
- printf(" - ");
- else
- {
- setcolor(n, rangemin, rangemax);
- printf("% -5.1f", getGroundHeight(v2s16(x,y), false));
- resetcolor();
- }
- }
- printf("\n");
- }
-}
-
-FixedHeightmap * UnlimitedHeightmap::getHeightmap(v2s16 p_from, bool generate)
-{
- DSTACK("UnlimitedHeightmap::getHeightmap()");
- /*
- We want to check that all neighbours of the wanted heightmap
- exist.
- This is because generating the neighboring heightmaps will
- modify the current one.
- */
-
- if(generate)
- {
- // Go through all neighbors (corners also) and the current one
- // and generate every one of them.
- for(s16 x=p_from.X-1; x<=p_from.X+1; x++)
- for(s16 y=p_from.Y-1; y<=p_from.Y+1; y++)
- {
- v2s16 p(x,y);
-
- // Check if exists
- core::map<v2s16, FixedHeightmap*>::Node *n = m_heightmaps.find(p);
- if(n != NULL)
- continue;
-
- // Doesn't exist
- // Generate it
-
- FixedHeightmap *heightmap = new FixedHeightmap(this, p, m_blocksize);
-
- m_heightmaps.insert(p, heightmap);
-
- f32 corners[4];
-
- s32 div = SECTOR_HEIGHTMAP_SPLIT * MAP_BLOCKSIZE;
-
- {
- PointAttributeList *palist = m_padb->getList("hm_baseheight");
-
- if(palist->empty())
- {
- corners[0] = 0;
- corners[1] = 0;
- corners[2] = 0;
- corners[3] = 0;
- }
- else
- {
-#if 0
- corners[0] = palist->getNearAttr((p+v2s16(0,0)) * div).getFloat();
- corners[1] = palist->getNearAttr((p+v2s16(1,0)) * div).getFloat();
- corners[2] = palist->getNearAttr((p+v2s16(1,1)) * div).getFloat();
- corners[3] = palist->getNearAttr((p+v2s16(0,1)) * div).getFloat();
-#endif
-#if 1
- corners[0] = palist->getInterpolatedFloat((p+v2s16(0,0))*div);
- corners[1] = palist->getInterpolatedFloat((p+v2s16(1,0))*div);
- corners[2] = palist->getInterpolatedFloat((p+v2s16(1,1))*div);
- corners[3] = palist->getInterpolatedFloat((p+v2s16(0,1))*div);
-#endif
- }
- }
- /*else
- {
- corners[0] = m_base_generator->getValue(p+v2s16(0,0));
- corners[1] = m_base_generator->getValue(p+v2s16(1,0));
- corners[2] = m_base_generator->getValue(p+v2s16(1,1));
- corners[3] = m_base_generator->getValue(p+v2s16(0,1));
- }*/
-
- /*f32 randmax = m_randmax_generator->getValue(p);
- f32 randfactor = m_randfactor_generator->getValue(p);*/
-
- f32 randmax = m_padb->getList("hm_randmax")
- ->getInterpolatedFloat(p*div);
- f32 randfactor = m_padb->getList("hm_randfactor")
- ->getInterpolatedFloat(p*div);
- //dstream<<"randmax="<<randmax<<" randfactor="<<randfactor<<std::endl;
-
- heightmap->generateContinued(randmax, randfactor, corners);
- }
- }
-
- core::map<v2s16, FixedHeightmap*>::Node *n = m_heightmaps.find(p_from);
-
- if(n != NULL)
- {
- return n->getValue();
- }
- else
- {
- throw InvalidPositionException
- ("Something went really wrong in UnlimitedHeightmap::getHeightmap");
- }
-}
-
-f32 UnlimitedHeightmap::getGroundHeight(v2s16 p, bool generate)
-{
- v2s16 heightmappos = getNodeHeightmapPos(p);
- v2s16 relpos = p - heightmappos*m_blocksize;
- try{
- FixedHeightmap * href = getHeightmap(heightmappos, generate);
- f32 h = href->getGroundHeight(relpos);
- if(h > GROUNDHEIGHT_VALID_MINVALUE)
- return h;
- }
- catch(InvalidPositionException){}
- /*
- If on border or in the (0,0) corner, try to get from
- overlapping heightmaps
- */
- if(relpos.X == 0){
- try{
- FixedHeightmap * href = getHeightmap(
- heightmappos-v2s16(1,0), false);
- f32 h = href->getGroundHeight(v2s16(m_blocksize, relpos.Y));
- if(h > GROUNDHEIGHT_VALID_MINVALUE)
- return h;
- }
- catch(InvalidPositionException){}
- }
- if(relpos.Y == 0){
- try{
- FixedHeightmap * href = getHeightmap(
- heightmappos-v2s16(0,1), false);
- f32 h = href->getGroundHeight(v2s16(relpos.X, m_blocksize));
- if(h > GROUNDHEIGHT_VALID_MINVALUE)
- return h;
- }
- catch(InvalidPositionException){}
- }
- if(relpos.X == 0 && relpos.Y == 0){
- try{
- FixedHeightmap * href = getHeightmap(
- heightmappos-v2s16(1,1), false);
- f32 h = href->getGroundHeight(v2s16(m_blocksize, m_blocksize));
- if(h > GROUNDHEIGHT_VALID_MINVALUE)
- return h;
- }
- catch(InvalidPositionException){}
- }
- return GROUNDHEIGHT_NOTFOUND_SETVALUE;
-}
-
-void UnlimitedHeightmap::setGroundHeight(v2s16 p, f32 y, bool generate)
-{
- bool was_set = false;
-
- v2s16 heightmappos = getNodeHeightmapPos(p);
- v2s16 relpos = p - heightmappos*m_blocksize;
- /*dstream<<"UnlimitedHeightmap::setGroundHeight(("
- <<p.X<<","<<p.Y<<"), "<<y<<"): "
- <<"heightmappos=("<<heightmappos.X<<","
- <<heightmappos.Y<<") relpos=("
- <<relpos.X<<","<<relpos.Y<<")"
- <<std::endl;*/
- try{
- FixedHeightmap * href = getHeightmap(heightmappos, generate);
- href->setGroundHeight(relpos, y);
- was_set = true;
- }catch(InvalidPositionException){}
- // Update in neighbour heightmap if it's at border
- if(relpos.X == 0){
- try{
- FixedHeightmap * href = getHeightmap(
- heightmappos-v2s16(1,0), generate);
- href->setGroundHeight(v2s16(m_blocksize, relpos.Y), y);
- was_set = true;
- }catch(InvalidPositionException){}
- }
- if(relpos.Y == 0){
- try{
- FixedHeightmap * href = getHeightmap(
- heightmappos-v2s16(0,1), generate);
- href->setGroundHeight(v2s16(relpos.X, m_blocksize), y);
- was_set = true;
- }catch(InvalidPositionException){}
- }
- if(relpos.X == 0 && relpos.Y == 0){
- try{
- FixedHeightmap * href = getHeightmap(
- heightmappos-v2s16(1,1), generate);
- href->setGroundHeight(v2s16(m_blocksize, m_blocksize), y);
- was_set = true;
- }catch(InvalidPositionException){}
- }
-
- if(was_set == false)
- {
- throw InvalidPositionException
- ("UnlimitedHeightmap failed to set height");
- }
-}
-
-
-void UnlimitedHeightmap::serialize(std::ostream &os, u8 version)
-{
- //dstream<<"UnlimitedHeightmap::serialize()"<<std::endl;
-
- if(!ser_ver_supported(version))
- throw VersionMismatchException
- ("ERROR: UnlimitedHeightmap format not supported");
-
- if(version <= 7)
- {
- /*if(m_base_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
- || m_randmax_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
- || m_randfactor_generator->getId() != VALUE_GENERATOR_ID_CONSTANT)*/
- /*if(std::string(m_base_generator->getName()) != "constant"
- || std::string(m_randmax_generator->getName()) != "constant"
- || std::string(m_randfactor_generator->getName()) != "constant")
- {
- throw SerializationError
- ("Cannot write UnlimitedHeightmap in old version: "
- "Generators are not ConstantGenerators.");
- }*/
-
- // Dummy values
- f32 basevalue = 0.0;
- f32 randmax = 0.0;
- f32 randfactor = 0.0;
-
- // Write version
- os.write((char*)&version, 1);
-
- /*
- [0] u16 blocksize
- [2] s32 randmax*1000
- [6] s32 randfactor*1000
- [10] s32 basevalue*1000
- [14] u32 heightmap_count
- [18] X * (v2s16 pos + heightmap)
- */
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, m_blocksize);
- u32 heightmap_count = m_heightmaps.size();
-
- //dstream<<"heightmap_size="<<heightmap_size<<std::endl;
-
- u32 datasize = 2+4+4+4+4+heightmap_count*(4+heightmap_size);
- SharedBuffer<u8> data(datasize);
-
- writeU16(&data[0], m_blocksize);
- writeU32(&data[2], (s32)(randmax*1000.0));
- writeU32(&data[6], (s32)(randfactor*1000.0));
- writeU32(&data[10], (s32)(basevalue*1000.0));
- writeU32(&data[14], heightmap_count);
-
- core::map<v2s16, FixedHeightmap*>::Iterator j;
- j = m_heightmaps.getIterator();
- u32 i=0;
- for(; j.atEnd() == false; j++)
- {
- FixedHeightmap *hm = j.getNode()->getValue();
- v2s16 pos = j.getNode()->getKey();
- writeV2S16(&data[18+i*(4+heightmap_size)], pos);
- hm->serialize(&data[18+i*(4+heightmap_size)+4], version);
- i++;
- }
-
- os.write((char*)*data, data.getSize());
- }
- else if(version <= 11)
- {
- // Write version
- os.write((char*)&version, 1);
-
- u8 buf[4];
-
- writeU16(buf, m_blocksize);
- os.write((char*)buf, 2);
-
- /*m_randmax_generator->serialize(os);
- m_randfactor_generator->serialize(os);
- m_base_generator->serialize(os);*/
- os<<"constant 0.0\n";
- os<<"constant 0.0\n";
- os<<"constant 0.0\n";
-
- u32 heightmap_count = m_heightmaps.size();
- writeU32(buf, heightmap_count);
- os.write((char*)buf, 4);
-
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, m_blocksize);
-
- SharedBuffer<u8> hmdata(heightmap_size);
-
- core::map<v2s16, FixedHeightmap*>::Iterator j;
- j = m_heightmaps.getIterator();
- u32 i=0;
- for(; j.atEnd() == false; j++)
- {
- v2s16 pos = j.getNode()->getKey();
- writeV2S16(buf, pos);
- os.write((char*)buf, 4);
-
- FixedHeightmap *hm = j.getNode()->getValue();
- hm->serialize(*hmdata, version);
- os.write((char*)*hmdata, hmdata.getSize());
-
- i++;
- }
- }
- else
- {
- // Write version
- os.write((char*)&version, 1);
-
- u8 buf[4];
-
- writeU16(buf, m_blocksize);
- os.write((char*)buf, 2);
-
- /*m_randmax_generator->serialize(os);
- m_randfactor_generator->serialize(os);
- m_base_generator->serialize(os);*/
-
- u32 heightmap_count = m_heightmaps.size();
- writeU32(buf, heightmap_count);
- os.write((char*)buf, 4);
-
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, m_blocksize);
-
- SharedBuffer<u8> hmdata(heightmap_size);
-
- core::map<v2s16, FixedHeightmap*>::Iterator j;
- j = m_heightmaps.getIterator();
- u32 i=0;
- for(; j.atEnd() == false; j++)
- {
- v2s16 pos = j.getNode()->getKey();
- writeV2S16(buf, pos);
- os.write((char*)buf, 4);
-
- FixedHeightmap *hm = j.getNode()->getValue();
- hm->serialize(*hmdata, version);
- os.write((char*)*hmdata, hmdata.getSize());
-
- i++;
- }
- }
-
-#if 0
- if(version <= 7)
- {
- /*if(m_base_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
- || m_randmax_generator->getId() != VALUE_GENERATOR_ID_CONSTANT
- || m_randfactor_generator->getId() != VALUE_GENERATOR_ID_CONSTANT)*/
- if(std::string(m_base_generator->getName()) != "constant"
- || std::string(m_randmax_generator->getName()) != "constant"
- || std::string(m_randfactor_generator->getName()) != "constant")
- {
- throw SerializationError
- ("Cannot write UnlimitedHeightmap in old version: "
- "Generators are not ConstantGenerators.");
- }
-
- f32 basevalue = ((ConstantGenerator*)m_base_generator)->m_value;
- f32 randmax = ((ConstantGenerator*)m_randmax_generator)->m_value;
- f32 randfactor = ((ConstantGenerator*)m_randfactor_generator)->m_value;
-
- // Write version
- os.write((char*)&version, 1);
-
- /*
- [0] u16 blocksize
- [2] s32 randmax*1000
- [6] s32 randfactor*1000
- [10] s32 basevalue*1000
- [14] u32 heightmap_count
- [18] X * (v2s16 pos + heightmap)
- */
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, m_blocksize);
- u32 heightmap_count = m_heightmaps.size();
-
- //dstream<<"heightmap_size="<<heightmap_size<<std::endl;
-
- u32 datasize = 2+4+4+4+4+heightmap_count*(4+heightmap_size);
- SharedBuffer<u8> data(datasize);
-
- writeU16(&data[0], m_blocksize);
- writeU32(&data[2], (s32)(randmax*1000.0));
- writeU32(&data[6], (s32)(randfactor*1000.0));
- writeU32(&data[10], (s32)(basevalue*1000.0));
- writeU32(&data[14], heightmap_count);
-
- core::map<v2s16, FixedHeightmap*>::Iterator j;
- j = m_heightmaps.getIterator();
- u32 i=0;
- for(; j.atEnd() == false; j++)
- {
- FixedHeightmap *hm = j.getNode()->getValue();
- v2s16 pos = j.getNode()->getKey();
- writeV2S16(&data[18+i*(4+heightmap_size)], pos);
- hm->serialize(&data[18+i*(4+heightmap_size)+4], version);
- i++;
- }
-
- os.write((char*)*data, data.getSize());
- }
- else
- {
- // Write version
- os.write((char*)&version, 1);
-
- u8 buf[4];
-
- writeU16(buf, m_blocksize);
- os.write((char*)buf, 2);
-
- /*m_randmax_generator->serialize(os, version);
- m_randfactor_generator->serialize(os, version);
- m_base_generator->serialize(os, version);*/
- m_randmax_generator->serialize(os);
- m_randfactor_generator->serialize(os);
- m_base_generator->serialize(os);
-
- u32 heightmap_count = m_heightmaps.size();
- writeU32(buf, heightmap_count);
- os.write((char*)buf, 4);
-
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, m_blocksize);
-
- SharedBuffer<u8> hmdata(heightmap_size);
-
- core::map<v2s16, FixedHeightmap*>::Iterator j;
- j = m_heightmaps.getIterator();
- u32 i=0;
- for(; j.atEnd() == false; j++)
- {
- v2s16 pos = j.getNode()->getKey();
- writeV2S16(buf, pos);
- os.write((char*)buf, 4);
-
- FixedHeightmap *hm = j.getNode()->getValue();
- hm->serialize(*hmdata, version);
- os.write((char*)*hmdata, hmdata.getSize());
-
- i++;
- }
- }
-#endif
-}
-
-UnlimitedHeightmap * UnlimitedHeightmap::deSerialize(std::istream &is,
- PointAttributeDatabase *padb)
-{
- u8 version;
- is.read((char*)&version, 1);
-
- if(!ser_ver_supported(version))
- throw VersionMismatchException("ERROR: UnlimitedHeightmap format not supported");
-
- if(version <= 7)
- {
- /*
- [0] u16 blocksize
- [2] s32 randmax*1000
- [6] s32 randfactor*1000
- [10] s32 basevalue*1000
- [14] u32 heightmap_count
- [18] X * (v2s16 pos + heightmap)
- */
- SharedBuffer<u8> data(18);
- is.read((char*)*data, 18);
- if(is.gcount() != 18)
- throw SerializationError
- ("UnlimitedHeightmap::deSerialize: no enough input data");
- s16 blocksize = readU16(&data[0]);
- // Dummy read randmax, randfactor, basevalue
- /*f32 randmax = (f32)*/readU32(&data[2]) /*/ 1000.0*/;
- /*f32 randfactor = (f32)*/readU32(&data[6]) /*/ 1000.0*/;
- /*f32 basevalue = (f32)*/readU32(&data[10]) /*/ 1000.0*/;
- u32 heightmap_count = readU32(&data[14]);
-
- /*dstream<<"UnlimitedHeightmap::deSerialize():"
- <<" blocksize="<<blocksize
- <<" heightmap_count="<<heightmap_count
- <<std::endl;*/
-
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, blocksize);
-
- //dstream<<"heightmap_size="<<heightmap_size<<std::endl;
-
- /*ValueGenerator *maxgen = new ConstantGenerator(randmax);
- ValueGenerator *factorgen = new ConstantGenerator(randfactor);
- ValueGenerator *basegen = new ConstantGenerator(basevalue);*/
-
- UnlimitedHeightmap *hm = new UnlimitedHeightmap
- (blocksize, padb);
-
- for(u32 i=0; i<heightmap_count; i++)
- {
- //dstream<<"i="<<i<<std::endl;
- SharedBuffer<u8> data(4+heightmap_size);
- is.read((char*)*data, 4+heightmap_size);
- if(is.gcount() != (s32)(4+heightmap_size)){
- delete hm;
- throw SerializationError
- ("UnlimitedHeightmap::deSerialize: no enough input data");
- }
- v2s16 pos = readV2S16(&data[0]);
- FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize);
- f->deSerialize(&data[4], version);
- hm->m_heightmaps.insert(pos, f);
- }
- return hm;
- }
- else if(version <= 11)
- {
- u8 buf[4];
-
- is.read((char*)buf, 2);
- s16 blocksize = readU16(buf);
-
- // Dummy-read three lines (generators)
- std::string templine;
- std::getline(is, templine, '\n');
-
- is.read((char*)buf, 4);
- u32 heightmap_count = readU32(buf);
-
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, blocksize);
-
- UnlimitedHeightmap *hm = new UnlimitedHeightmap
- (blocksize, padb);
-
- for(u32 i=0; i<heightmap_count; i++)
- {
- is.read((char*)buf, 4);
- v2s16 pos = readV2S16(buf);
-
- SharedBuffer<u8> data(heightmap_size);
- is.read((char*)*data, heightmap_size);
- if(is.gcount() != (s32)(heightmap_size)){
- delete hm;
- throw SerializationError
- ("UnlimitedHeightmap::deSerialize: no enough input data");
- }
- FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize);
- f->deSerialize(*data, version);
- hm->m_heightmaps.insert(pos, f);
- }
- return hm;
- }
- else
- {
- u8 buf[4];
-
- is.read((char*)buf, 2);
- s16 blocksize = readU16(buf);
-
- /*ValueGenerator *maxgen = ValueGenerator::deSerialize(is);
- ValueGenerator *factorgen = ValueGenerator::deSerialize(is);
- ValueGenerator *basegen = ValueGenerator::deSerialize(is);*/
-
- is.read((char*)buf, 4);
- u32 heightmap_count = readU32(buf);
-
- u32 heightmap_size =
- FixedHeightmap::serializedLength(version, blocksize);
-
- UnlimitedHeightmap *hm = new UnlimitedHeightmap
- (blocksize, padb);
-
- for(u32 i=0; i<heightmap_count; i++)
- {
- is.read((char*)buf, 4);
- v2s16 pos = readV2S16(buf);
-
- SharedBuffer<u8> data(heightmap_size);
- is.read((char*)*data, heightmap_size);
- if(is.gcount() != (s32)(heightmap_size)){
- delete hm;
- throw SerializationError
- ("UnlimitedHeightmap::deSerialize: no enough input data");
- }
- FixedHeightmap *f = new FixedHeightmap(hm, pos, blocksize);
- f->deSerialize(*data, version);
- hm->m_heightmaps.insert(pos, f);
- }
- return hm;
- }
-}
-
-