From af95cfc7a15788386d055a5b4a7377673d36b8bf Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 29 Nov 2010 10:57:05 +0200 Subject: [PATCH] =?utf8?q?vokselijuttu=20lis=C3=A4tty?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- minetest.vcproj | 4 + src/voxel.cpp | 304 ++++++++++++++++++++++++++++++++++++++++++++++++ src/voxel.h | 224 +++++++++++++++++++++++++++++++++++ 3 files changed, 532 insertions(+) create mode 100644 src/voxel.cpp create mode 100644 src/voxel.h diff --git a/minetest.vcproj b/minetest.vcproj index c60d9a1f..0401e2a0 100644 --- a/minetest.vcproj +++ b/minetest.vcproj @@ -247,6 +247,10 @@ RelativePath=".\src\utility.cpp" > + + = 3 && em.Y >= 3) + { + if(y==m_area.MinEdge.Y+0) o<<"y x-> "; + if(y==m_area.MinEdge.Y+1) o<<"| "; + if(y==m_area.MinEdge.Y+2) o<<"V "; + } + + for(s32 z=m_area.MinEdge.Z; z<=m_area.MaxEdge.Z; z++) + { + for(s32 x=m_area.MinEdge.X; x<=m_area.MaxEdge.X; x++) + { + u8 m = m_data[m_area.index(x,y,z)].d; + char c = 'X'; + if(m == MATERIAL_IGNORE) + c = 'I'; + else if(m <= 9) + c = m + '0'; + o< buf(area.getVolume()); + + for(s32 z=area.MinEdge.Z; z<=area.MaxEdge.Z; z++) + for(s32 y=area.MinEdge.Y; y<=area.MaxEdge.Y; y++) + for(s32 x=area.MinEdge.X; x<=area.MaxEdge.X; x++) + { + v3s16 p(x,y,z); + + v3s16 dirs[] = { + v3s16(1,1,0), + v3s16(1,0,1), + v3s16(1,-1,0), + v3s16(1,0,-1), + v3s16(-1,1,0), + v3s16(-1,0,1), + v3s16(-1,-1,0), + v3s16(-1,0,-1), + }; + //const v3s16 *dirs = g_26dirs; + + s16 total = 0; + s16 airness = 0; + u8 m = MATERIAL_IGNORE; + + for(s16 i=0; i<8; i++) + //for(s16 i=0; i<26; i++) + { + v3s16 p2 = p + dirs[i]; + + MapNode &n = m_data[m_area.index(p2)]; + if(n.d == MATERIAL_IGNORE) + continue; + + airness += (n.d == MATERIAL_AIR) ? 1 : -1; + total++; + + if(m == MATERIAL_IGNORE && n.d != MATERIAL_AIR) + m = n.d; + } + + // 1 if air, 0 if not + buf[area.index(p)] = airness > -total/2 ? MATERIAL_AIR : m; + //buf[area.index(p)] = airness > -total ? MATERIAL_AIR : m; + //buf[area.index(p)] = airness >= -7 ? MATERIAL_AIR : m; + } + + for(s32 z=area.MinEdge.Z; z<=area.MaxEdge.Z; z++) + for(s32 y=area.MinEdge.Y; y<=area.MaxEdge.Y; y++) + for(s32 x=area.MinEdge.X; x<=area.MaxEdge.X; x++) + { + v3s16 p(x,y,z); + m_data[m_area.index(p)].d = buf[area.index(p)]; + } +} + +#if 0 +void VoxelManipulator::blitFromNodeContainer + (v3s16 p_from, v3s16 p_to, v3s16 size, NodeContainer *c) +{ + VoxelArea a_to(p_to, p_to+size-v3s16(1,1,1)); + addArea(a_to); + for(s16 z=0; zgetNode(p_from + p); + m_data[m_area.index(p_to + p)] = n; + } + catch(InvalidPositionException &e) + { + } + + /*v3s16 p(x,y,z); + MapNode n(MATERIAL_IGNORE); + try{ + n = c->getNode(p_from + p); + } + catch(InvalidPositionException &e) + { + } + m_data[m_area.index(p_to + p)] = n;*/ + } +} + +void VoxelManipulator::blitToNodeContainer + (v3s16 p_from, v3s16 p_to, v3s16 size, NodeContainer *c) +{ + for(s16 z=0; zsetNode(p_to + p, n); + } + catch(InvalidPositionException &e) + { + } + } +} +#endif + +/* + MapVoxelManipulator +*/ + +MapVoxelManipulator::MapVoxelManipulator(Map *map) +{ + m_map = map; +} + +void MapVoxelManipulator::emerge(VoxelArea a) +{ + v3s16 size = a.getExtent(); + + addArea(a); + + for(s16 z=0; zgetNode(a.MinEdge + p); + m_data[m_area.index(a.MinEdge + p)] = n; + } + catch(InvalidPositionException &e) + { + } + } +} + +void MapVoxelManipulator::blitBack + (core::map & modified_blocks) +{ + /* + Initialize block cache + */ + v3s16 blockpos_last; + MapBlock *block = NULL; + bool block_checked_in_modified = false; + + for(s32 z=m_area.MinEdge.Z; z<=m_area.MaxEdge.Z; z++) + for(s32 y=m_area.MinEdge.Y; y<=m_area.MaxEdge.Y; y++) + for(s32 x=m_area.MinEdge.X; x<=m_area.MaxEdge.X; x++) + { + v3s16 p(x,y,z); + + MapNode &n = m_data[m_area.index(p)]; + if(n.d == MATERIAL_IGNORE) + continue; + + v3s16 blockpos = getNodeBlockPos(p); + + try + { + // Get block + if(block == NULL || blockpos != blockpos_last){ + block = m_map->getBlockNoCreate(blockpos); + blockpos_last = blockpos; + block_checked_in_modified = false; + } + + // Calculate relative position in block + v3s16 relpos = p - blockpos * MAP_BLOCKSIZE; + + // Don't continue if nothing has changed here + if(block->getNode(relpos) == n) + continue; + + //m_map->setNode(m_area.MinEdge + p, n); + block->setNode(relpos, n); + + /* + Make sure block is in modified_blocks + */ + if(block_checked_in_modified == false) + { + modified_blocks[blockpos] = block; + block_checked_in_modified = true; + } + } + catch(InvalidPositionException &e) + { + } + } +} + +//END diff --git a/src/voxel.h b/src/voxel.h new file mode 100644 index 00000000..eee9177f --- /dev/null +++ b/src/voxel.h @@ -0,0 +1,224 @@ +#ifndef VOXEL_HEADER +#define VOXEL_HEADER + +#include "common_irrlicht.h" +#include "mapblock.h" +#include + +/* + TODO: A fast voxel manipulator class + + Not thread-safe. +*/ + +/* + This class resembles aabbox3d a lot, but has inclusive + edges for saner handling of integer sizes +*/ +class VoxelArea +{ +public: + // Starts as zero sized + VoxelArea(): + MinEdge(1,1,1), + MaxEdge(0,0,0) + { + } + VoxelArea(v3s16 min_edge, v3s16 max_edge): + MinEdge(min_edge), + MaxEdge(max_edge) + { + } + VoxelArea(v3s16 p): + MinEdge(p), + MaxEdge(p) + { + } + void addArea(VoxelArea &a) + { + if(a.MinEdge.X < MinEdge.X) MinEdge.X = a.MinEdge.X; + if(a.MinEdge.Y < MinEdge.Y) MinEdge.Y = a.MinEdge.Y; + if(a.MinEdge.Z < MinEdge.Z) MinEdge.Z = a.MinEdge.Z; + if(a.MaxEdge.X > MaxEdge.X) MaxEdge.X = a.MaxEdge.X; + if(a.MaxEdge.Y > MaxEdge.Y) MaxEdge.Y = a.MaxEdge.Y; + if(a.MaxEdge.Z > MaxEdge.Z) MaxEdge.Z = a.MaxEdge.Z; + } + void addPoint(v3s16 p) + { + if(p.X < MinEdge.X) MinEdge.X = p.X; + if(p.Y < MinEdge.Y) MinEdge.Y = p.Y; + if(p.Z < MinEdge.Z) MinEdge.Z = p.Z; + if(p.X > MaxEdge.X) MaxEdge.X = p.X; + if(p.Y > MaxEdge.Y) MaxEdge.Y = p.Y; + if(p.Z > MaxEdge.Z) MaxEdge.Z = p.Z; + } + v3s16 getExtent() + { + return MaxEdge - MinEdge + v3s16(1,1,1); + } + s32 getVolume() + { + v3s16 e = getExtent(); + return (s32)e.X * (s32)e.Y * (s32)e.Z; + } + bool isInside(v3s16 p) + { + return( + p.X >= MinEdge.X && p.X <= MaxEdge.X && + p.Y >= MinEdge.Y && p.Y <= MaxEdge.Y && + p.Z >= MinEdge.Z && p.Z <= MaxEdge.Z + ); + } + bool operator==(const VoxelArea &other) + { + return (MinEdge == other.MinEdge + && MaxEdge == other.MaxEdge); + } + + /* + Translates position from virtual coordinates to array index + */ + s32 index(s16 x, s16 y, s16 z) + { + v3s16 em = getExtent(); + v3s16 off = MinEdge; + s32 i = (s32)(z-off.Z)*em.Y*em.X + (y-off.Y)*em.X + (x-off.X); + //dstream<<" i("< & modified_blocks); + +private: + Map *m_map; +}; + +#endif + -- 2.30.2