forked from oerkki/voxelands
parent
3c94ab6199
commit
70495d8ebe
344
src/game.cpp
344
src/game.cpp
|
@ -250,88 +250,59 @@ public:
|
|||
/*
|
||||
Find what the player is pointing at
|
||||
*/
|
||||
void getPointedNode(Client *client,
|
||||
v3f camera_direction,v3f camera_position,
|
||||
void getPointedNode(Client *client, v3f player_position,
|
||||
v3f camera_direction, v3f camera_position,
|
||||
bool &nodefound, core::line3d<f32> shootline,
|
||||
v3s16 &nodepos, v3s16 &neighbourpos, v3s16 camera_offset,
|
||||
core::aabbox3d<f32> &nodehilightbox,
|
||||
f32 d)
|
||||
{
|
||||
//inventory
|
||||
f32 mindistance = BS * 1001;
|
||||
|
||||
v3s16 pos_i = floatToInt(player_position, BS);
|
||||
|
||||
/*infostream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
|
||||
<<std::endl;*/
|
||||
//printf("%f,%f,%f - %f,%f,%f\n",shootline.start.X,shootline.start.Y,shootline.start.Z,shootline.end.X,shootline.end.Y,shootline.end.Z);
|
||||
|
||||
s16 a = d;
|
||||
s16 ystart = pos_i.Y + 0 - (camera_direction.Y<0 ? a : 1);
|
||||
s16 zstart = pos_i.Z - (camera_direction.Z<0 ? a : 1);
|
||||
s16 xstart = pos_i.X - (camera_direction.X<0 ? a : 1);
|
||||
s16 yend = pos_i.Y + 1 + (camera_direction.Y>0 ? a : 1);
|
||||
s16 zend = pos_i.Z + (camera_direction.Z>0 ? a : 1);
|
||||
s16 xend = pos_i.X + (camera_direction.X>0 ? a : 1);
|
||||
InventoryItem *wield = (InventoryItem*)client->getLocalPlayer()->getWieldItem();
|
||||
bool wield_is_hand = (wield == NULL);
|
||||
bool wield_is_tool = (wield && wield->getContent()&CONTENT_TOOLITEM_MASK);
|
||||
bool wield_is_craft = (wield && wield->getContent()&CONTENT_CRAFTITEM_MASK);
|
||||
bool wield_is_material = (!wield_is_hand && !wield_is_tool && !wield_is_craft);
|
||||
//initialize iteration
|
||||
|
||||
content_t content = CONTENT_IGNORE;
|
||||
v3s16 cam_i = floatToInt(camera_position, BS);
|
||||
//coordinates of current node
|
||||
s16 x=cam_i.X;
|
||||
s16 y=cam_i.Y;
|
||||
s16 z=cam_i.Z;
|
||||
s16 oldx=x;
|
||||
s16 oldy=y;
|
||||
s16 oldz=z;
|
||||
v3f norm_pos=camera_position/BS;//divide by BS so one node is one unit
|
||||
v3f norm_dir=v3f(camera_direction);
|
||||
norm_dir.normalize();
|
||||
norm_dir*=d;
|
||||
f32 rx=2;//ratio by which we multiply norm_dir to hit node (ratio x)
|
||||
f32 rxs=1;//incrementing rx by rxs gives the next node in x direction (ratio x step)
|
||||
s16 xs=1;//incrementing rx involves incrementing x by xs (x step)
|
||||
if(norm_dir.X>0){//set rx,rxs and xs
|
||||
rx=(floorf(norm_pos.X-0.5)+1.5-norm_pos.X)/norm_dir.X;
|
||||
rxs=1/norm_dir.X;
|
||||
}else if(norm_dir.X<0){
|
||||
rx=(floorf(norm_pos.X-0.5)-norm_pos.X+0.5)/norm_dir.X;
|
||||
rxs=-1/norm_dir.X;
|
||||
xs=-1;
|
||||
}//other directions
|
||||
f32 rz=2;
|
||||
f32 rzs=1;
|
||||
s16 zs=1;
|
||||
if(norm_dir.Z>0){
|
||||
rz=(floorf(norm_pos.Z-0.5)+1.5-norm_pos.Z)/norm_dir.Z;
|
||||
rzs=1/norm_dir.Z;
|
||||
}else if(norm_dir.Z<0){
|
||||
rz=(floorf(norm_pos.Z-0.5)-norm_pos.Z+0.5)/norm_dir.Z;
|
||||
rzs=-1/norm_dir.Z;
|
||||
zs=-1;
|
||||
}
|
||||
f32 ry=2;
|
||||
f32 rys=1;
|
||||
s16 ys=1;
|
||||
if(norm_dir.Y>0){
|
||||
ry=(floorf(norm_pos.Y-0.5)+1.5-norm_pos.Y)/norm_dir.Y;
|
||||
rys=1/norm_dir.Y;
|
||||
}else if(norm_dir.Y<0){
|
||||
ry=(floorf(norm_pos.Y-0.5)-norm_pos.Y+0.5)/norm_dir.Y;
|
||||
rys=-1/norm_dir.Y;
|
||||
ys=-1;
|
||||
}
|
||||
//now iterate through nodes
|
||||
do{
|
||||
bool testable=true;
|
||||
|
||||
for(s16 y = ystart; y <= yend; y++)
|
||||
for(s16 z = zstart; z <= zend; z++)
|
||||
for(s16 x = xstart; x <= xend; x++)
|
||||
{
|
||||
//printf("%d,%d,%d\n",x,y,z);
|
||||
MapNode n;
|
||||
try
|
||||
{
|
||||
n = client->getNode(v3s16(x,y,z));
|
||||
if (content_features(n.getContent()).pointable == false) {
|
||||
if (content_features(n.getContent()).liquid_type != LIQUID_SOURCE)
|
||||
testable=false;
|
||||
continue;
|
||||
if (!wield || content_toolitem_features(wield->getContent()).liquids_pointable == false)
|
||||
testable=false;
|
||||
continue;
|
||||
}else if (content_features(n.getContent()).material_pointable == false && wield_is_material) {
|
||||
testable=false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
testable=false;
|
||||
continue;
|
||||
}
|
||||
//if node is valid
|
||||
if(testable){
|
||||
|
||||
v3s16 np(x,y,z);
|
||||
v3f npf = intToFloat(np, BS);
|
||||
|
||||
|
@ -355,6 +326,7 @@ void getPointedNode(Client *client,
|
|||
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();
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
|
@ -382,17 +354,24 @@ void getPointedNode(Client *client,
|
|||
cpf + v3f(BS/6, BS/3, BS/6)
|
||||
);
|
||||
}
|
||||
if(box.intersectsWithLine(shootline))
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np;
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np;
|
||||
mindistance = distance;
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
}
|
||||
}
|
||||
}else if(n.getContent() == CONTENT_RAIL) {
|
||||
f32 distance = (npf - camera_position).getLength();
|
||||
|
||||
float d = (float)BS/8;
|
||||
v3f vertices[4] =
|
||||
{
|
||||
|
@ -410,15 +389,19 @@ void getPointedNode(Client *client,
|
|||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
|
||||
if(box.intersectsWithLine(shootline))
|
||||
if(distance < mindistance)
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np;
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np;
|
||||
mindistance = distance;
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
}
|
||||
}
|
||||
/*
|
||||
Roofs and Node boxes
|
||||
|
@ -434,104 +417,139 @@ void getPointedNode(Client *client,
|
|||
|| content_features(n).draw_type == CDT_SLABLIKE
|
||||
|| content_features(n).draw_type == CDT_FLAGLIKE
|
||||
) {
|
||||
aabb3f box;
|
||||
aabb3f nhbox(0.5*BS,0.5*BS,0.5*BS,-0.5*BS,-0.5*BS,-0.5*BS);
|
||||
bool hit = false;
|
||||
std::vector<NodeBox> boxes = content_features(n).getNodeBoxes(n);
|
||||
for (std::vector<NodeBox>::iterator b = boxes.begin(); b != boxes.end(); b++) {
|
||||
box = b->m_box;
|
||||
if (nhbox.MinEdge.X > box.MinEdge.X)
|
||||
nhbox.MinEdge.X = box.MinEdge.X;
|
||||
if (nhbox.MinEdge.Y > box.MinEdge.Y)
|
||||
nhbox.MinEdge.Y = box.MinEdge.Y;
|
||||
if (nhbox.MinEdge.Z > box.MinEdge.Z)
|
||||
nhbox.MinEdge.Z = box.MinEdge.Z;
|
||||
if (nhbox.MaxEdge.X < box.MaxEdge.X)
|
||||
nhbox.MaxEdge.X = box.MaxEdge.X;
|
||||
if (nhbox.MaxEdge.Y < box.MaxEdge.Y)
|
||||
nhbox.MaxEdge.Y = box.MaxEdge.Y;
|
||||
if (nhbox.MaxEdge.Z < box.MaxEdge.Z)
|
||||
nhbox.MaxEdge.Z = box.MaxEdge.Z;
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
if (box.intersectsWithLine(shootline)) {
|
||||
for(u16 i=0; i<6; i++) {
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
f32 distance = (npf - camera_position).getLength();
|
||||
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
if (distance < mindistance) {
|
||||
aabb3f box;
|
||||
aabb3f nhbox(0.5*BS,0.5*BS,0.5*BS,-0.5*BS,-0.5*BS,-0.5*BS);
|
||||
bool hit = false;
|
||||
std::vector<NodeBox> boxes = content_features(n).getNodeBoxes(n);
|
||||
for (std::vector<NodeBox>::iterator b = boxes.begin(); b != boxes.end(); b++) {
|
||||
box = b->m_box;
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
if (nhbox.MinEdge.X > box.MinEdge.X)
|
||||
nhbox.MinEdge.X = box.MinEdge.X;
|
||||
if (nhbox.MinEdge.Y > box.MinEdge.Y)
|
||||
nhbox.MinEdge.Y = box.MinEdge.Y;
|
||||
if (nhbox.MinEdge.Z > box.MinEdge.Z)
|
||||
nhbox.MinEdge.Z = box.MinEdge.Z;
|
||||
if (nhbox.MaxEdge.X < box.MaxEdge.X)
|
||||
nhbox.MaxEdge.X = box.MaxEdge.X;
|
||||
if (nhbox.MaxEdge.Y < box.MaxEdge.Y)
|
||||
nhbox.MaxEdge.Y = box.MaxEdge.Y;
|
||||
if (nhbox.MaxEdge.Z < box.MaxEdge.Z)
|
||||
nhbox.MaxEdge.Z = box.MaxEdge.Z;
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np + dirs[i];
|
||||
hit = true;
|
||||
}
|
||||
} // for dirs
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
|
||||
if (box.intersectsWithLine(shootline)) {
|
||||
for(u16 i=0; i<6; i++) {
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
v3f centerpoint = npf + dir_f * BS/2;
|
||||
f32 distance =
|
||||
(centerpoint - camera_position).getLength();
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np + dirs[i];
|
||||
mindistance = distance;
|
||||
|
||||
hit = true;
|
||||
}
|
||||
} // if distance < mindistance
|
||||
} // for dirs
|
||||
}
|
||||
}
|
||||
if (hit) {
|
||||
nhbox.MinEdge -= 0.002;
|
||||
nhbox.MaxEdge += 0.002;
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nhbox.MinEdge += nodepos_f;
|
||||
nhbox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nhbox;
|
||||
}
|
||||
boxes.clear();
|
||||
}
|
||||
if (hit) {
|
||||
nhbox.MinEdge -= 0.002;
|
||||
nhbox.MaxEdge += 0.002;
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nhbox.MinEdge += nodepos_f;
|
||||
nhbox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nhbox;
|
||||
}
|
||||
boxes.clear();
|
||||
|
||||
/*
|
||||
Regular blocks
|
||||
*/
|
||||
}else{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos.set(oldx,oldy,oldz);
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nodebox;
|
||||
for(u16 i=0; i<6; i++)
|
||||
{
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
v3f centerpoint = npf + dir_f * BS/2;
|
||||
f32 distance =
|
||||
(centerpoint - camera_position).getLength();
|
||||
//printf("%f %f - %d,%d,%d\n",distance, mindistance,x,y,z);
|
||||
|
||||
if(distance < mindistance)
|
||||
{
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np + dirs[i];
|
||||
mindistance = distance;
|
||||
|
||||
//nodehilightbox = facebox;
|
||||
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nodebox;
|
||||
}
|
||||
} // if distance < mindistance
|
||||
} // for dirs
|
||||
} // regular block
|
||||
} //testable
|
||||
//if found node, it is the closest
|
||||
if(nodefound)break;
|
||||
//check if we can step forward
|
||||
if(rx>1&&ry>1&&rz>1)break;
|
||||
//step to next node
|
||||
oldx=x;
|
||||
oldy=y;
|
||||
oldz=z;
|
||||
if((rx<ry)&&(rx<rz)){
|
||||
rx+=rxs;
|
||||
x+=xs;
|
||||
}else if(ry<rz){
|
||||
ry+=rys;
|
||||
y+=ys;
|
||||
}else{
|
||||
rz+=rzs;
|
||||
z+=zs;
|
||||
}
|
||||
}while(true);
|
||||
} // for coords
|
||||
if (nodefound) {
|
||||
client->setPointedNode(nodepos);
|
||||
client->setPointedContent(content);
|
||||
|
@ -1615,7 +1633,7 @@ void the_game(
|
|||
v3s16 neighbourpos;
|
||||
core::aabbox3d<f32> nodehilightbox;
|
||||
|
||||
getPointedNode(&client,
|
||||
getPointedNode(&client, player_position,
|
||||
camera_direction, camera_position,
|
||||
nodefound, shootline,
|
||||
nodepos, neighbourpos, camera_offset,
|
||||
|
|
Loading…
Reference in New Issue