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>