Skip to content
Snippets Groups Projects
Commit af95cfc7 authored by Perttu Ahola's avatar Perttu Ahola
Browse files

vokselijuttu lisätty

parent c707e001
No related branches found
No related tags found
No related merge requests found
...@@ -247,6 +247,10 @@ ...@@ -247,6 +247,10 @@
RelativePath=".\src\utility.cpp" RelativePath=".\src\utility.cpp"
> >
</File> </File>
<File
RelativePath=".\src\voxel.cpp"
>
</File>
</Filter> </Filter>
<Filter <Filter
Name="Header Files" Name="Header Files"
......
#include "voxel.h"
#include "map.h"
VoxelManipulator::VoxelManipulator():
m_data(NULL)
{
}
VoxelManipulator::~VoxelManipulator()
{
if(m_data)
delete[] m_data;
}
void VoxelManipulator::addArea(VoxelArea area)
{
if(area.getExtent() == v3s16(0,0,0))
return;
// Calculate new area
VoxelArea new_area;
if(m_area.getExtent() == v3s16(0,0,0))
{
new_area = area;
}
else
{
new_area = m_area;
new_area.addArea(area);
}
if(new_area == m_area)
return;
s32 new_size = new_area.getVolume();
/*dstream<<"adding area ";
area.print(dstream);
dstream<<", old area ";
m_area.print(dstream);
dstream<<", new area ";
new_area.print(dstream);
dstream<<", new_size="<<new_size;
dstream<<std::endl;*/
// Allocate and clear new data
MapNode *new_data;
new_data = new MapNode[new_size];
for(s32 i=0; i<new_size; i++)
{
new_data[i].d = MATERIAL_IGNORE;
}
// Copy old data
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++)
{
new_data[new_area.index(z,y,x)] = m_data[m_area.index(x,y,z)];
}
// Replace member
m_area = new_area;
MapNode *old_data = m_data;
m_data = new_data;
delete[] old_data;
}
void VoxelManipulator::print(std::ostream &o)
{
v3s16 em = m_area.getExtent();
v3s16 of = m_area.MinEdge;
o<<"size: "<<em.X<<"x"<<em.Y<<"x"<<em.Z
<<" offset: ("<<of.X<<","<<of.Y<<","<<of.Z<<")"<<std::endl;
for(s32 y=m_area.MinEdge.Y; y<=m_area.MaxEdge.Y; y++)
{
if(em.X >= 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<<c;
}
o<<' ';
}
o<<std::endl;
}
}
void VoxelManipulator::interpolate(VoxelArea area)
{
VoxelArea emerge_area = area;
emerge_area.MinEdge -= v3s16(1,1,1);
emerge_area.MaxEdge += v3s16(1,1,1);
emerge(emerge_area);
SharedBuffer<u8> 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; z<size.Z; z++)
for(s16 y=0; y<size.Y; y++)
for(s16 x=0; x<size.X; x++)
{
v3s16 p(x,y,z);
try{
MapNode n = c->getNode(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; z<size.Z; z++)
for(s16 y=0; y<size.Y; y++)
for(s16 x=0; x<size.X; x++)
{
v3s16 p(x,y,z);
try{
MapNode &n = m_data[m_area.index(p_from + p)];
if(n.d == MATERIAL_IGNORE)
continue;
c->setNode(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; z<size.Z; z++)
for(s16 y=0; y<size.Y; y++)
for(s16 x=0; x<size.X; x++)
{
v3s16 p(x,y,z);
try{
MapNode n = m_map->getNode(a.MinEdge + p);
m_data[m_area.index(a.MinEdge + p)] = n;
}
catch(InvalidPositionException &e)
{
}
}
}
void MapVoxelManipulator::blitBack
(core::map<v3s16, MapBlock*> & 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
#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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment