RenderParticles' Direction can sometimes get a bit off

Found a bug? Post information about it here so we can fix it!

Moderator: Moderators

Post Reply
User avatar
rrTea
Posts: 323
Joined: Sat Feb 15, 2014 9:54 am

RenderParticles' Direction can sometimes get a bit off

Post by rrTea » Wed Mar 30, 2016 12:30 am

In the following example, try to spawn a few models by clicking around the screen with left mouse button. Note how the particles are sprayed in the direction opposite of the red "head", and that they rotate following the model's rotation. After confirming this, trigger the launch by pressing the right mouse button... The direction of moving and the particles' direction will fall out of sync.

It's possible that it won't be very noticeable on the first try so maybe you'll need to try a few times, but in most cases it's pretty obvious (I'm attaching a gif where I marked two random examples), as if the particles' Direction continues to rotate a few frames after the model is "launched".

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="Prg" Caption="Particles test" ClearColor="0.502 0.502 1 1" Camera="cam_Front" FileVersion="2">
  <OnLoaded>
    <ZLibrary Comment="RndPol() Random polarity: 1 or -1">
      <Source>
<![CDATA[float RndPol()
{
float YinYang;
YinYang = (0-0.5)+rnd();
YinYang = YinYang/abs(YinYang);
return YinYang;
}]]>
      </Source>
    </ZLibrary>
    <Group Comment="Values">
      <Children>
        <Variable Name="ScreenRatio"/>
        <Variable Name="ScreenEdgeTop"/>
        <Variable Name="ScreenEdgeRight"/>
        <ZExpression Comment="Calculate">
          <Expression>
<![CDATA[ScreenRatio = (1f*Prg.ViewportWidth/Prg.ViewportHeight);

ScreenEdgeTop   = cam_Front.OrthoZoom*1f;
ScreenEdgeRight = cam_Front.OrthoZoom*ScreenRatio;]]>
          </Expression>
        </ZExpression>
        <Variable Name="PI2"/>
        <ZExpression Expression="PI2=PI*2;"/>
      </Children>
    </Group>
    <Camera Name="cam_Front" Kind="1" Position="0 0 10" OrthoZoom="12"/>
  </OnLoaded>
  <OnUpdate>
    <KeyPress Comment="Rockets spawn" Keys="{" RepeatDelay="0.2">
      <OnPressed>
        <ZExpression>
          <Expression>
<![CDATA[float RndX = rnd()*rndPol()*ScreenEdgeRight;
float RndY = rnd()*rndPol()*ScreenEdgeTop;

mod_RocketThick.Position = vector3(RndX,RndY,0);]]>
          </Expression>
        </ZExpression>
        <SpawnModel Model="mod_RocketThick"/>
      </OnPressed>
    </KeyPress>
    <KeyPress Comment="Rockets erase" Keys=" ">
      <OnPressed>
        <RemoveAllModels/>
      </OnPressed>
    </KeyPress>
  </OnUpdate>
  <Content>
    <Mesh Name="mesh_Rocket">
      <Producers>
        <MeshBox Scale="0.5 0.5 0.5"/>
        <MeshTransform Position="0 -0.5 -0.3" Rotation="0.1 0.1 0.065"/>
        <MeshExpression AutoNormals="0" VertexColors="255">
          <Expression>
<![CDATA[//V : current vertex
//N : current normal (turn off AutoNormals when modifying normals)
//C : current color (turn on VertexColors)
//TexCoord : current texture coordinate (turn on HasTexCoords)

C = vector4(1,0,0,1);]]>
          </Expression>
        </MeshExpression>
        <MeshBox Comment="Body" Scale="0.5 1 0.5" Grid2DOnly="255"/>
        <MeshExpression AutoNormals="0" VertexColors="255">
          <Expression>
<![CDATA[//V : current vertex
//N : current normal (turn off AutoNormals when modifying normals)
//C : current color (turn on VertexColors)
//TexCoord : current texture coordinate (turn on HasTexCoords)

C = vector4(1,1,1,1);
//colorWhiteOpaque;]]>
          </Expression>
        </MeshExpression>
        <MeshCombine/>
      </Producers>
    </Mesh>
    <Model Name="mod_RocketThick" Position="-1.9038 -7.2268 0" RotationVelocity="0 0 0.1" CollisionBounds="1 1 0 0">
      <States>
        <ModelState Name="mState_Preying">
          <OnUpdate>
            <KeyPress Keys="}">
              <OnPressed>
                <SetModelState State="mState_Flying"/>
              </OnPressed>
            </KeyPress>
          </OnUpdate>
        </ModelState>
        <ModelState Name="mState_Flying">
          <OnStart>
            <ZExpression Comment="Prepare rocket">
              <Expression>
<![CDATA[CurrentModel.RotationVelocity.Z = 0;

CurrentModel.Velocity.X = 0+sin(CurrentModel.Rotation.Z*PI2)*2f;
CurrentModel.Velocity.Y = 0-cos(CurrentModel.Rotation.Z*PI2)*2f;]]>
              </Expression>
            </ZExpression>
          </OnStart>
        </ModelState>
      </States>
      <OnSpawn>
        <SetModelState State="mState_Preying"/>
      </OnSpawn>
      <OnUpdate>
        <Condition Comment="Out of screen?">
          <Expression>
<![CDATA[return (
abs(CurrentModel.Position.X) > CurrentModel.Scale.X*4 + ScreenEdgeRight ||
abs(CurrentModel.Position.Y) > CurrentModel.Scale.X*4 + ScreenEdgeTop
);]]>
          </Expression>
          <OnTrue>
            <RemoveModel/>
          </OnTrue>
        </Condition>
      </OnUpdate>
      <OnRender>
        <UseMaterial Material="mat_ColorMondrian"/>
        <RenderMesh Mesh="mesh_Rocket"/>
        <UseMaterial Material="mat_Dotted"/>
        <RenderParticles ParticlesPerSecond="10" Spread="0.2" ParticleWidth="2" ParticleHeight="2" Speed="3" SpeedRange="0.2" ParticleLifetime="1" AnimateSize="-2" FollowModel="0">
          <OnEmitExpression>
<![CDATA[//Emit particle.
//PColor : particle color, PAngle : particle angle

PColor = vector3(0.5,0.25,0);

//PAngle = CurrentModel.Rotation.Z;]]>
          </OnEmitExpression>
        </RenderParticles>
      </OnRender>
    </Model>
    <Bitmap Name="bmp_Dot" Filter="1">
      <Producers>
        <BitmapExpression UseBlankSource="255">
          <Expression>
<![CDATA[// Local variables

float X1, Y1, B, S;

// Distance from center ( per axis )

X1 = 0.5-x;
Y1 = 0.5-y;

B = 64/2f    ; // 64 = BitMapsize | 2 = Anti-Aliasing bias ( in pixels )

pixel.A = B*0.5-sqrt(X1*X1+Y1*Y1)*B;

// Set RGB to white

pixel.R = 1;
pixel.G = 1;
pixel.B = 1;]]>
          </Expression>
        </BitmapExpression>
      </Producers>
    </Bitmap>
    <Material Name="mat_ColorMondrian" Shading="1" Light="0"/>
    <Material Name="mat_Dotted" Light="0" Blend="2">
      <Textures>
        <MaterialTexture Texture="bmp_Dot" TextureWrapMode="2" TexCoords="1"/>
      </Textures>
    </Material>
  </Content>
</ZApplication>
Edit: Removed the gif as it was distracting
Last edited by rrTea on Thu Mar 31, 2016 12:06 am, edited 1 time in total.

User avatar
VilleK
Site Admin
Posts: 1924
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: RenderParticles' Direction can sometimes get a bit off

Post by VilleK » Wed Mar 30, 2016 11:00 am

I can see it happening but I don't have an immediate idea of why. Kjell, do you have time to check it out?

User avatar
Kjell
Posts: 1650
Joined: Sat Feb 23, 2008 11:15 pm

Re: RenderParticles' Direction can sometimes get a bit off

Post by Kjell » Wed Mar 30, 2016 7:17 pm

Hmm,
VilleK wrote:I can see it happening but I don't have an immediate idea of why. Kjell, do you have time to check it out?
At the very least there's something strange going on when rotating a model that contains a RenderParticles component ( with FollowModel turned off ).

Image

As you can see in the GIF, when re-positioning the model all particles continue independently from the model ( as you'd expect ), but when you rotate the model their position gets affected by the rotation.

K

User avatar
rrTea
Posts: 323
Joined: Sat Feb 15, 2014 9:54 am

Re: RenderParticles' Direction can sometimes get a bit off

Post by rrTea » Sat Jul 30, 2016 11:25 am

I would expect that unticking "FollowModel" would mean that, once it is launched, the particle goes off independently of the model - in other words, a model's position matters only for starting coordinates of a particle. So in Kjell's example I'd expect particles to not rotate when the model's Rotation.Z / RotationVelocity.Z are changed.

Related to this - is it by design that RenderParticles' Direction has to be multiplied by 2PI to direct it in a specific angle, unlike any other angles like rotations of models etc? This always confuses me, I usually write

Code: Select all

particles_Rocket.Direction = 0.5+CurrentModel.Rotation.Z;
and then (after discovering it doesn't work) have to fix it to

Code: Select all

particles_Rocket.Direction = (0.5+CurrentModel.Rotation.Z)*Pi2;

User avatar
Rado1
Posts: 770
Joined: Wed May 05, 2010 12:16 pm

Re: RenderParticles' Direction can sometimes get a bit off

Post by Rado1 » Sun Aug 07, 2016 2:53 pm

I completely agree with rrTea: unchecking the FollowModel property should cause independent moving of particles on model transformation after its spawning and Direction and Spread properties should be expressed in interval <0,1> as rotations of models. BTW also RenderText.CharRotate uses radians, it should be unified with other rotations as well.

Post Reply