diff --git a/src/client/clientobject.h b/src/client/clientobject.h index 987005730..05c235ace 100644 --- a/src/client/clientobject.h +++ b/src/client/clientobject.h @@ -48,8 +48,7 @@ public: virtual bool getCollisionBox(aabb3f *toset) const { return false; } virtual bool getSelectionBox(aabb3f *toset) const { return false; } virtual bool collideWithObjects() const { return false; } - virtual v3f getPosition(){ return v3f(0,0,0); } - virtual float getYaw() const { return 0; } + virtual const v3f getPosition() const { return v3f(0.0f); } virtual scene::ISceneNode *getSceneNode() { return NULL; } virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode() { return NULL; } virtual bool isLocalPlayer() const {return false;} diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index e76cacdd4..d7ab8e945 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -401,7 +401,7 @@ bool GenericCAO::getSelectionBox(aabb3f *toset) const return true; } -v3f GenericCAO::getPosition() +const v3f GenericCAO::getPosition() const { if (getParent() != nullptr) { if (m_matrixnode) diff --git a/src/client/content_cao.h b/src/client/content_cao.h index aef1f1296..3a071101f 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -154,12 +154,9 @@ public: virtual bool getSelectionBox(aabb3f *toset) const; - v3f getPosition(); + const v3f getPosition() const; - inline const v3f &getRotation() - { - return m_rotation; - } + inline const v3f &getRotation() const { return m_rotation; } const bool isImmortal(); @@ -180,6 +177,12 @@ public: return m_matrixnode->getRelativeTransformationMatrix(); } + inline const core::matrix4 &getAbsolutePosRotMatrix() const + { + assert(m_matrixnode); + return m_matrixnode->getAbsoluteTransformation(); + } + inline f32 getStepHeight() const { return m_prop.stepheight; diff --git a/src/client/particles.cpp b/src/client/particles.cpp index 4777a5b99..f59f8f083 100644 --- a/src/client/particles.cpp +++ b/src/client/particles.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "client.h" #include "collision.h" +#include "client/content_cao.h" #include "client/clientevent.h" #include "client/renderingengine.h" #include "util/numeric.h" @@ -38,9 +39,10 @@ with this program; if not, write to the Free Software Foundation, Inc., v3f random_v3f(v3f min, v3f max) { - return v3f( rand()/(float)RAND_MAX*(max.X-min.X)+min.X, - rand()/(float)RAND_MAX*(max.Y-min.Y)+min.Y, - rand()/(float)RAND_MAX*(max.Z-min.Z)+min.Z); + return v3f( + rand() / (float)RAND_MAX * (max.X - min.X) + min.X, + rand() / (float)RAND_MAX * (max.Y - min.Y) + min.Y, + rand() / (float)RAND_MAX * (max.Z - min.Z) + min.Z); } Particle::Particle( @@ -299,16 +301,21 @@ ParticleSpawner::ParticleSpawner( } void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius, - bool is_attached, const v3f &attached_pos, float attached_yaw) + const core::matrix4 *attached_absolute_pos_rot_matrix) { v3f ppos = m_player->getPosition() / BS; v3f pos = random_v3f(m_minpos, m_maxpos); // Need to apply this first or the following check // will be wrong for attached spawners - if (is_attached) { - pos.rotateXZBy(attached_yaw); - pos += attached_pos; + if (attached_absolute_pos_rot_matrix) { + pos *= BS; + attached_absolute_pos_rot_matrix->transformVect(pos); + pos /= BS; + v3s16 camera_offset = m_particlemanager->m_env->getCameraOffset(); + pos.X += camera_offset.X; + pos.Y += camera_offset.Y; + pos.Z += camera_offset.Z; } if (pos.getDistanceFrom(ppos) > radius) @@ -317,18 +324,19 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius, v3f vel = random_v3f(m_minvel, m_maxvel); v3f acc = random_v3f(m_minacc, m_maxacc); - if (is_attached) { - // Apply attachment yaw - vel.rotateXZBy(attached_yaw); - acc.rotateXZBy(attached_yaw); + if (attached_absolute_pos_rot_matrix) { + // Apply attachment rotation + attached_absolute_pos_rot_matrix->rotateVect(vel); + attached_absolute_pos_rot_matrix->rotateVect(acc); } float exptime = rand() / (float)RAND_MAX - * (m_maxexptime - m_minexptime) - + m_minexptime; + * (m_maxexptime - m_minexptime) + + m_minexptime; + float size = rand() / (float)RAND_MAX - * (m_maxsize - m_minsize) - + m_minsize; + * (m_maxsize - m_minsize) + + m_minsize; m_particlemanager->addParticle(new Particle( m_gamedef, @@ -359,14 +367,10 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE; bool unloaded = false; - bool is_attached = false; - v3f attached_pos = v3f(0,0,0); - float attached_yaw = 0; - if (m_attached_id != 0) { - if (ClientActiveObject *attached = env->getActiveObject(m_attached_id)) { - attached_pos = attached->getPosition() / BS; - attached_yaw = attached->getYaw(); - is_attached = true; + const core::matrix4 *attached_absolute_pos_rot_matrix = nullptr; + if (m_attached_id) { + if (GenericCAO *attached = dynamic_cast(env->getActiveObject(m_attached_id))) { + attached_absolute_pos_rot_matrix = &attached->getAbsolutePosRotMatrix(); } else { unloaded = true; } @@ -382,7 +386,7 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) // Pretend to, but don't actually spawn a particle if it is // attached to an unloaded object or distant from player. if (!unloaded) - spawnParticle(env, radius, is_attached, attached_pos, attached_yaw); + spawnParticle(env, radius, attached_absolute_pos_rot_matrix); i = m_spawntimes.erase(i); } else { @@ -398,7 +402,7 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) for (int i = 0; i <= m_amount; i++) { if (rand() / (float)RAND_MAX < dtime) - spawnParticle(env, radius, is_attached, attached_pos, attached_yaw); + spawnParticle(env, radius, attached_absolute_pos_rot_matrix); } } } @@ -419,7 +423,7 @@ void ParticleManager::step(float dtime) stepSpawners (dtime); } -void ParticleManager::stepSpawners (float dtime) +void ParticleManager::stepSpawners(float dtime) { MutexAutoLock lock(m_spawner_list_lock); for (auto i = m_particle_spawners.begin(); i != m_particle_spawners.end();) { @@ -433,7 +437,7 @@ void ParticleManager::stepSpawners (float dtime) } } -void ParticleManager::stepParticles (float dtime) +void ParticleManager::stepParticles(float dtime) { MutexAutoLock lock(m_particle_list_lock); for (auto i = m_particles.begin(); i != m_particles.end();) { @@ -448,7 +452,7 @@ void ParticleManager::stepParticles (float dtime) } } -void ParticleManager::clearAll () +void ParticleManager::clearAll() { MutexAutoLock lock(m_spawner_list_lock); MutexAutoLock lock2(m_particle_list_lock); @@ -457,9 +461,7 @@ void ParticleManager::clearAll () m_particle_spawners.erase(i++); } - for(std::vector::iterator i = - m_particles.begin(); - i != m_particles.end();) + for(auto i = m_particles.begin(); i != m_particles.end();) { (*i)->remove(); delete *i; diff --git a/src/client/particles.h b/src/client/particles.h index 353743372..e7b8cbe24 100644 --- a/src/client/particles.h +++ b/src/client/particles.h @@ -144,8 +144,7 @@ public: private: void spawnParticle(ClientEnvironment *env, float radius, - bool is_attached, const v3f &attached_pos, - float attached_yaw); + const core::matrix4 *attached_absolute_pos_rot_matrix); ParticleManager *m_particlemanager; float m_time;