#include "util/numeric.h" // For IntervalLimiter
#include "util/serialize.h"
#include "util/basic_macros.h"
+#include "client/sound.h"
#include "client/tile.h"
#include "environment.h"
#include "collision.h"
#include "client.h"
#include "wieldmesh.h"
#include <algorithm>
+#include <cmath>
#include "client/renderingengine.h"
class Settings;
std::unordered_map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
-void SmoothTranslator::init(v3f vect)
+template<typename T>
+void SmoothTranslator<T>::init(T current)
{
- vect_old = vect;
- vect_show = vect;
- vect_aim = vect;
- anim_counter = 0;
+ val_old = current;
+ val_current = current;
+ val_target = current;
anim_time = 0;
anim_time_counter = 0;
aim_is_end = true;
}
-void SmoothTranslator::update(v3f vect_new, bool is_end_position, float update_interval)
+template<typename T>
+void SmoothTranslator<T>::update(T new_target, bool is_end_position, float update_interval)
{
aim_is_end = is_end_position;
- vect_old = vect_show;
- vect_aim = vect_new;
- if(update_interval > 0)
- {
+ val_old = val_current;
+ val_target = new_target;
+ if (update_interval > 0) {
anim_time = update_interval;
} else {
- if(anim_time < 0.001 || anim_time > 1.0)
+ if (anim_time < 0.001 || anim_time > 1.0)
anim_time = anim_time_counter;
else
anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
}
anim_time_counter = 0;
- anim_counter = 0;
}
-void SmoothTranslator::translate(f32 dtime)
+template<typename T>
+void SmoothTranslator<T>::translate(f32 dtime)
+{
+ anim_time_counter = anim_time_counter + dtime;
+ T val_diff = val_target - val_old;
+ f32 moveratio = 1.0;
+ if (anim_time > 0.001)
+ moveratio = anim_time_counter / anim_time;
+ f32 move_end = aim_is_end ? 1.0 : 1.5;
+
+ // Move a bit less than should, to avoid oscillation
+ moveratio = std::min(moveratio * 0.8f, move_end);
+ val_current = val_old + val_diff * moveratio;
+}
+
+void SmoothTranslatorWrapped::translate(f32 dtime)
{
anim_time_counter = anim_time_counter + dtime;
- anim_counter = anim_counter + dtime;
- v3f vect_move = vect_aim - vect_old;
+ f32 val_diff = std::abs(val_target - val_old);
+ if (val_diff > 180.f)
+ val_diff = 360.f - val_diff;
+
f32 moveratio = 1.0;
- if(anim_time > 0.001)
+ if (anim_time > 0.001)
moveratio = anim_time_counter / anim_time;
+ f32 move_end = aim_is_end ? 1.0 : 1.5;
+
// Move a bit less than should, to avoid oscillation
- moveratio = moveratio * 0.8;
- float move_end = 1.5;
- if(aim_is_end)
- move_end = 1.0;
- if(moveratio > move_end)
- moveratio = move_end;
- vect_show = vect_old + vect_move * moveratio;
+ moveratio = std::min(moveratio * 0.8f, move_end);
+ wrappedApproachShortest(val_current, val_target,
+ val_diff * moveratio, 360.f);
}
/*
processMessage(message);
}
+ m_yaw = wrapDegrees_0_360(m_yaw);
pos_translator.init(m_position);
+ yaw_translator.init(m_yaw);
updateNodePos();
}
bool GenericCAO::getSelectionBox(aabb3f *toset) const
{
if (!m_prop.is_visible || !m_is_visible || m_is_local_player
- || !m_prop.pointable || getParent() != NULL) {
+ || !m_prop.pointable) {
return false;
}
*toset = m_selection_box;
return m_position;
}
- return pos_translator.vect_show;
+ return pos_translator.val_current;
}
const bool GenericCAO::isImmortal()
m_env->attachement_parent_ids[ci] = 0;
}
}
+ m_children.clear();
m_env->attachement_parent_ids[getId()] = 0;
return;
}
+ video::E_MATERIAL_TYPE material_type = (m_prop.use_texture_alpha) ?
+ video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
if (m_prop.visual == "sprite") {
infostream<<"GenericCAO::addToScene(): single_sprite"<<std::endl;
m_spritenode = RenderingEngine::get_scene_manager()->addBillboardSceneNode(
tsrc->getTextureForMesh("unknown_node.png"));
m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
- m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
+ m_spritenode->setMaterialType(material_type);
m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
u8 li = m_last_light;
m_spritenode->setColor(video::SColor(255,li,li,li));
video::S3DVertex( dx, dy, 0, 0,0,0, c, 0,0),
video::S3DVertex(-dx, dy, 0, 0,0,0, c, 1,0),
};
+ if (m_is_player) {
+ // Move minimal Y position to 0 (feet position)
+ for (video::S3DVertex &vertex : vertices)
+ vertex.Pos.Y += dy;
+ }
u16 indices[] = {0,1,2,2,3,0};
buf->append(vertices, 4, indices, 6);
// Set material
video::S3DVertex(-dx, dy, 0, 0,0,0, c, 0,0),
video::S3DVertex( dx, dy, 0, 0,0,0, c, 1,0),
};
+ if (m_is_player) {
+ // Move minimal Y position to 0 (feet position)
+ for (video::S3DVertex &vertex : vertices)
+ vertex.Pos.Y += dy;
+ }
u16 indices[] = {0,1,2,2,3,0};
buf->append(vertices, 4, indices, 6);
// Set material
m_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
m_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
- m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
+ m_meshnode->setMaterialType(material_type);
m_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
}
else if(m_prop.visual == "mesh") {
setAnimatedMeshColor(m_animated_meshnode, video::SColor(255,li,li,li));
- bool backface_culling = m_prop.backface_culling;
- if (m_is_player)
- backface_culling = false;
-
m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
- m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
+ m_animated_meshnode->setMaterialType(material_type);
m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
- m_animated_meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, backface_culling);
+ m_animated_meshnode->setMaterialFlag(video::EMF_BACK_FACE_CULLING,
+ m_prop.backface_culling);
}
else
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
if (node) {
v3s16 camera_offset = m_env->getCameraOffset();
- node->setPosition(pos_translator.vect_show - intToFloat(camera_offset, BS));
+ node->setPosition(pos_translator.val_current - intToFloat(camera_offset, BS));
if (node != m_spritenode) { // rotate if not a sprite
v3f rot = node->getRotation();
- rot.Y = -m_yaw;
+ rot.Y = m_is_local_player ? -m_yaw : -yaw_translator.val_current;
node->setRotation(rot);
}
}
int old_anim = player->last_animation;
float old_anim_speed = player->last_animation_speed;
m_position = player->getPosition();
+ m_yaw = wrapDegrees_0_360(player->getYaw());
m_velocity = v3f(0,0,0);
m_acceleration = v3f(0,0,0);
- pos_translator.vect_show = m_position;
- m_yaw = player->getYaw();
+ pos_translator.val_current = m_position;
+ yaw_translator.val_current = m_yaw;
const PlayerControl &controls = player->getPlayerControl();
bool walking = false;
m_position = getPosition();
m_velocity = v3f(0,0,0);
m_acceleration = v3f(0,0,0);
- pos_translator.vect_show = m_position;
+ pos_translator.val_current = m_position;
if(m_is_local_player) // Update local player attachment position
{
m_env->getLocalPlayer()->parent = getParent();
}
} else {
- v3f lastpos = pos_translator.vect_show;
+ yaw_translator.translate(dtime);
+ v3f lastpos = pos_translator.val_current;
if(m_prop.physical)
{
updateNodePos();
}
- float moved = lastpos.getDistanceFrom(pos_translator.vect_show);
+ float moved = lastpos.getDistanceFrom(pos_translator.val_current);
m_step_distance_counter += moved;
if (m_step_distance_counter > 1.5f * BS) {
m_step_distance_counter = 0.0f;
updateTextures(m_previous_texture_modifier);
}
}
- if(!getParent() && fabs(m_prop.automatic_rotate) > 0.001)
- {
+ if (!getParent() && std::fabs(m_prop.automatic_rotate) > 0.001) {
m_yaw += dtime * m_prop.automatic_rotate * 180 / M_PI;
+ yaw_translator.val_current = m_yaw;
updateNodePos();
}
+ m_prop.automatic_face_movement_dir_offset;
float max_rotation_delta =
dtime * m_prop.automatic_face_movement_max_rotation_per_sec;
- float delta = wrapDegrees_0_360(target_yaw - m_yaw);
- if (delta > max_rotation_delta && 360 - delta > max_rotation_delta) {
- m_yaw += (delta < 180) ? max_rotation_delta : -max_rotation_delta;
- m_yaw = wrapDegrees_0_360(m_yaw);
- } else {
- m_yaw = target_yaw;
- }
+ wrappedApproachShortest(m_yaw, target_yaw, max_rotation_delta, 360.f);
+ yaw_translator.val_current = m_yaw;
updateNodePos();
}
}
int row = m_tx_basepos.Y;
int col = m_tx_basepos.X;
- if(m_tx_select_horiz_by_yawpitch)
- {
- if(cam_to_entity.Y > 0.75)
+ if (m_tx_select_horiz_by_yawpitch) {
+ if (cam_to_entity.Y > 0.75)
col += 5;
- else if(cam_to_entity.Y < -0.75)
+ else if (cam_to_entity.Y < -0.75)
col += 4;
- else{
+ else {
float mob_dir =
atan2(cam_to_entity.Z, cam_to_entity.X) / M_PI * 180.;
float dir = mob_dir - m_yaw;
dir = wrapDegrees_180(dir);
- //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
- if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
+ if (std::fabs(wrapDegrees_180(dir - 0)) <= 45.1f)
col += 2;
- else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
+ else if(std::fabs(wrapDegrees_180(dir - 90)) <= 45.1f)
col += 3;
- else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
+ else if(std::fabs(wrapDegrees_180(dir - 180)) <= 45.1f)
col += 0;
- else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
+ else if(std::fabs(wrapDegrees_180(dir + 90)) <= 45.1f)
col += 1;
else
col += 4;
float txs = m_tx_size.X;
float tys = m_tx_size.Y;
- setBillboardTextureMatrix(m_spritenode,
- txs, tys, col, row);
+ setBillboardTextureMatrix(m_spritenode, txs, tys, col, row);
}
}
m_current_texture_modifier = mod;
m_glow = m_prop.glow;
+ video::E_MATERIAL_TYPE material_type = (m_prop.use_texture_alpha) ?
+ video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
if (m_spritenode) {
if (m_prop.visual == "sprite") {
std::string texturestring = "unknown_node.png";
if (!m_prop.textures.empty())
texturestring = m_prop.textures[0];
texturestring += mod;
+ m_spritenode->getMaterial(0).MaterialType = material_type;
m_spritenode->setMaterialTexture(0,
tsrc->getTextureForMesh(texturestring));
// Set material flags and texture
video::SMaterial& material = m_animated_meshnode->getMaterial(i);
+ material.MaterialType = material_type;
material.TextureLayer[0].Texture = texture;
material.setFlag(video::EMF_LIGHTING, true);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material.setFlag(video::EMF_BACK_FACE_CULLING, m_prop.backface_culling);
// don't filter low-res textures, makes them look blurry
// player models have a res of 64
// Set material flags and texture
video::SMaterial& material = m_meshnode->getMaterial(i);
+ material.MaterialType = material_type;
material.setFlag(video::EMF_LIGHTING, false);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
material.setTexture(0,
{
if (!m_animated_meshnode)
return;
-
+
m_animated_meshnode->setAnimationSpeed(m_animation_speed);
}
m_position = readV3F1000(is);
m_velocity = readV3F1000(is);
m_acceleration = readV3F1000(is);
- if(fabs(m_prop.automatic_rotate) < 0.001)
+ if (std::fabs(m_prop.automatic_rotate) < 0.001f)
m_yaw = readF1000(is);
else
readF1000(is);
+ m_yaw = wrapDegrees_0_360(m_yaw);
bool do_interpolate = readU8(is);
bool is_end_position = readU8(is);
float update_interval = readF1000(is);
} else {
pos_translator.init(m_position);
}
+ yaw_translator.update(m_yaw, false, update_interval);
updateNodePos();
} else if (cmd == GENERIC_CMD_SET_TEXTURE_MOD) {
std::string mod = deSerializeString(is);
updateBonePosition();
} else if (cmd == GENERIC_CMD_ATTACH_TO) {
- u16 parentID = readS16(is);
- u16 oldparent = m_env->attachement_parent_ids[getId()];
- if (oldparent) {
- m_children.erase(std::remove(m_children.begin(), m_children.end(),
- getId()), m_children.end());
- }
- m_env->attachement_parent_ids[getId()] = parentID;
- GenericCAO *parentobj = m_env->getGenericCAO(parentID);
+ u16 parent_id = readS16(is);
+ u16 &old_parent_id = m_env->attachement_parent_ids[getId()];
+ if (parent_id != old_parent_id) {
+ if (GenericCAO *old_parent = m_env->getGenericCAO(old_parent_id)) {
+ old_parent->m_children.erase(std::remove(
+ m_children.begin(), m_children.end(),
+ getId()), m_children.end());
+ }
+ if (GenericCAO *new_parent = m_env->getGenericCAO(parent_id))
+ new_parent->m_children.push_back(getId());
- if (parentobj) {
- parentobj->m_children.push_back(getId());
+ old_parent_id = parent_id;
}
m_attachment_bone = deSerializeString(is);