From 681d127ff1d288f4c3123a05f71ef15a6c549b5d Mon Sep 17 00:00:00 2001 From: orwell96 Date: Mon, 24 Oct 2016 19:56:27 +0200 Subject: [PATCH] Particles: Make attached particle spawners respect the parent's yaw Position, velocity and acceleration vectors of particles are rotated by the yaw of the parent object so that they are truly relative to it. Clarify new attached particle spawner behavior in lua_api.txt. --- doc/lua_api.txt | 3 ++- src/clientobject.h | 1 + src/content_cao.cpp | 3 ++- src/content_cao.h | 4 ++++ src/particles.cpp | 36 ++++++++++++++++++++++++++++-------- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 84080502f..80e66020d 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4152,7 +4152,8 @@ The Biome API is still in an experimental phase and subject to change. -- ^ collision_removal: if true then particle is removed when it collides, -- ^ requires collisiondetection = true to have any effect attached = ObjectRef, - -- ^ attached: if defined, makes particle positions relative to this object. + -- ^ attached: if defined, particle positions, velocities and accelerations + -- ^ are relative to this object's position and yaw. vertical = false, -- ^ vertical: if true faces player using y axis only texture = "image.png", diff --git a/src/clientobject.h b/src/clientobject.h index c4e1a634b..83931e438 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -61,6 +61,7 @@ public: virtual bool getCollisionBox(aabb3f *toset){return false;} virtual bool collideWithObjects(){return false;} virtual v3f getPosition(){return v3f(0,0,0);} + virtual float getYaw() const {return 0;} virtual scene::ISceneNode *getSceneNode(){return NULL;} virtual scene::IMeshSceneNode *getMeshSceneNode(){return NULL;} virtual scene::IAnimatedMeshSceneNode *getAnimatedMeshSceneNode(){return NULL;} diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 88ed43a8c..6b35d5881 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -313,7 +313,8 @@ public: {return &m_selection_box;} v3f getPosition() {return m_position;} - + inline float getYaw() const + {return 0;} std::string infoText() {return m_infotext;} diff --git a/src/content_cao.h b/src/content_cao.h index 5b3471814..a158e8296 100644 --- a/src/content_cao.h +++ b/src/content_cao.h @@ -136,6 +136,10 @@ public: aabb3f *getSelectionBox(); v3f getPosition(); + inline float getYaw() const + { + return m_yaw; + } scene::ISceneNode *getSceneNode(); diff --git a/src/particles.cpp b/src/particles.cpp index f20fb4083..acf9cc815 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -253,12 +253,17 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) m_time += dtime; bool unloaded = false; - v3f attached_offset = v3f(0,0,0); + 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_offset = attached->getPosition() / BS; - else + if (ClientActiveObject *attached = env->getActiveObject(m_attached_id)) { + attached_pos = attached->getPosition() / BS; + attached_yaw = attached->getYaw(); + is_attached = true; + } else { unloaded = true; + } } if (m_spawntime != 0) // Spawner exists for a predefined timespan @@ -277,8 +282,15 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) v3f pos = random_v3f(m_minpos, m_maxpos); v3f vel = random_v3f(m_minvel, m_maxvel); v3f acc = random_v3f(m_minacc, m_maxacc); - // Make relative to offest - pos += attached_offset; + + if (is_attached) { + // Apply attachment yaw and position + pos.rotateXZBy(attached_yaw); + pos += attached_pos; + vel.rotateXZBy(attached_yaw); + acc.rotateXZBy(attached_yaw); + } + float exptime = rand()/(float)RAND_MAX *(m_maxexptime-m_minexptime) +m_minexptime; @@ -321,10 +333,18 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) { if (rand()/(float)RAND_MAX < dtime) { - v3f pos = random_v3f(m_minpos, m_maxpos) - + attached_offset; + v3f pos = random_v3f(m_minpos, m_maxpos); v3f vel = random_v3f(m_minvel, m_maxvel); v3f acc = random_v3f(m_minacc, m_maxacc); + + if (is_attached) { + // Apply attachment yaw and position + pos.rotateXZBy(attached_yaw); + pos += attached_pos; + vel.rotateXZBy(attached_yaw); + acc.rotateXZBy(attached_yaw); + } + float exptime = rand()/(float)RAND_MAX *(m_maxexptime-m_minexptime) +m_minexptime;