diff options
author | Perttu Ahola <celeron55@gmail.com> | 2010-11-29 10:57:05 +0200 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2010-11-29 10:57:05 +0200 |
commit | af95cfc7a15788386d055a5b4a7377673d36b8bf (patch) | |
tree | 97889cda4bcf9225275f1ce0929bf65f0d59f23a /src/voxel.h | |
parent | c707e00195f1035ae535f3fc8697af42e73190c0 (diff) | |
download | minetest-af95cfc7a15788386d055a5b4a7377673d36b8bf.tar.gz minetest-af95cfc7a15788386d055a5b4a7377673d36b8bf.tar.bz2 minetest-af95cfc7a15788386d055a5b4a7377673d36b8bf.zip |
vokselijuttu lisätty
Diffstat (limited to 'src/voxel.h')
-rw-r--r-- | src/voxel.h | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/voxel.h b/src/voxel.h new file mode 100644 index 000000000..eee9177f3 --- /dev/null +++ b/src/voxel.h @@ -0,0 +1,224 @@ +#ifndef VOXEL_HEADER +#define VOXEL_HEADER + +#include "common_irrlicht.h" +#include "mapblock.h" +#include <iostream> + +/* + TODO: A fast voxel manipulator class + + Not thread-safe. +*/ + +/* + This class resembles aabbox3d<s16> 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("<<x<<","<<y<<","<<z<<")="<<i<<" "; + return i; + } + s32 index(v3s16 p) + { + return index(p.X, p.Y, p.Z); + } + + void print(std::ostream &o) + { + o<<"("<<MinEdge.X + <<","<<MinEdge.Y + <<","<<MinEdge.Z + <<")("<<MaxEdge.X + <<","<<MaxEdge.Y + <<","<<MaxEdge.Z + <<")"; + } + + // Edges are inclusive + v3s16 MinEdge; + v3s16 MaxEdge; +}; + +class VoxelManipulator : public NodeContainer +{ +public: + VoxelManipulator(); + ~VoxelManipulator(); + + /* + Virtuals from NodeContainer + */ + virtual u16 nodeContainerId() const + { + return NODECONTAINER_ID_VOXELMANIPULATOR; + } + bool isValidPosition(v3s16 p) + { + return m_area.isInside(p); + } + // These are a bit slow and shouldn't be used internally + MapNode getNode(v3s16 p) + { + if(isValidPosition(p) == false) + emerge(VoxelArea(p)); + + MapNode &n = m_data[m_area.index(p)]; + + //TODO: Is this the right behaviour? + if(n.d == MATERIAL_IGNORE) + throw InvalidPositionException + ("Not returning MATERIAL_IGNORE in VoxelManipulator"); + + return n; + } + void setNode(v3s16 p, MapNode & n) + { + if(isValidPosition(p) == false) + emerge(VoxelArea(p)); + m_data[m_area.index(p)] = n; + } + + MapNode & operator[](v3s16 p) + { + //dstream<<"operator[] p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl; + if(isValidPosition(p) == false) + emerge(VoxelArea(p)); + return m_data[m_area.index(p)]; + } + + /* + Manipulation of bigger chunks + */ + + void print(std::ostream &o); + + void addArea(VoxelArea area); + + void interpolate(VoxelArea area); + + /*void blitFromNodeContainer + (v3s16 p_from, v3s16 p_to, v3s16 size, NodeContainer *c); + + void blitToNodeContainer + (v3s16 p_from, v3s16 p_to, v3s16 size, NodeContainer *c);*/ + + /* + Virtual functions + */ + + /* + Get the contents of the requested area from somewhere. + + If not found from source, add as MATERIAL_IGNORE. + */ + virtual void emerge(VoxelArea a) + { + //dstream<<"emerge p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl; + addArea(a); + } + + /* + Member variables + */ + + /* + The area that is stored in m_data. + addInternalBox should not be used if getExtent() == v3s16(0,0,0) + MaxEdge is 1 higher than maximum allowed position + */ + VoxelArea m_area; + /* + NULL if data size is 0 + Data is stored as [z*h*w + y*h + x] + Special data values: + MATERIAL_IGNORE: Unspecified node + */ + MapNode *m_data; +private: +}; + +class Map; + +class MapVoxelManipulator : public VoxelManipulator +{ +public: + MapVoxelManipulator(Map *map); + + virtual void emerge(VoxelArea a); + + void blitBack(core::map<v3s16, MapBlock*> & modified_blocks); + +private: + Map *m_map; +}; + +#endif + |