Particles: Make attached particle spawners respect the parent's yaw
authororwell96 <mono96.mml@gmail.com>
Mon, 24 Oct 2016 17:56:27 +0000 (19:56 +0200)
committerparamat <mat.gregory@virginmedia.com>
Fri, 18 Nov 2016 06:18:54 +0000 (06:18 +0000)
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
src/clientobject.h
src/content_cao.cpp
src/content_cao.h
src/particles.cpp

index 84080502f0052e99a9e771923e4408c5ecb51206..80e66020dfaf7bf97f9bcd320cdb6391ff572a9e 100644 (file)
@@ -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",
index c4e1a634b056b68d7a5f44faafb77995fcc3b821..83931e438e63194a3981514d6f1d41897bd4bfb8 100644 (file)
@@ -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;}
index 88ed43a8c8a37697997f74af3f75a47dd85b7211..6b35d5881da39eddb77700c11b0c11549855a898 100644 (file)
@@ -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;}
 
index 5b34718140c7512915a90c7d8d3ee554aff96c7b..a158e8296761a61e957fb3051feff933c8422415 100644 (file)
@@ -136,6 +136,10 @@ public:
        aabb3f *getSelectionBox();
 
        v3f getPosition();
+       inline float getYaw() const
+       {
+               return m_yaw;
+       }
 
        scene::ISceneNode *getSceneNode();
 
index f20fb4083033631a48370ace89c6fc34a57be062..acf9cc8155b22dc2bf6f1e6238092f71b23a0226 100644 (file)
@@ -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;