Generalize selection boxes

This commit is contained in:
Perttu Ahola 2011-11-13 12:31:05 +02:00
parent 2ef414d05f
commit 79c9f14aec
3 changed files with 97 additions and 165 deletions

@ -335,6 +335,7 @@ void content_mapnode_init()
f->solidness = 0; // drawn separately, makes no faces
f->air_equivalent = true; // grass grows underneath
f->walkable = false;
f->selection_box.type = NODEBOX_FIXED;
setDirtLikeDiggingProperties(f->digging_properties, 0.75);
i = CONTENT_LADDER;
@ -350,6 +351,7 @@ void content_mapnode_init()
f->air_equivalent = true;
f->walkable = false;
f->climbable = true;
f->selection_box.type = NODEBOX_WALLMOUNTED;
setWoodLikeDiggingProperties(f->digging_properties, 0.5);
// Deprecated
@ -606,6 +608,13 @@ void content_mapnode_init()
f->air_equivalent = true;
f->dug_item = std::string("MaterialItem2 ")+itos(i)+" 1";
f->light_source = LIGHT_MAX-1;
f->selection_box.type = NODEBOX_WALLMOUNTED;
f->selection_box.wall_top = core::aabbox3d<f32>(
-BS/10, BS/2-BS/3.333*2, -BS/10, BS/10, BS/2, BS/10);
f->selection_box.wall_bottom = core::aabbox3d<f32>(
-BS/10, -BS/2, -BS/10, BS/10, -BS/2+BS/3.333*2, BS/10);
f->selection_box.wall_side = core::aabbox3d<f32>(
-BS/2, -BS/3.333, -BS/10, -BS/2+BS/3.333, BS/3.333, BS/10);
f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
i = CONTENT_SIGN_WALL;
@ -623,6 +632,7 @@ void content_mapnode_init()
if(f->initial_metadata == NULL)
f->initial_metadata = new SignNodeMetadata("Some sign");
f->digging_properties.set("", DiggingProperties(true, 0.5, 0));
f->selection_box.type = NODEBOX_WALLMOUNTED;
i = CONTENT_CHEST;
f = &content_features(i);

@ -43,7 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "gettext.h"
#include "log.h"
#include "filesys.h"
// Needed for some special cases for CONTENT_TORCH and CONTENT_SIGN_WALL
// Needed for writing to signs (CONTENT_SIGN_WALL)
// TODO: A generic way for handling such should be created
#include "content_mapnode.h"
// Needed for sign text input
@ -343,10 +343,29 @@ void getPointedNode(Client *client, v3f player_position,
v3s16(-1,0,0), // left
};
/*
Meta-objects
*/
if(n.getContent() == CONTENT_TORCH)
ContentFeatures &f = content_features(n);
if(f.selection_box.type == NODEBOX_FIXED)
{
f32 distance = (npf - camera_position).getLength();
core::aabbox3d<f32> box = f.selection_box.fixed;
box.MinEdge += npf;
box.MaxEdge += npf;
if(distance < mindistance)
{
if(box.intersectsWithLine(shootline))
{
nodefound = true;
nodepos = np;
neighbourpos = np;
mindistance = distance;
nodehilightbox = box;
}
}
}
else if(f.selection_box.type == NODEBOX_WALLMOUNTED)
{
v3s16 dir = unpackDir(n.param2);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
@ -356,129 +375,40 @@ void getPointedNode(Client *client, v3f player_position,
core::aabbox3d<f32> box;
// bottom
if(dir == v3s16(0,-1,0))
{
box = core::aabbox3d<f32>(
npf - v3f(BS/6, BS/2, BS/6),
npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
);
}
// top
else if(dir == v3s16(0,1,0))
{
box = core::aabbox3d<f32>(
npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
npf + v3f(BS/6, BS/2, BS/6)
);
if(dir == v3s16(0,1,0)){
box = f.selection_box.wall_top;
}
// bottom
else if(dir == v3s16(0,-1,0)){
box = f.selection_box.wall_bottom;
}
// side
else
else{
v3f vertices[2] =
{
box = core::aabbox3d<f32>(
cpf - v3f(BS/6, BS/3, BS/6),
cpf + v3f(BS/6, BS/3, BS/6)
);
}
if(distance < mindistance)
{
if(box.intersectsWithLine(shootline))
{
nodefound = true;
nodepos = np;
neighbourpos = np;
mindistance = distance;
nodehilightbox = box;
}
}
}
else if(n.getContent() == CONTENT_SIGN_WALL)
{
v3s16 dir = unpackDir(n.param2);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f;
f32 distance = (cpf - camera_position).getLength();
v3f vertices[4] =
{
v3f(BS*0.42,-BS*0.35,-BS*0.4),
v3f(BS*0.49, BS*0.35, BS*0.4),
f.selection_box.wall_side.MinEdge,
f.selection_box.wall_side.MaxEdge
};
for(s32 i=0; i<2; i++)
{
if(dir == v3s16(1,0,0))
vertices[i].rotateXZBy(0);
if(dir == v3s16(-1,0,0))
vertices[i].rotateXZBy(180);
if(dir == v3s16(0,0,1))
vertices[i].rotateXZBy(90);
if(dir == v3s16(0,0,-1))
vertices[i].rotateXZBy(-90);
if(dir == v3s16(0,-1,0))
vertices[i].rotateXYBy(-90);
if(dir == v3s16(0,1,0))
vertices[i].rotateXYBy(90);
vertices[i] += npf;
}
core::aabbox3d<f32> box;
box = core::aabbox3d<f32>(vertices[0]);
box.addInternalPoint(vertices[1]);
if(distance < mindistance)
{
if(box.intersectsWithLine(shootline))
{
nodefound = true;
nodepos = np;
neighbourpos = np;
mindistance = distance;
nodehilightbox = box;
}
}
}
else if(n.getContent() == CONTENT_LADDER)
{
v3s16 dir = unpackDir(n.param2);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f;
f32 distance = (cpf - camera_position).getLength();
v3f vertices[4] =
{
v3f(BS*0.42,-BS/2,-BS/2),
v3f(BS*0.49, BS/2, BS/2),
};
for(s32 i=0; i<2; i++)
{
if(dir == v3s16(1,0,0))
vertices[i].rotateXZBy(0);
if(dir == v3s16(-1,0,0))
if(dir == v3s16(1,0,0))
vertices[i].rotateXZBy(180);
if(dir == v3s16(0,0,1))
vertices[i].rotateXZBy(90);
if(dir == v3s16(0,0,-1))
vertices[i].rotateXZBy(90);
if(dir == v3s16(0,0,1))
vertices[i].rotateXZBy(-90);
if(dir == v3s16(0,-1,0))
vertices[i].rotateXYBy(-90);
if(dir == v3s16(0,1,0))
vertices[i].rotateXYBy(90);
vertices[i] += npf;
}
core::aabbox3d<f32> box;
box = core::aabbox3d<f32>(vertices[0]);
box.addInternalPoint(vertices[1]);
}
box.MinEdge += npf;
box.MaxEdge += npf;
if(distance < mindistance)
{
@ -492,47 +422,7 @@ void getPointedNode(Client *client, v3f player_position,
}
}
}
else if(n.getContent() == CONTENT_RAIL)
{
v3s16 dir = unpackDir(n.param0);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f;
f32 distance = (cpf - camera_position).getLength();
float d = (float)BS/16;
v3f vertices[4] =
{
v3f(BS/2, -BS/2+d, -BS/2),
v3f(-BS/2, -BS/2, BS/2),
};
for(s32 i=0; i<2; i++)
{
vertices[i] += npf;
}
core::aabbox3d<f32> box;
box = core::aabbox3d<f32>(vertices[0]);
box.addInternalPoint(vertices[1]);
if(distance < mindistance)
{
if(box.intersectsWithLine(shootline))
{
nodefound = true;
nodepos = np;
neighbourpos = np;
mindistance = distance;
nodehilightbox = box;
}
}
}
/*
Regular blocks
*/
else
else // NODEBOX_REGULAR
{
for(u16 i=0; i<6; i++)
{

@ -57,6 +57,35 @@ enum LiquidType
LIQUID_SOURCE
};
enum NodeBoxType
{
NODEBOX_REGULAR, // Regular block; allows buildable_to
NODEBOX_FIXED, // Static separately defined box
NODEBOX_WALLMOUNTED, // Box for wall_mounted nodes; (top, bottom, side)
};
struct NodeBox
{
enum NodeBoxType type;
// NODEBOX_REGULAR (no parameters)
// NODEBOX_FIXED
core::aabbox3d<f32> fixed;
// NODEBOX_WALLMOUNTED
core::aabbox3d<f32> wall_top;
core::aabbox3d<f32> wall_bottom;
core::aabbox3d<f32> wall_side; // being at the -X side
NodeBox():
type(NODEBOX_REGULAR),
// default is rail-like
fixed(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
// default is sign/ladder-like
wall_top(-BS/2, BS/2-BS/16., -BS/2, BS/2, BS/2, BS/2),
wall_bottom(-BS/2, -BS/2, -BS/2, BS/2, -BS/2+BS/16., BS/2),
wall_side(-BS/2, -BS/2, -BS/2, -BS/2+BS/16., BS/2, BS/2)
{}
};
struct MapNode;
class NodeMetadata;
@ -150,6 +179,8 @@ struct ContentFeatures
u32 damage_per_second;
NodeBox selection_box;
// NOTE: Move relevant properties to here from elsewhere
void reset()
@ -186,6 +217,7 @@ struct ContentFeatures
light_source = 0;
digging_properties.clear();
damage_per_second = 0;
selection_box = NodeBox();
}
ContentFeatures()