示例#1
0
        public override void Update(ParticleEffect fx, ParticleEffectInstance instance, TimeSpan delta, ref Matrix4 transform, float sparam)
        {
            if (!fx.Pairs.ContainsKey(this))
            {
                return;
            }
            var maxCount = MaxParticles == null ? int.MaxValue : (int)Math.Ceiling(MaxParticles.GetValue(sparam, 0f));
            var freq     = Frequency == null ? 0f : Frequency.GetValue(sparam, 0f);
            var spawnMs  = freq <= 0 ? 0 : 1 / (double)freq;
            var state    = instance.GetEmitterState(this);

            if (state.ParticleCount >= maxCount)
            {
                return;
            }
            if (spawnMs > 0)
            {
                //Spawn lots of particles
                var dt = Math.Min(delta.TotalSeconds, 1);                 //don't go crazy during debug pauses
                while (true)
                {
                    if (state.SpawnTimer < dt)
                    {
                        dt -= state.SpawnTimer;
                        state.SpawnTimer = spawnMs;
                    }
                    else
                    {
                        state.SpawnTimer -= dt;
                        break;
                    }
                    if (state.ParticleCount + 1 <= maxCount)
                    {
                        var idx = instance.GetNextFreeParticle();
                        if (idx == -1)
                        {
                            return;
                        }
                        state.ParticleCount++;
                        SpawnParticle(idx, fx, instance, ref transform, sparam);
                        instance.Particles[idx].Appearance.OnParticleSpawned(idx, instance);
                    }
                }
            }
        }
        public ParticleEffectInstance(ParticleEffect fx)
        {
            Effect = fx;
            int emitterCount = 0;

            foreach (var node in fx.References)
            {
                if (node.Node is FLBeamAppearance)
                {
                    BeamAppearances.Add(node, new LineBuffer(512));
                }
                if (node.Node is FxEmitter)
                {
                    emitterCount++;
                }
            }
            Particles = new Particle[PARTICLES_PER_EMITTER * emitterCount];
        }
示例#3
0
        protected override void SetParticle(int idx, ParticleEffect fx, ParticleEffectInstance instance, ref Matrix4 transform, float sparam)
        {
            var r_min = MinRadius.GetValue(sparam, 0);
            var r_max = MaxRadius.GetValue(sparam, 0);

            var   radius = instance.Random.NextFloat(r_min, r_max);
            float s_min  = MathHelper.DegreesToRadians(MinSpread.GetValue(sparam, 0));
            float s_max  = MathHelper.DegreesToRadians(MaxSpread.GetValue(sparam, 0));

            var direction = RandomInCone(instance.Random, s_min, s_max);
            var tr        = Transform.GetMatrix(sparam, 0);
            var n         = (tr * new Vector4(direction.Normalized(), 0)).Xyz.Normalized();
            var p         = n * radius;

            n *= Pressure.GetValue(sparam, 0);
            instance.Particles[idx].Position = p;
            instance.Particles[idx].Normal   = n;
        }
示例#4
0
 public ParticleLibrary(ResourceManager res, AleFile ale)
 {
     Resources = res;
     foreach (var effect in ale.FxLib.Effects)
     {
         var fx = new ParticleEffect(this);
         fx.CRC  = effect.CRC;
         fx.Name = effect.Name;
         Dictionary <uint, NodeReference> nodesByIndex = new Dictionary <uint, NodeReference>();
         foreach (var noderef in effect.Fx)
         {
             FxNode node = null;
             if (!noderef.IsAttachmentNode)
             {
                 node = NodeFromAle(ale.NodeLib.Nodes.Where((arg) => arg.CRC == noderef.CRC).First());
             }
             var reference = new NodeReference();
             reference.Node             = node;
             reference.IsAttachmentNode = noderef.IsAttachmentNode;
             nodesByIndex.Add(noderef.Index, reference);
         }
         foreach (var noderef in effect.Fx)
         {
             var nd = nodesByIndex[noderef.Index];
             if (noderef.Parent != 32768)
             {
                 var parent = nodesByIndex[noderef.Parent];
                 parent.Children.Add(nd);
                 nd.Parent = parent;
             }
         }
         foreach (var pair in effect.Pairs)
         {
             var n1 = nodesByIndex[pair.Item1];
             var n2 = nodesByIndex[pair.Item2];
             n1.Paired.Add(n2);
         }
         fx.References = new List <NodeReference>(nodesByIndex.Values);
         Effects.Add(fx);
     }
 }
示例#5
0
        public Matrix4 GetTranslation(ParticleEffect effect, Matrix4 attachment, float sparam, float time)
        {
            Matrix4 mat = Matrix4.Identity;

            if (Transform != null)
            {
                mat = Transform.GetMatrix(sparam, time);
            }
            if (effect.AttachmentNodes.Contains(this))
            {
                return(mat * attachment);
            }
            else if (effect.Parents[this] is FxRootNode)
            {
                return(mat);
            }
            else
            {
                return(mat * effect.Parents [this].GetTranslation(effect, attachment, sparam, time));
            }
        }
示例#6
0
        public override void Draw(ref Particle particle, float globaltime, ParticleEffect effect, ResourceManager res, Billboards billboards, ref Matrix4 transform, float sparam)
        {
            var time    = particle.TimeAlive / particle.LifeSpan;
            var node_tr = GetTranslation(effect, transform, sparam, time);

            var       p = node_tr.Transform(particle.Position);
            Texture2D tex;
            Vector2   tl, tr, bl, br;

            HandleTexture(res, globaltime, sparam, ref particle, out tex, out tl, out tr, out bl, out br);
            var c = Color.GetValue(sparam, time);
            var a = Alpha.GetValue(sparam, time);

            var p2 = node_tr.Transform(particle.Position + particle.Normal);
            var n  = (p - p2).Normalized();

            billboards.DrawPerspective(
                tex,
                p,
                new Vector2(Size.GetValue(sparam, time)),
                new Color4(c, a),
                tl,
                tr,
                bl,
                br,
                n,
                Rotate == null ? 0f : Rotate.GetValue(sparam, time),
                SortLayers.OBJECT,
                BlendInfo
                );

            if (DrawNormals)
            {
                Debug.DrawLine(p - (n * 8), p + (n * 8));
            }
        }
示例#7
0
 public virtual void Update(ParticleEffect fx, ParticleEffectInstance instance, TimeSpan delta, ref Matrix4 transform, float sparam)
 {
 }
示例#8
0
        public unsafe void DrawBeamApp(PolylineRender poly, LineBuffer points, float globalTime, ParticleEffect effect, ParticleEffectInstance instance, ResourceManager res, Billboards billboards, ref Matrix4 transform, float sparam)
        {
            //TODO: Cross-plane not showing
            //TODO: In some cases particles are going backwards? (Broken emitter or LineBuffer)
            //TODO: See if z sorting can be better for Polyline
            //TODO: Implement FLBeamAppearance properties
            if (points.Count < 2)
            {
                return;
            }
            int lastIndex = 0;

            while (points[lastIndex].Active == false)
            {
                lastIndex++;
                if (lastIndex >= points.Count)
                {
                    return;
                }
            }
            //Get only active indices, alloc on stack for 0 GC pressure
            int *indices = stackalloc int[256];
            int  ptCount = 0;

            for (int i = lastIndex; i < points.Count; i++)
            {
                if (points[i].Active)
                {
                    indices[ptCount++] = points[i].ParticleIndex;
                }
            }

            var       node_tr = GetTranslation(effect, transform, sparam, 0);
            Texture2D tex;
            Vector2   tl, tr, bl, br;

            HandleTexture(res, globalTime, sparam, ref instance.Particles[points[lastIndex].ParticleIndex], out tex, out tl, out tr, out bl, out br);
            //Sorting hack kinda
            var z = RenderHelpers.GetZ(billboards.Camera.Position, node_tr.Transform(Vector3.Zero));

            for (int j = 0; j < 2; j++)             //two planes
            {
                poly.StartLine(tex, BlendInfo);
                bool    odd = true;
                Vector3 dir = Vector3.Zero;

                for (int i = 0; i < ptCount; i++)
                {
                    var pos = node_tr.Transform(instance.Particles[indices[i]].Position);
                    if (i + 1 < ptCount)
                    {
                        var pos2     = node_tr.Transform(instance.Particles[indices[i + 1]].Position);
                        var forward  = (pos2 - pos).Normalized();
                        var toCamera = (billboards.Camera.Position - pos).Normalized();
                        var up       = Vector3.Cross(toCamera, forward);
                        up.Normalize();
                        dir = up;
                        if (j == 1)
                        {
                            //Broken? Doesn't show up
                            var right = Vector3.Cross(forward, up).Normalized();
                            dir = right;
                        }
                    }
                    var time = instance.Particles[indices[i]].TimeAlive / instance.Particles[indices[i]].LifeSpan;
                    var w    = Width.GetValue(sparam, time);
                    poly.AddPoint(
                        pos + (dir * w / 2),
                        pos - (dir * w / 2),
                        odd ? tl : bl,
                        odd ? tr : br,
                        new Color4(
                            Color.GetValue(sparam, time),
                            Alpha.GetValue(sparam, time)
                            )
                        );
                    odd = !odd;
                }
                poly.FinishLine(z);
            }
        }
示例#9
0
 public override void Draw(ref Particle particle, float globaltime, ParticleEffect effect, ResourceManager res, Billboards billboards, ref Matrix4 transform, float sparam)
 {
     //Empty on purpose. Individual particles don't draw
 }
示例#10
0
 public ParticleLibrary(ResourceManager res, AleFile ale)
 {
     Resources = res;
     foreach (var effect in ale.FxLib.Effects)
     {
         var fx   = new ParticleEffect(this);
         var root = new FxRootNode();
         fx.CRC  = effect.CRC;
         fx.Name = effect.Name;
         List <FxNode>             nodes        = new List <FxNode>();
         Dictionary <uint, FxNode> nodesByIndex = new Dictionary <uint, FxNode>();
         foreach (var noderef in effect.Fx)
         {
             FxNode node;
             if (noderef.IsAttachmentNode)
             {
                 node = new FxNode("Attachment_0x" + noderef.CRC.ToString("X"), "Empty")
                 {
                     CRC = noderef.CRC
                 };
             }
             else
             {
                 node = NodeFromAle(ale.NodeLib.Nodes.Where((arg) => arg.CRC == noderef.CRC).First());
             }
             nodes.Add(node);
             nodesByIndex.Add(noderef.Index, node);
         }
         foreach (var noderef in effect.Fx)
         {
             var nd = nodesByIndex[noderef.Index];
             //var nd = FindNode(noderef.CRC);
             if (noderef.Parent != 32768)
             {
                 fx.Parents.Add(nd, nodesByIndex[noderef.Parent]);
             }
             else
             {
                 fx.Parents.Add(nd, root);
             }
             if (noderef.IsAttachmentNode)
             {
                 fx.AttachmentNodes.Add(nd);
             }
         }
         foreach (var pair in effect.Pairs)
         {
             var n1 = nodesByIndex[pair.Item1];
             var n2 = nodesByIndex[pair.Item2];
             List <Fx.FxNode> pairedTo;
             if (!fx.Pairs.TryGetValue(n1, out pairedTo))
             {
                 pairedTo = new List <FxNode>();
                 fx.Pairs.Add(n1, pairedTo);
             }
             pairedTo.Add(n2);
         }
         fx.SetNodes(nodes);
         Effects.Add(fx);
     }
 }
示例#11
0
 public virtual void Draw(ref Particle particle, float globaltime, ParticleEffect effect, ResourceManager res, Billboards billboards, ref Matrix4 transform, float sparam)
 {
 }
 public ParticleLibrary(ResourceManager res, AleFile ale)
 {
     Resources = res;
     foreach (var effect in ale.FxLib.Effects)
     {
         var fx = new ParticleEffect(this);
         fx.CRC  = effect.CRC;
         fx.Name = effect.Name;
         Dictionary <uint, NodeReference> nodesByIndex = new Dictionary <uint, NodeReference>();
         foreach (var noderef in effect.Fx)
         {
             FxNode node = null;
             if (!noderef.IsAttachmentNode)
             {
                 var nd = ale.NodeLib.Nodes.FirstOrDefault((arg) => arg.CRC == noderef.CRC);
                 if (nd == null)
                 {
                     node = new FxNode("error node", "error node");
                     FLLog.Error("Fx", fx.Name + " bad node CRC 0x" + noderef.CRC.ToString("x"));
                 }
                 else
                 {
                     node = NodeFromAle(ale.NodeLib.Nodes.Where((arg) => arg.CRC == noderef.CRC).First());
                 }
             }
             var reference = new NodeReference();
             reference.Node             = node;
             reference.IsAttachmentNode = noderef.IsAttachmentNode;
             nodesByIndex.Add(noderef.Index, reference);
         }
         foreach (var noderef in effect.Fx)
         {
             var nd = nodesByIndex[noderef.Index];
             if (noderef.Parent != 32768)
             {
                 var parent = nodesByIndex[noderef.Parent];
                 parent.Children.Add(nd);
                 nd.Parent = parent;
             }
         }
         foreach (var pair in effect.Pairs)
         {
             var n1 = nodesByIndex[pair.Item1];
             var n2 = nodesByIndex[pair.Item2];
             n1.Paired.Add(n2);
         }
         int emitterIndex = 0;
         int beamIndex    = 0;
         fx.References = new List <NodeReference>(nodesByIndex.Values);
         for (int i = 0; i < fx.References.Count; i++)
         {
             fx.References[i].Index        = i;
             fx.References[i].EmitterIndex = emitterIndex;
             fx.References[i].BeamIndex    = beamIndex;
             if (fx.References[i].Node is FxEmitter)
             {
                 emitterIndex++;
             }
             if (fx.References[i].Node is FLBeamAppearance)
             {
                 beamIndex++;
             }
         }
         fx.EmitterCount = emitterIndex;
         fx.BeamCount    = beamIndex;
         Effects.Add(fx);
     }
 }
示例#13
0
        public override void Draw(ref Particle particle, float globaltime, ParticleEffect effect, ResourceManager res, Billboards billboards, ref Matrix4 transform, float sparam)
        {
            var time    = particle.TimeAlive / particle.LifeSpan;
            var node_tr = GetTranslation(effect, transform, sparam, time);
            var src_pos = particle.Position;
            var l       = Length.GetValue(sparam, time);
            var w       = Width.GetValue(sparam, time);
            var sc      = Scale.GetValue(sparam, time);

            if (!CenterOnPos)
            {
                var nd = particle.Normal.Normalized();
                src_pos += nd * (l * sc * 0.25f);
            }
            var       p = node_tr.Transform(src_pos);
            Texture2D tex;
            Vector2   tl, tr, bl, br;

            HandleTexture(res, globaltime, sparam, ref particle, out tex, out tl, out tr, out bl, out br);
            var c  = Color.GetValue(sparam, time);
            var a  = Alpha.GetValue(sparam, time);
            var p2 = node_tr.Transform(src_pos + (particle.Normal * 20));
            var n  = (p2 - p).Normalized();

            billboards.DrawRectAppearance(
                tex,
                p,
                new Vector2(l, w) * sc * 0.5f,
                new Color4(c, a),
                tl,
                tr,
                bl,
                br,
                n,
                Rotate == null ? 0f : Rotate.GetValue(sparam, time),
                SortLayers.OBJECT,
                BlendInfo
                );

            /*var p1_proj = Project(billboards, p);
             * var p2_proj = Project(billboards, p2);
             *
             * var px1 = new Vector2(
             *      (p1_proj.X + 1) / 2 * 1024,
             *      (1 - p1_proj.Y) / 2 * 768);
             * var px2 = new Vector2(
             *      (p2_proj.X + 1) / 2 * 1024,
             *      (1 - p2_proj.Y) / 2 * 1024
             * );
             *
             * var angle = (float)Math.Atan2(px2.Y - px1.Y, px2.X - px1.X);*/

            /*var src_pos2 = src_pos + (particle.Normal * 20);
             * var angle = (float)Math.Atan2(src_pos2.Y - src_pos.Y, src_pos2.Z - src_pos.Z);
             * var angle_deg = MathHelper.RadiansToDegrees(angle);
             * billboards.Draw(
             *      tex,
             *      p,
             *      new Vector2(l, w) * sc * 0.5f,
             *      new Color4(c, a),
             *      tl,
             *      tr,
             *      bl,
             *      br,
             *      angle, //Rotate == null ? 0f : Rotate.GetValue(sparam, time),
             *      SortLayers.OBJECT,
             *      BlendInfo
             * );*/
            if (DrawNormals)
            {
                Debug.DrawLine(p - (n * 8), p + (n * 8));
            }
        }
示例#14
0
 protected virtual void SetParticle(int idx, ParticleEffect fx, ParticleEffectInstance instance, ref Matrix4 transform, float sparam)
 {
 }