Fix getting pointed node

Fixes #3719
Closes #3753
This commit is contained in:
RealBadAngel 2016-02-20 10:58:40 +01:00 committed by est31
parent 31e0667a4a
commit 9961185550
1 changed files with 77 additions and 59 deletions

View File

@ -304,7 +304,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
INodeDefManager *nodedef = client->getNodeDefManager(); INodeDefManager *nodedef = client->getNodeDefManager();
ClientMap &map = client->getEnv().getClientMap(); ClientMap &map = client->getEnv().getClientMap();
f32 mindistance = BS * 1001; f32 min_distance = BS * 1001;
// First try to find a pointed at active object // First try to find a pointed at active object
if (look_for_object) { if (look_for_object) {
@ -324,7 +324,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
hud->setSelectionPos(pos, camera_offset); hud->setSelectionPos(pos, camera_offset);
} }
mindistance = (selected_object->getPosition() - camera_position).getLength(); min_distance = (selected_object->getPosition() - camera_position).getLength();
result.type = POINTEDTHING_OBJECT; result.type = POINTEDTHING_OBJECT;
result.object_id = selected_object->getId(); result.object_id = selected_object->getId();
@ -333,14 +333,13 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
// That didn't work, try to find a pointed at node // That didn't work, try to find a pointed at node
v3s16 pos_i = floatToInt(player_position, BS); v3s16 pos_i = floatToInt(player_position, BS);
/*infostream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")" /*infostream<<"pos_i=("<<pos_i.X<<","<<pos_i.Y<<","<<pos_i.Z<<")"
<<std::endl;*/ <<std::endl;*/
s16 a = d; s16 a = d;
s16 ystart = pos_i.Y + 0 - (camera_direction.Y < 0 ? a : 1); s16 ystart = pos_i.Y - (camera_direction.Y < 0 ? a : 1);
s16 zstart = pos_i.Z - (camera_direction.Z < 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 xstart = pos_i.X - (camera_direction.X < 0 ? a : 1);
s16 yend = pos_i.Y + 1 + (camera_direction.Y > 0 ? a : 1); s16 yend = pos_i.Y + 1 + (camera_direction.Y > 0 ? a : 1);
@ -357,24 +356,25 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
if (xend == 32767) if (xend == 32767)
xend = 32766; xend = 32766;
for (s16 y = ystart; y <= yend; y++) v3s16 pointed_pos(0, 0, 0);
for (s16 z = zstart; z <= zend; z++)
for (s16 y = ystart; y <= yend; y++) {
for (s16 z = zstart; z <= zend; z++) {
for (s16 x = xstart; x <= xend; x++) { for (s16 x = xstart; x <= xend; x++) {
MapNode n; MapNode n;
bool is_valid_position; bool is_valid_position;
n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position); n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position);
if (!is_valid_position) if (!is_valid_position) {
continue; continue;
}
if (!isPointableNode(n, client, liquids_pointable)) if (!isPointableNode(n, client, liquids_pointable)) {
continue; continue;
}
std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef); std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
v3s16 np(x, y, z); v3s16 np(x, y, z);
v3f npf = intToFloat(np, BS); v3f npf = intToFloat(np, BS);
for (std::vector<aabb3f>::const_iterator for (std::vector<aabb3f>::const_iterator
i = boxes.begin(); i = boxes.begin();
i != boxes.end(); ++i) { i != boxes.end(); ++i) {
@ -382,62 +382,80 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio
box.MinEdge += npf; box.MinEdge += npf;
box.MaxEdge += npf; box.MaxEdge += npf;
for (u16 j = 0; j < 6; j++) { v3f centerpoint = box.getCenter();
v3s16 facedir = g_6dirs[j]; f32 distance = (centerpoint - camera_position).getLength();
aabb3f facebox = box; if (distance >= min_distance) {
continue;
f32 d = 0.001 * BS;
if (facedir.X > 0)
facebox.MinEdge.X = facebox.MaxEdge.X - d;
else if (facedir.X < 0)
facebox.MaxEdge.X = facebox.MinEdge.X + d;
else if (facedir.Y > 0)
facebox.MinEdge.Y = facebox.MaxEdge.Y - d;
else if (facedir.Y < 0)
facebox.MaxEdge.Y = facebox.MinEdge.Y + d;
else if (facedir.Z > 0)
facebox.MinEdge.Z = facebox.MaxEdge.Z - d;
else if (facedir.Z < 0)
facebox.MaxEdge.Z = facebox.MinEdge.Z + d;
v3f centerpoint = facebox.getCenter();
f32 distance = (centerpoint - camera_position).getLength();
if (distance >= mindistance)
continue;
if (!facebox.intersectsWithLine(shootline))
continue;
v3s16 np_above = np + facedir;
result.type = POINTEDTHING_NODE;
result.node_undersurface = np;
result.node_abovesurface = np_above;
mindistance = distance;
selectionboxes->clear();
for (std::vector<aabb3f>::const_iterator
i2 = boxes.begin();
i2 != boxes.end(); ++i2) {
aabb3f box = *i2;
box.MinEdge += v3f(-d, -d, -d);
box.MaxEdge += v3f(d, d, d);
selectionboxes->push_back(box);
}
hud->setSelectionPos(npf, camera_offset);
} }
if (!box.intersectsWithLine(shootline)) {
continue;
}
result.type = POINTEDTHING_NODE;
min_distance = distance;
pointed_pos = np;
} }
} // for coords }
}
}
if (result.type == POINTEDTHING_NODE) {
f32 d = 0.001 * BS;
MapNode n = map.getNodeNoEx(pointed_pos);
v3f npf = intToFloat(pointed_pos, BS);
std::vector<aabb3f> boxes = n.getSelectionBoxes(nodedef);
f32 face_min_distance = 1000 * BS;
for (std::vector<aabb3f>::const_iterator
i = boxes.begin();
i != boxes.end(); ++i) {
aabb3f box = *i;
box.MinEdge += npf;
box.MaxEdge += npf;
for (u16 j = 0; j < 6; j++) {
v3s16 facedir = g_6dirs[j];
aabb3f facebox = box;
if (facedir.X > 0) {
facebox.MinEdge.X = facebox.MaxEdge.X - d;
} else if (facedir.X < 0) {
facebox.MaxEdge.X = facebox.MinEdge.X + d;
} else if (facedir.Y > 0) {
facebox.MinEdge.Y = facebox.MaxEdge.Y - d;
} else if (facedir.Y < 0) {
facebox.MaxEdge.Y = facebox.MinEdge.Y + d;
} else if (facedir.Z > 0) {
facebox.MinEdge.Z = facebox.MaxEdge.Z - d;
} else if (facedir.Z < 0) {
facebox.MaxEdge.Z = facebox.MinEdge.Z + d;
}
v3f centerpoint = facebox.getCenter();
f32 distance = (centerpoint - camera_position).getLength();
if (distance >= face_min_distance)
continue;
if (!facebox.intersectsWithLine(shootline))
continue;
result.node_abovesurface = pointed_pos + facedir;
face_min_distance = distance;
}
}
selectionboxes->clear();
for (std::vector<aabb3f>::const_iterator
i = boxes.begin();
i != boxes.end(); ++i) {
aabb3f box = *i;
box.MinEdge += v3f(-d, -d, -d);
box.MaxEdge += v3f(d, d, d);
selectionboxes->push_back(box);
}
hud->setSelectionPos(intToFloat(pointed_pos, BS), camera_offset);
result.node_undersurface = pointed_pos;
}
// Update selection mesh light level and vertex colors // Update selection mesh light level and vertex colors
if (selectionboxes->size() > 0) { if (selectionboxes->size() > 0) {
v3f pf = hud->getSelectionPos(); v3f pf = hud->getSelectionPos();
v3s16 p = floatToInt(pf, BS); v3s16 p = floatToInt(pf, BS);
// Get selection mesh light level // Get selection mesh light level
MapNode n = map.getNodeNoEx(p); MapNode n = map.getNodeNoEx(p);
u16 node_light = getInteriorLight(n, -1, nodedef); u16 node_light = getInteriorLight(n, -1, nodedef);
u16 light_level = node_light; u16 light_level = node_light;