From 9961185550ff2a8ada61455ac351f85ea7122aa2 Mon Sep 17 00:00:00 2001 From: RealBadAngel Date: Sat, 20 Feb 2016 10:58:40 +0100 Subject: [PATCH] Fix getting pointed node Fixes #3719 Closes #3753 --- src/game.cpp | 136 +++++++++++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 59 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index 9729ca477..18ca11d6f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -304,7 +304,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio INodeDefManager *nodedef = client->getNodeDefManager(); ClientMap &map = client->getEnv().getClientMap(); - f32 mindistance = BS * 1001; + f32 min_distance = BS * 1001; // First try to find a pointed at active object if (look_for_object) { @@ -324,7 +324,7 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio 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.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 - v3s16 pos_i = floatToInt(player_position, BS); /*infostream<<"pos_i=("< 0 ? a : 1); @@ -357,24 +356,25 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio if (xend == 32767) xend = 32766; - for (s16 y = ystart; y <= yend; y++) - for (s16 z = zstart; z <= zend; z++) + v3s16 pointed_pos(0, 0, 0); + + for (s16 y = ystart; y <= yend; y++) { + for (s16 z = zstart; z <= zend; z++) { for (s16 x = xstart; x <= xend; x++) { MapNode n; bool is_valid_position; n = map.getNodeNoEx(v3s16(x, y, z), &is_valid_position); - if (!is_valid_position) + if (!is_valid_position) { continue; - - if (!isPointableNode(n, client, liquids_pointable)) + } + if (!isPointableNode(n, client, liquids_pointable)) { continue; - + } std::vector boxes = n.getSelectionBoxes(nodedef); v3s16 np(x, y, z); v3f npf = intToFloat(np, BS); - for (std::vector::const_iterator i = boxes.begin(); i != boxes.end(); ++i) { @@ -382,62 +382,80 @@ PointedThing getPointedThing(Client *client, Hud *hud, const v3f &player_positio box.MinEdge += npf; box.MaxEdge += npf; - for (u16 j = 0; j < 6; j++) { - v3s16 facedir = g_6dirs[j]; - aabb3f facebox = box; - - 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::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); + v3f centerpoint = box.getCenter(); + f32 distance = (centerpoint - camera_position).getLength(); + if (distance >= min_distance) { + continue; } + 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 boxes = n.getSelectionBoxes(nodedef); + f32 face_min_distance = 1000 * BS; + for (std::vector::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::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 if (selectionboxes->size() > 0) { v3f pf = hud->getSelectionPos(); - v3s16 p = floatToInt(pf, BS); + v3s16 p = floatToInt(pf, BS); // Get selection mesh light level - MapNode n = map.getNodeNoEx(p); + MapNode n = map.getNodeNoEx(p); u16 node_light = getInteriorLight(n, -1, nodedef); u16 light_level = node_light;