23 changes: 22 additions & 1 deletion src/raycast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "raycast.h"
#include "irr_v3d.h"
#include "irr_aabb3d.h"
#include <quaternion.h>
#include "constants.h"

bool RaycastSort::operator() (const PointedThing &pt1,
Expand Down Expand Up @@ -68,7 +69,7 @@ RaycastState::RaycastState(const core::line3d<f32> &shootline,


bool boxLineCollision(const aabb3f &box, const v3f &start,
const v3f &dir, v3f *collision_point, v3s16 *collision_normal)
const v3f &dir, v3f *collision_point, v3f *collision_normal)
{
if (box.isPointInside(start)) {
*collision_point = start;
Expand Down Expand Up @@ -135,3 +136,23 @@ bool boxLineCollision(const aabb3f &box, const v3f &start,
}
return false;
}

bool boxLineCollision(const aabb3f &box, const v3f &rotation,
const v3f &start, const v3f &dir,
v3f *collision_point, v3f *collision_normal, v3f *raw_collision_normal)
{
// Inversely transform the ray rather than rotating the box faces;
// this allows us to continue using a simple ray - AABB intersection
core::quaternion rot(rotation * core::DEGTORAD);
rot.makeInverse();

bool collision = boxLineCollision(box, rot * start, rot * dir, collision_point, collision_normal);
if (!collision) return collision;

// Transform the results back
rot.makeInverse();
*collision_point = rot * *collision_point;
*raw_collision_normal = *collision_normal;
*collision_normal = rot * *collision_normal;
return collision;
}
6 changes: 5 additions & 1 deletion src/raycast.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ class RaycastState
* @returns true if a collision point was found
*/
bool boxLineCollision(const aabb3f &box, const v3f &start, const v3f &dir,
v3f *collision_point, v3s16 *collision_normal);
v3f *collision_point, v3f *collision_normal);

bool boxLineCollision(const aabb3f &box, const v3f &box_rotation,
const v3f &start, const v3f &dir,
v3f *collision_point, v3f *collision_normal, v3f *raw_collision_normal);
10 changes: 7 additions & 3 deletions src/script/common/c_content.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,12 @@ void read_object_properties(lua_State *L, int index,
lua_pop(L, 1);

lua_getfield(L, -1, "selectionbox");
if (lua_istable(L, -1))
if (lua_istable(L, -1)) {
getboolfield(L, -1, "rotate", prop->rotate_selectionbox);
prop->selectionbox = read_aabb3f(L, -1, 1.0);
else if (collisionbox_defined)
} else if (collisionbox_defined) {
prop->selectionbox = prop->collisionbox;
}
lua_pop(L, 1);

getboolfield(L, -1, "pointable", prop->pointable);
Expand Down Expand Up @@ -377,6 +379,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop)
push_aabb3f(L, prop->collisionbox);
lua_setfield(L, -2, "collisionbox");
push_aabb3f(L, prop->selectionbox);
lua_pushboolean(L, prop->rotate_selectionbox);
lua_setfield(L, -2, "rotate");
lua_setfield(L, -2, "selectionbox");
lua_pushboolean(L, prop->pointable);
lua_setfield(L, -2, "pointable");
Expand Down Expand Up @@ -1880,7 +1884,7 @@ void push_pointed_thing(lua_State *L, const PointedThing &pointed, bool csm,
if (hitpoint && (pointed.type != POINTEDTHING_NOTHING)) {
push_v3f(L, pointed.intersection_point / BS); // convert to node coords
lua_setfield(L, -2, "intersection_point");
push_v3s16(L, pointed.intersection_normal);
push_v3f(L, pointed.intersection_normal);
lua_setfield(L, -2, "intersection_normal");
lua_pushinteger(L, pointed.box_id + 1); // change to Lua array index
lua_setfield(L, -2, "box_id");
Expand Down
5 changes: 5 additions & 0 deletions src/server/luaentity_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
}
}

if (fabs(m_prop.automatic_rotate) > 0.001f) {
m_rotation_add_yaw = modulo360f(m_rotation_add_yaw + dtime * core::RADTODEG *
m_prop.automatic_rotate);
}

if(m_registered) {
m_env->getScriptIface()->luaentity_Step(m_id, dtime, moveresult_p);
}
Expand Down
14 changes: 14 additions & 0 deletions src/server/unit_sao.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#include "object_properties.h"
#include "serveractiveobject.h"
#include <quaternion.h>
#include "util/numeric.h"

class UnitSAO : public ServerActiveObject
{
Expand All @@ -36,6 +38,17 @@ class UnitSAO : public ServerActiveObject
// Rotation
void setRotation(v3f rotation) { m_rotation = rotation; }
const v3f &getRotation() const { return m_rotation; }
const v3f getTotalRotation() const {
// This replicates what happens clientside serverside
core::matrix4 rot;
setPitchYawRoll(rot, -m_rotation);
v3f res;
// First rotate by m_rotation, then rotate by the automatic rotate yaw
(core::quaternion(v3f(0, -m_rotation_add_yaw * core::DEGTORAD, 0))
* core::quaternion(rot.getRotationDegrees() * core::DEGTORAD))
.toEuler(res);
return res * core::RADTODEG;
}
v3f getRadRotation() { return m_rotation * core::DEGTORAD; }

// Deprecated
Expand Down Expand Up @@ -95,6 +108,7 @@ class UnitSAO : public ServerActiveObject
u16 m_hp = 1;

v3f m_rotation;
f32 m_rotation_add_yaw = 0;

ItemGroupList m_armor_groups;

Expand Down
25 changes: 18 additions & 7 deletions src/serverenvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1771,16 +1771,27 @@ void ServerEnvironment::getSelectedActiveObjects(
continue;

v3f pos = obj->getBasePosition();

aabb3f offsetted_box(selection_box.MinEdge + pos,
selection_box.MaxEdge + pos);
v3f rel_pos = shootline_on_map.start - pos;

v3f current_intersection;
v3s16 current_normal;
if (boxLineCollision(offsetted_box, shootline_on_map.start, line_vector,
&current_intersection, &current_normal)) {
v3f current_normal;
v3f current_raw_normal;

ObjectProperties *props = obj->accessObjectProperties();
bool collision;
UnitSAO* usao = dynamic_cast<UnitSAO*>(obj);
if (props->rotate_selectionbox && usao != nullptr) {
collision = boxLineCollision(selection_box, usao->getTotalRotation(),
rel_pos, line_vector, &current_intersection, &current_normal, &current_raw_normal);
} else {
collision = boxLineCollision(selection_box, rel_pos, line_vector,
&current_intersection, &current_normal);
current_raw_normal = current_normal;
}
if (collision) {
current_intersection += pos;
objects.emplace_back(
(s16) obj->getId(), current_intersection, current_normal,
(s16) obj->getId(), current_intersection, current_normal, current_raw_normal,
(current_intersection - shootline_on_map.start).getLengthSQ());
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/util/pointedthing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <sstream>

PointedThing::PointedThing(const v3s16 &under, const v3s16 &above,
const v3s16 &real_under, const v3f &point, const v3s16 &normal,
const v3s16 &real_under, const v3f &point, const v3f &normal,
u16 box_id, f32 distSq):
type(POINTEDTHING_NODE),
node_undersurface(under),
Expand All @@ -36,12 +36,13 @@ PointedThing::PointedThing(const v3s16 &under, const v3s16 &above,
distanceSq(distSq)
{}

PointedThing::PointedThing(u16 id, const v3f &point, const v3s16 &normal,
f32 distSq) :
PointedThing::PointedThing(u16 id, const v3f &point,
const v3f &normal, const v3f &raw_normal, f32 distSq) :
type(POINTEDTHING_OBJECT),
object_id(id),
intersection_point(point),
intersection_normal(normal),
raw_intersection_normal(raw_normal),
distanceSq(distSq)
{}

Expand Down
11 changes: 8 additions & 3 deletions src/util/pointedthing.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ struct PointedThing
* This is perpendicular to the face the ray hits,
* points outside of the box and it's length is 1.
*/
v3s16 intersection_normal;
v3f intersection_normal;
/*!
* Only valid if type is POINTEDTHING_OBJECT.
* Raw normal vector of the intersection before applying rotation.
*/
v3f raw_intersection_normal;
/*!
* Only valid if type isn't POINTEDTHING_NONE.
* Indicates which selection box is selected, if there are more of them.
Expand All @@ -90,10 +95,10 @@ struct PointedThing
PointedThing() = default;
//! Constructor for POINTEDTHING_NODE
PointedThing(const v3s16 &under, const v3s16 &above,
const v3s16 &real_under, const v3f &point, const v3s16 &normal,
const v3s16 &real_under, const v3f &point, const v3f &normal,
u16 box_id, f32 distSq);
//! Constructor for POINTEDTHING_OBJECT
PointedThing(u16 id, const v3f &point, const v3s16 &normal, f32 distSq);
PointedThing(u16 id, const v3f &point, const v3f &normal, const v3f &raw_normal, f32 distSq);
std::string dump() const;
void serialize(std::ostream &os) const;
void deSerialize(std::istream &is);
Expand Down