示例#1
0
        private RasterInkStroke CreateDryStrokeFromRasterBrush(DecodedRasterInkBuilder decodedRasterInkBuilder, RasterBrush rasterBrush, Stroke stroke)
        {
            var result = decodedRasterInkBuilder.AddWholePath(stroke.Spline.Data, rasterBrush.Spacing, stroke.Layout);

            List <float> points = new List <float>(result.Addition);

            uint channelMask = (uint)decodedRasterInkBuilder.SplineInterpolator.InterpolatedSplineLayout.ChannelMask;

            ParticleList particleList = new ParticleList();

            particleList.Assign(points, channelMask);

            ParticleBrush particleBrush = new ParticleBrush
            {
                FillTexture  = mGraphics.CreateTexture(Task.Run(async() => await Utils.GetPixelDataAsync(rasterBrush.FillTexture)).Result),
                FillTileSize = new Size(rasterBrush.FillWidth, rasterBrush.FillHeight),
                RotationMode = (ParticleRotationMode)rasterBrush.RotationMode,
                Scattering   = rasterBrush.Scattering,
                ShapeTexture = mGraphics.CreateTexture(Task.Run(async() => await Utils.GetPixelDataAsync(rasterBrush.ShapeTextures[0])).Result)
            };

            RasterInkStroke dryStroke = new RasterInkStroke(stroke, rasterBrush, particleList, particleBrush);

            return(dryStroke);
        }
        internal override void Update(GameTime gameTime)
        {
            float now = (float)gameTime.TotalGameTime.TotalMilliseconds;

            for (int i = ParticleList.Count - 1; i >= 0; i--)
            {
                Particle particle  = ParticleList[i];
                float    timeAlive = now - this.BirthTime;

                if (timeAlive > this.MaxAge)
                {
                    ParticleList.RemoveAt(i);
                }
                else
                {
                    float relAge = timeAlive / this.MaxAge;
                    particle.Position = 0.5f * particle.Accelaration * relAge * relAge + particle.Direction * relAge + this.Position; //particle.OrginalPosition;

                    float invAge = 1.0f - relAge;
                    particle.Color = new Color(new Vector4(invAge, invAge, invAge, invAge));

                    Vector2 positionFromCenter = particle.Position - this.Position; //particle.OrginalPosition;
                    float   distance           = positionFromCenter.Length();
                    particle.Scale = ((50.0f + distance) / 200.0f) * this.Size;

                    ParticleList[i] = particle;
                }
            }
        }
示例#3
0
    public InstantObject GetParticleEffect(ParticleList type)
    {
        Queue <InstantObject> container = null;
        GameObject            prefab    = null;

        switch (type)
        {
        case ParticleList.Explosion:
            container = _explosionEffect;
            prefab    = GameData.PrefabExplosion;
            break;

        case ParticleList.HitEffectA:
            container = _hitEffectA;
            prefab    = GameData.PrefabHitEffectA;
            break;
        }

        if (container.Count == 0)
        {
            AddToContainer(prefab, container);
        }
        InstantObject rv = container.Dequeue();

        rv.gameObject.SetActive(true);
        return(rv);
    }
示例#4
0
        protected override void StoreCurrentStroke(string pointerDeviceType)
        {
            var allData = mInkBuilder.SplineInterpolator.AllData;

            var points = new List <float>();

            if (allData != null)
            {
                for (int i = 0; i < allData.Count; i++)
                {
                    points.Add(allData[i]);
                }

                if (points.Count > 0)
                {
                    uint         channelMask = (uint)mInkBuilder.SplineInterpolator.InterpolatedSplineLayout.ChannelMask;
                    ParticleList path        = new ParticleList();
                    path.Assign(points, channelMask);
                    mDryStrokes.Add(new DryStroke(path, mStartRandomSeed, mStrokeConstants.Clone(), mInkBuilder.Brush));
                }
            }

            mRenderingContext.SetTarget(mAllStrokesLayer);
            mRenderingContext.DrawLayer(mCurrentStrokeLayer, null, Ink.Rendering.BlendMode.SourceOver);

            mRenderingContext.SetTarget(mCurrentStrokeLayer);
            mRenderingContext.ClearColor(Colors.Transparent);

            mDirtyRectManager.Reset();

            mSerializer.EncodeCurrentStroke(pointerDeviceType, mInkBuilder, mStrokeConstants, mStartRandomSeed);
        }
示例#5
0
        public void AddParticleP1(Particle.ParticleInfo info, ParticleList inList)
        {
            Particle useParticle = (ParticleSystemRoss.Instance()).GetNextFreeParticleP1(inList, "hmm");

            if (particle != null)
            {
                switch (info.type)
                {
                case ParticleType.kParticle_WaterSparkle:
                    useParticle.Launch_WaterSparkle(info);
                    break;

                case ParticleType.kParticle_WaterLine:
                    useParticle.Launch_WaterLine(info);
                    break;

                case ParticleType.kParticle_PondBlob:
                    useParticle.Launch_PondBlob(info);
                    break;

                default:
                    Globals.Assert(false);
                    break;
                }
            }
        }
示例#6
0
        public void UpdateList(ParticleList listType)
        {
            int listHead;

            listHead = usedListHead[(int)listType];
            int i = listHead;

            while (i != -1)
            {
                bool flagToRemove = false;
                if ((particle[i]).Update())
                {
                    flagToRemove = true;
                }

                int prevI = i;
                i = (particle[i]).next;
                if (flagToRemove)
                {
                    particle[prevI].myAtlasBillboard.StopRender();
                    this.RemoveFromListP1(listType, prevI);
                    this.AddToFreeList(prevI);
                }
            }
        }
        public RasterInkStroke(RasterInkBuilder inkBuilder,
                               PointerDeviceType pointerDeviceType,
                               List <float> points,
                               uint seed,
                               RasterBrush rasterBrush,
                               ParticleBrush particleBrush,
                               StrokeConstants StrokeParams,
                               Identifier sensorDataId)
        {
            Id = Identifier.FromNewGuid();

            PointerDeviceType = pointerDeviceType;

            uint channelMask = (uint)inkBuilder.SplineInterpolator.InterpolatedSplineLayout.ChannelMask;

            Path = new ParticleList();
            Path.Assign(points, channelMask);

            RandomSeed      = seed;
            StrokeConstants = StrokeParams;
            SensorDataId    = sensorDataId;
            RasterBrush     = rasterBrush;
            ParticleBrush   = particleBrush;

            // Cloning is needed, otherwise the spatial data is corrupted
            Spline = inkBuilder.SplineProducer.AllData.Clone();
            Layout = inkBuilder.Layout;
        }
示例#8
0
 public DryStroke(ParticleList path, uint seed, StrokeConstants StrokeParams, ParticleBrush particleBrush)
 {
     Path            = path;
     RandomSeed      = seed;
     StrokeConstants = StrokeParams;
     ParticleBrush   = particleBrush;
 }
        internal override void AddParticle(GameTime gameTime)
        {
            Particle particle = new Particle();

            //particle.OrginalPosition = Position;
            particle.Position = Position; // particle.OrginalPosition;
            //particle.Rotation = rotation;
            ////particle.BirthTime = (float)gameTime.TotalGameTime.TotalMilliseconds;
            ////particle.MaxAge = MaxAge;
            particle.Scale = 1f;
            particle.Color = Color.White;

            //float particleDistance = (float)Manager.Random.NextDouble() * this.Spread; //Size;
            //Vector2 displacement = new Vector2(particleDistance, 0);
            //float angle = MathHelper.ToRadians(Manager.Random.Next(360));
            //displacement = Vector2.Transform(displacement, Matrix.CreateRotationZ(angle));
            //particle.Direction = displacement * 2.0f;
            //particle.Accelaration = -particle.Direction;

            Vector2 direction = this.Position - this.aimAt.ToVector2();

            direction.Normalize();
            particle.Direction    = direction;
            particle.Accelaration = new Vector2(-3f, -3f);

            ParticleList.Add(particle);
        }
示例#10
0
    // Update is called once per frame
    void Update()
    {
        int NumToSpawn = rate;

        if (spawnerTime < 0.0f)
        {
            playing = false;
        }
        spawnerTime -= Time.deltaTime;

        while (currParticles < maxParticles && NumToSpawn > 0 && playing)
        {
            //spawn
            GameObject currPart = Instantiate(particle, this.GetComponent <Transform>());

            ParticleList currlist = currPart.GetComponent <ParticleList>();

            currlist.position = new Vector3(Random.Range(minRangePos.x, maxRangePos.x), Random.Range(minRangePos.y, maxRangePos.y), Random.Range(minRangePos.z, maxRangePos.z));

            //custom spawners:
            if (ringSpawner)
            {
                Vector3 offset = new Vector3(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f), 0.0f);
                offset.Normalize();
                currlist.position += offset * Random.Range(ringRadius, circleRadius);
            }

            currlist.velocity       = new Vector3(Random.Range(minInitialVel.x, maxInitialVel.x), Random.Range(minInitialVel.y, maxInitialVel.y), 0.0f) * Random.Range(rangeVel.x, rangeVel.y);
            currlist.size           = lerpSize.x;
            currlist.alpha          = lerpAlpha.x;
            currlist.age            = 0.0f;
            currlist.lifetime       = Random.Range(rangeLifetime.x, rangeLifetime.y);
            currlist.mass           = mass;
            currlist.gravity        = gravity;
            currlist.lerpAlpha      = lerpAlpha;
            currlist.LerpSize       = lerpSize;
            currlist.noiseStrength  = noiseStrength;
            currlist.noiseFrequency = noiseFrequency;
            currlist.useNoise       = noiseOn;

            currParticles++;
            NumToSpawn--;
        }


        if (play)
        {
            play        = false;
            playing     = true;
            spawnerTime = spawnTime;
        }

        if (parse)
        {
            parse = false;
            OnParse();
        }
    }
示例#11
0
        public override void _Ready()
        {
            var size = GetViewportRect().Size;
            var list = new ParticleList()
            {
                Position = new Vector2(size.x / 2, size.y / 4)
            };

            AddChild(list);
        }
示例#12
0
        public Particle GetNextFreeParticleP1(ParticleList inList, string debugName)
        {
            if (freeListHead == -1)
            {
                return(null);
            }

            int oldHead = freeListHead;

            this.RemoveFromFreeList(oldHead);
            this.AddToListP1(inList, oldHead);
            return(particle[oldHead]);
        }
示例#13
0
 /// <summary>
 /// Updates the Unity Particle System with the generated particle data.
 /// </summary>
 void UpdateShuriken()
 {
     if (Renderers == null)
     {
         return;
     }
     foreach (GameObject g in Renderers)
     {
         ParticleSystem system = g.GetComponent <ParticleSystem>();
         system?.SetParticles(ParticleList.Select(p => Particle.ConvertToParticleSystem(p, m_prefab.TextureSheetPow)).ToArray(), m_particleList.Length);
     }
     CalculateBounds();
 }
示例#14
0
        public void UpdateParticles(GameTime gameTime)
        {
            EmittedNewParticle = false;
            if (gameTime.ElapsedGameTime.TotalMilliseconds > 0)
            {
                if (Active)
                {
                    timeSinceLastEmission += gameTime.ElapsedGameTime.Milliseconds;

                    if (emitterFrequency == 0 || timeSinceLastEmission >= emitterFrequency)
                    {
                        emitterFrequency = emitterHelper.RandomizedDouble(RandomEmissionInterval);
                        if (emitterFrequency == 0)
                        {
                            throw new Exception("emitter frequency cannot be below 0.1d !!");
                        }
                        for (int i = 0; i < Math.Round(timeSinceLastEmission / emitterFrequency); i++)
                        {
                            EmitParticle();
                        }
                        timeSinceLastEmission = 0;
                    }
                }
                else
                {
                    emitterFrequency = 0;
                }

                foreach (Particle particle in ParticleList.ToArray())
                {
                    float y = -1 * ((float)Math.Cos(MathHelper.ToRadians(particle.Direction))) * particle.Speed;
                    float x = (float)Math.Sin(MathHelper.ToRadians(particle.Direction)) * particle.Speed;

                    particle.TotalLifetime += gameTime.ElapsedGameTime.Milliseconds;
                    particle.Position      += new Vector2(x, y);
                    particle.Rotation      += particle.RotationSpeed;
                    ParticleScaler.Scale(particle, ParticleLifeTime);
                    particle.Fade  = ParticleFader.Fade(particle, ParticleLifeTime);
                    particle.Color = new Color(particle.Fade, particle.Fade, particle.Fade, particle.Fade);

                    if (particle.TotalLifetime > ParticleLifeTime)
                    {
                        ParticleList.Remove(particle);
                    }
                }
            }
        }
示例#15
0
        private void EmitParticle()
        {
            if (i > TextureList.Count - 1)
            {
                i = 0;
            }

            Particle particle = new Particle(TextureList[i],
                                             Position,
                                             (float)emitterHelper.RandomizedDouble(ParticleSpeed),
                                             (float)emitterHelper.RandomizedDouble(ParticleDirection),
                                             MathHelper.ToRadians((float)emitterHelper.RandomizedDouble(ParticleRotation)),
                                             (float)emitterHelper.RandomizedDouble(RotationSpeed),
                                             Opacity);

            ParticleList.Add(particle);
            EmittedNewParticle  = true;
            LastEmittedParticle = particle;
            i++;
        }
示例#16
0
        public void RemoveFromListP1(ParticleList listType, int whichObject)
        {
            numActiveParticles--;
            int listHead = usedListHead[(int)listType];

            if (whichObject == listHead)
            {
                usedListHead[(int)listType] = (particle[whichObject]).next;
                return;
            }

            int item = listHead;

            while ((particle[item]).next != whichObject)
            {
                item = (particle[item]).next;
            }
            ;

            (particle[item]).SetNext((particle[whichObject]).next);
        }
        public RasterInkStroke(Stroke stroke, RasterBrush rasterBrush, ParticleList particleList, ParticleBrush particleBrush)
        {
            Id            = stroke.Id;
            Path          = particleList;
            RandomSeed    = stroke.Style.RandomSeed;
            RasterBrush   = rasterBrush;
            ParticleBrush = particleBrush;

            PathPointProperties ppp = stroke.Style.PathPointProperties;

            StrokeConstants = new StrokeConstants
            {
                Color = MediaColor.FromArgb(
                    ppp.Alpha.HasValue ? (byte)(ppp.Alpha * 255.0f) : byte.MinValue,
                    ppp.Red.HasValue ? (byte)(ppp.Red * 255.0f) : byte.MinValue,
                    ppp.Green.HasValue ? (byte)(ppp.Green * 255.0f) : byte.MinValue,
                    ppp.Blue.HasValue ? (byte)(ppp.Blue * 255.0f) : byte.MinValue)
            };
            SensorDataId = stroke.SensorDataId;

            Spline = stroke.Spline;
            Layout = stroke.Layout;
        }
示例#18
0
    // Play the type of particle on the container
    // if called with the same type that is being played. do nothing.
    // if currently played particle is different type, stop and play the new type.
    public GameObject Play(ParticleList type, Transform container)
    {
        GameObject particlePrefab = null;
        GameObject particle       = null;
        int        instanceId     = container.GetInstanceID();

        if (playingParticles.ContainsKey(container.GetInstanceID()))
        {
            ParticleWithType playingParticle = playingParticles[instanceId];
            if (playingParticle.type == type)
            {
                return(playingParticle.particle);
            }
            else
            {
                Stop(container);
            }
        }
        particlePrefab = particleDictionary[type];
        particle       = Instantiate(particlePrefab, container, false) as GameObject;
        playingParticles[instanceId] = new ParticleWithType(type, particle);
        return(particle);
    }
示例#19
0
        private DryStroke CreateDryStrokeFromRasterBrush(DecodedRasterInkBuilder decodedRasterInkBuilder, RasterBrush rasterBrush, Stroke stroke)
        {
            var result = decodedRasterInkBuilder.AddWholePath(stroke.Spline.Data, rasterBrush.Spacing, stroke.Layout);

            List <float> points = new List <float>(result.Addition);

            uint channelMask = (uint)decodedRasterInkBuilder.SplineInterpolator.InterpolatedSplineLayout.ChannelMask;

            ParticleList particleList = new ParticleList();

            particleList.Assign(points, channelMask);

            PathPointProperties ppp = stroke.Style.PathPointProperties;

            StrokeConstants strokeConstants = new StrokeConstants
            {
                Color = MediaColor.FromArgb(
                    ppp.Alpha.HasValue ? (byte)(ppp.Alpha * 255.0f) : byte.MinValue,
                    ppp.Red.HasValue ? (byte)(ppp.Red * 255.0f) : byte.MinValue,
                    ppp.Green.HasValue ? (byte)(ppp.Green * 255.0f) : byte.MinValue,
                    ppp.Blue.HasValue ? (byte)(ppp.Blue * 255.0f) : byte.MinValue)
            };

            ParticleBrush particleBrush = new ParticleBrush
            {
                FillTexture  = mGraphics.CreateTexture(Utils.GetPixelData(rasterBrush.FillTexture)),
                FillTileSize = new Size(rasterBrush.FillWidth, rasterBrush.FillHeight),
                RotationMode = (ParticleRotationMode)rasterBrush.RotationMode,
                Scattering   = rasterBrush.Scattering,
                ShapeTexture = mGraphics.CreateTexture(Utils.GetPixelData(rasterBrush.ShapeTextures[0]))
            };


            DryStroke dryStroke = new DryStroke(particleList, stroke.Style.RandomSeed, strokeConstants, particleBrush);

            return(dryStroke);
        }
示例#20
0
        /// <inheritdoc />
        public override unsafe void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sorter)
        {
            // If you want, you can integrate the base builder here and not call it. It should result in slight speed up
            base.PatchVertexBuffer(ref bufferState, invViewX, invViewY, ref sorter);

            var colorField = sorter.GetField(ParticleFields.Color);

            if (!colorField.IsValid())
            {
                return;
            }

            var colAttribute = bufferState.GetAccessor(VertexAttributes.Color);

            if (colAttribute.Size <= 0)
            {
                return;
            }

            foreach (var particle in sorter)
            {
                // Set the vertex color attribute to the particle's color field
                var color = (uint)(*(Color4 *)particle[colorField]).ToRgba();
                bufferState.SetAttributePerSegment(colAttribute, (IntPtr)(&color));

                bufferState.NextSegment();
            }

            bufferState.StartOver();
        }
 public override int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
 {
     return 0;
 }
示例#22
0
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
                                                     ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter, ref Matrix viewProj)
        {
            // Update the curve samplers if required
            base.BuildVertexBuffer(ref bufferState, invViewX, invViewY, ref spaceTranslation, ref spaceRotation, spaceScale, ref sorter, ref viewProj);

            // Get all required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);

            if (!positionField.IsValid())
            {
                return(0);
            }
            var lifeField   = sorter.GetField(ParticleFields.Life);
            var sizeField   = sorter.GetField(ParticleFields.Size);
            var rotField    = sorter.GetField(ParticleFields.Quaternion);
            var hasRotation = rotField.IsValid() || (SamplerRotation != null);


            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            var trsIdentity = (spaceScale == 1f);

            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));


            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            foreach (var particle in sorter)
            {
                var centralPos = GetParticlePosition(particle, positionField, lifeField);

                var particleSize = GetParticleSize(particle, sizeField, lifeField);

                var unitX = new Vector3(1, 0, 0);
                var unitY = new Vector3(0, 0, 1);

                if (hasRotation)
                {
                    var particleRotation = GetParticleRotation(particle, rotField, lifeField);
                    particleRotation.Rotate(ref unitX);
                    particleRotation.Rotate(ref unitY);
                }

                // The TRS matrix is not an identity, so we need to transform the quad
                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos    = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;

                    spaceRotation.Rotate(ref unitX);
                    spaceRotation.Rotate(ref unitY);
                }

                // Use half size to make a Size = 1 result in a Billboard of 1m x 1m
                unitX *= (particleSize * 0.5f);
                unitY *= (particleSize * 0.5f);

                var particlePos = centralPos - unitX + unitY;
                var uvCoord     = new Vector2(0, 0);
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X    = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            var vtxPerShape = 4 * QuadsPerParticle;

            return(renderedParticles * vtxPerShape);
        }
示例#23
0
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
                                                     ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter, ref Matrix viewProj)
        {
            // Step 1 - get all required fields to build the particle shapes. Some fields may not exist if no initializer or updater operates on them
            //  In that case we just decide on a default value for that field and skip the update

            var positionField = sorter.GetField(ParticleFields.Position);

            if (!positionField.IsValid())
            {
                return(0); // We can't display the particles without position. All other fields are optional
            }
            var sizeField  = sorter.GetField(ParticleFields.Size);
            var angleField = sorter.GetField(ParticleFields.Angle);
            var hasAngle   = angleField.IsValid();

            var rectField   = sorter.GetField(CustomParticleFields.RectangleXY);
            var isRectangle = rectField.IsValid();

            // In case of Local space particles they are simulated in local emitter space, but drawn in world space
            //  If the draw space is identity (i.e. simulation space = draw space) skip transforming the particle's location later
            var trsIdentity = (spaceScale == 1f);

            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(new Quaternion(0, 0, 0, 1)));

            // Custom feature - fix the Y axis to always point up in world space rather than screen space
            if (FixYAxis)
            {
                invViewY   = new Vector3(0, 1, 0);
                invViewX.Y = 0;
                invViewX.Normalize();
            }

            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            foreach (var particle in sorter)
            {
                var centralPos = particle.Get(positionField);

                var particleSize = sizeField.IsValid() ? particle.Get(sizeField) : 1f;

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos    = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;
                }

                var unitX = invViewX * particleSize;
                var unitY = invViewY * particleSize;
                if (isRectangle)
                {
                    var rectSize = particle.Get(rectField);

                    unitX *= rectSize.X;
                    unitY *= rectSize.Y;
                }

                // Particle rotation. Positive value means clockwise rotation.
                if (hasAngle)
                {
                    var rotationAngle = particle.Get(angleField);
                    var cosA          = (float)Math.Cos(rotationAngle);
                    var sinA          = (float)Math.Sin(rotationAngle);
                    var tempX         = unitX * cosA - unitY * sinA;
                    unitY = unitY * cosA + unitX * sinA;
                    unitX = tempX;
                }


                var particlePos = centralPos - unitX + unitY;
                var uvCoord     = new Vector2(0, 0);
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X    = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            // Return the number of updated vertices
            var vtxPerShape = 4 * QuadsPerParticle;

            return(renderedParticles * vtxPerShape);
        }
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
            ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
        {
            // Step 1 - get all required fields to build the particle shapes. Some fields may not exist if no initializer or updater operates on them
            //  In that case we just decide on a default value for that field and skip the update

            var positionField = sorter.GetField(ParticleFields.Position);
            if (!positionField.IsValid())
                return 0; // We can't display the particles without position. All other fields are optional

            var sizeField = sorter.GetField(ParticleFields.Size);
            var angleField = sorter.GetField(ParticleFields.Angle);
            var hasAngle = angleField.IsValid();

            var rectField = sorter.GetField(CustomParticleFields.RectangleXY);
            var isRectangle = rectField.IsValid();

            // In case of Local space particles they are simulated in local emitter space, but drawn in world space
            //  If the draw space is identity (i.e. simulation space = draw space) skip transforming the particle's location later
            var trsIdentity = (spaceScale == 1f);
            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(new Quaternion(0, 0, 0, 1)));

            // Custom feature - fix the Y axis to always point up in world space rather than screen space
            if (FixYAxis)
            {
                invViewY = new Vector3(0, 1, 0);
                invViewX.Y = 0;
                invViewX.Normalize();
            }

            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            foreach (var particle in sorter)
            {
                var centralPos = particle.Get(positionField);

                var particleSize = sizeField.IsValid() ? particle.Get(sizeField) : 1f;

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;
                }

                var unitX = invViewX * particleSize;
                var unitY = invViewY * particleSize;
                if (isRectangle)
                {
                    var rectSize = particle.Get(rectField);

                    unitX *= rectSize.X;
                    unitY *= rectSize.Y;
                }

                // Particle rotation. Positive value means clockwise rotation.
                if (hasAngle)
                {
                    var rotationAngle = particle.Get(angleField);
                    var cosA = (float)Math.Cos(rotationAngle);
                    var sinA = (float)Math.Sin(rotationAngle);
                    var tempX = unitX * cosA - unitY * sinA;
                    unitY = unitY * cosA + unitX * sinA;
                    unitX = tempX;
                }


                var particlePos = centralPos - unitX + unitY;
                var uvCoord = new Vector2(0, 0);
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            // Return the number of updated vertices
            var vtxPerShape = 4 * QuadsPerParticle;
            return renderedParticles * vtxPerShape;
        }
示例#25
0
        /// <inheritdoc />
        public unsafe override void BuildUVCoordinates(ref ParticleBufferState bufferState, ref ParticleList sorter, AttributeDescription texCoordsDescription)
        {
            var lifeField = sorter.GetField(ParticleFields.RemainingLife);

            if (!lifeField.IsValid())
            {
                return;
            }

            var texAttribute = bufferState.GetAccessor(texCoordsDescription);

            if (texAttribute.Size == 0 && texAttribute.Offset == 0)
            {
                return;
            }

            var texDefault = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            if (texDefault.Size == 0 && texDefault.Offset == 0)
            {
                return;
            }

            foreach (var particle in sorter)
            {
                var normalizedTimeline = 1f - *(float *)(particle[lifeField]);

                Vector4 uvTransform = Vector4.Lerp(StartFrame, EndFrame, normalizedTimeline);
                uvTransform.Z -= uvTransform.X;
                uvTransform.W -= uvTransform.Y;

                bufferState.TransformAttributePerSegment(texDefault, texAttribute, this, ref uvTransform);

                bufferState.NextSegment();
            }


            bufferState.StartOver();
        }
示例#26
0
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
                                                     ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter, ref Matrix viewProj)
        {
            // Update the curve samplers if required
            base.BuildVertexBuffer(ref bufferState, invViewX, invViewY, ref spaceTranslation, ref spaceRotation, spaceScale, ref sorter, ref viewProj);

            // Get all the required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);

            if (!positionField.IsValid())
            {
                return(0);
            }
            var lifeField  = sorter.GetField(ParticleFields.Life);
            var sizeField  = sorter.GetField(ParticleFields.Size);
            var angleField = sorter.GetField(ParticleFields.Angle);
            var hasAngle   = angleField.IsValid() || (SamplerRotation != null);


            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            var trsIdentity = (spaceScale == 1f);

            trsIdentity = trsIdentity && (spaceTranslation.Equals(Vector3.Zero));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));


            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            foreach (var particle in sorter)
            {
                var centralPos = GetParticlePosition(particle, positionField, lifeField);

                var particleSize = GetParticleSize(particle, sizeField, lifeField);

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos    = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;
                }

                // Use half size to make a Size = 1 result in a Billboard of 1m x 1m
                var unitX = invViewX * (particleSize * 0.5f);
                var unitY = invViewY * (particleSize * 0.5f);

                // Particle rotation. Positive value means clockwise rotation.
                if (hasAngle)
                {
                    var rotationAngle = GetParticleRotation(particle, angleField, lifeField);

                    var cosA  = (float)Math.Cos(rotationAngle);
                    var sinA  = (float)Math.Sin(rotationAngle);
                    var tempX = unitX * cosA - unitY * sinA;
                    unitY = unitY * cosA + unitX * sinA;
                    unitX = tempX;
                }


                var particlePos = centralPos - unitX + unitY;
                var uvCoord     = Vector2.Zero;
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X    = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            var vtxPerShape = 4 * QuadsPerParticle;

            return(renderedParticles * vtxPerShape);
        }
        /// <inheritdoc />
        public unsafe override int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
            ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
        {
            // Update the curve samplers if required
            base.BuildVertexBuffer(ref bufferState, invViewX, invViewY, ref spaceTranslation, ref spaceRotation, spaceScale, ref sorter);

            // Get all the required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);
            if (!positionField.IsValid())
                return 0;
            var lifeField = sorter.GetField(ParticleFields.Life);
            var sizeField = sorter.GetField(ParticleFields.Size);
            var directionField = sorter.GetField(ParticleFields.Direction);

            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            var trsIdentity = (spaceScale == 1f);
            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));


            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            Vector3 invViewZ;
            Vector3.Cross(ref invViewX, ref invViewY, out invViewZ);
            invViewZ.Normalize();

            foreach (var particle in sorter)
            {
                var centralPos = GetParticlePosition(particle, positionField, lifeField);

                var centralOffset = (directionField.IsValid()) ? particle.Get(directionField) : new Vector3(0, 1, 0);

                var particleSize = GetParticleSize(particle, sizeField, lifeField);

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos = centralPos * spaceScale + spaceTranslation;

                    spaceRotation.Rotate(ref centralOffset);
                    centralOffset = centralOffset * spaceScale;

                    particleSize *= spaceScale;
                }

                var unitX = invViewX;
                var unitY = invViewY;

                {
                    var centralAxis = centralOffset;

                    float dotZ;
                    Vector3.Dot(ref centralAxis, ref invViewZ, out dotZ);
                    centralAxis -= invViewZ*dotZ;
                    centralAxis.Normalize();

                    float dotX;
                    Vector3.Dot(ref centralAxis, ref unitX, out dotX);

                    float dotY;
                    Vector3.Dot(ref centralAxis, ref unitY, out dotY);

                    unitX = unitX*dotY - unitY*dotX;
                    unitX.Normalize();

                    unitY = centralOffset;
                }

                // Use half size to make a Size = 1 result in a Billboard of 1m x 1m
                unitX *= (particleSize * 0.5f);
                if (ScaleLength)
                {
                    unitY *= (LengthFactor * particleSize * 0.5f);
                }
                else
                {
                    unitY *= (LengthFactor * 0.5f);
                }

                var particlePos = centralPos - unitX + unitY;
                var uvCoord = new Vector2(0, 0);
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            var vtxPerShape = 4 * QuadsPerParticle;
            return renderedParticles * vtxPerShape;
        }
示例#28
0
        public override unsafe void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sorter)
        {
            // If you want, you can integrate the base builder here and not call it. It should result in slight speed up
            base.PatchVertexBuffer(ref bufferState, invViewX, invViewY, ref sorter);

            // Update the non-default coordinates first, because they update off the default ones
            if (UVBuilder1 != null)
            {
                UVBuilder1.BuildUVCoordinates(ref bufferState, ref sorter, texCoord1);
            }

            // Update the default coordinates last
            if (UVBuilder0 != null)
            {
                UVBuilder0.BuildUVCoordinates(ref bufferState, ref sorter, texCoord0);
            }

            // If the particles have color field, the base class should have already passed the information
            if (HasColorField)
            {
                return;
            }

            // If there is no color stream we don't need to fill anything
            var colAttribute = bufferState.GetAccessor(VertexAttributes.Color);

            if (colAttribute.Size <= 0)
            {
                return;
            }

            // Since the particles don't have their own color field, set the default color to white
            var color = 0xFFFFFFFF;

            bufferState.StartOver();
            foreach (var particle in sorter)
            {
                bufferState.SetAttributePerParticle(colAttribute, (IntPtr)(&color));

                bufferState.NextParticle();
            }

            bufferState.StartOver();
        }
        public override unsafe void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sorter)
        {
            // If you want, you can integrate the base builder here and not call it. It should result in slight speed up
            base.PatchVertexBuffer(ref bufferState, invViewX, invViewY, ref sorter);

            // Update the non-default coordinates first, because they update off the default ones
            if (UVBuilder1 != null) UVBuilder1.BuildUVCoordinates(ref bufferState, ref sorter, texCoord1);

            // Update the default coordinates last
            if (UVBuilder0 != null) UVBuilder0.BuildUVCoordinates(ref bufferState, ref sorter, texCoord0);

            // If the particles have color field, the base class should have already passed the information
            if (HasColorField)
                return;

            // If there is no color stream we don't need to fill anything
            var colAttribute = bufferState.GetAccessor(VertexAttributes.Color);
            if (colAttribute.Size <= 0)
                return;

            // Since the particles don't have their own color field, set the default color to white
            var color = 0xFFFFFFFF;

            bufferState.StartOver();
            foreach (var particle in sorter)
            {
                bufferState.SetAttributePerParticle(colAttribute, (IntPtr)(&color));

                bufferState.NextParticle();
            }

            bufferState.StartOver();
        }
示例#30
0
 /// <summary>
 /// Builds the actual vertex buffer for the current frame using the particle data
 /// </summary>
 /// <param name="bufferState">Target particle buffer state, used to populate the assigned vertex buffer</param>
 /// <param name="invViewX">Unit vector X (right) in camera space, extracted from the inverse view matrix</param>
 /// <param name="invViewY">Unit vector Y (up) in camera space, extracted from the inverse view matrix</param>
 /// <param name="spaceTranslation">Translation of the target draw space in regard to the particle data (world or local)</param>
 /// <param name="spaceRotation">Rotation of the target draw space in regard to the particle data (world or local)</param>
 /// <param name="spaceScale">Uniform scale of the target draw space in regard to the particle data (world or local)</param>
 /// <param name="sorter">Particle enumerator which can be iterated and returns sported particles</param>
 /// <returns></returns>
 public abstract int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, 
     ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter);
        public void Load(RTSRenderer renderer, ParticleOptions o)
        {
            // Create Bullet System
            plBullets = new ParticleList<BulletParticle, VertexBulletInstance>(renderer, o.BulletMaxCount, ParticleType.Bullet);
            using(var fs = File.OpenRead(o.BulletModel)) {
                LoadBulletModel(renderer, fs, ParsingFlags.ConversionOpenGL);
            }
            LoadBulletTexture(renderer, o.BulletTexture);

            // Create Fire System
            plFires = new ParticleList<FireParticle, VertexFireInstance>(renderer, o.FireMaxCount, ParticleType.Fire);
            BuildFireModel(renderer, o.FireDetail);
            LoadFireShader(renderer, o.FireNoise, o.FireColor, o.FireAlpha);

            // Create Lightning System
            plBolts = new ParticleList<LightningParticle, VertexLightningInstance>(renderer, o.LightningMaxCount, ParticleType.Lightning);
            BuildLightningModel(renderer);
            LoadLightningShader(renderer, o.LightningImage, o.LightningNumTypes);

            // Create Alert System
            plAlerts = new ParticleList<AlertParticle, VertexAlertInstance>(renderer, o.AlertMaxCount, ParticleType.Alert);
            BuildAlertModel(renderer);
            tAlert = renderer.LoadTexture2D(o.AlertImage);

            // Create Blood System
            plBloods = new ParticleList<BloodParticle, VertexAlertInstance>(renderer, o.BloodMaxCount, ParticleType.Blood);
            BuildBloodModel(renderer);
            tBlood = renderer.LoadTexture2D(o.BloodImage);
        }
示例#32
0
 /// <summary>
 /// Enhances or animates the texture coordinates using already existing base coordinates of (0, 0, 1, 1) or similar
 /// (base texture coordinates may differ depending on the actual shape)
 /// </summary>
 /// <param name="bufferState">The particle buffer state which is used to build the assigned vertex buffer</param>
 /// <param name="sorter"><see cref="ParticleSorter"/> to use to iterate over all particles drawn this frame</param>
 /// <param name="texCoordsDescription">Attribute description of the texture coordinates in the current vertex layout</param>
 public abstract void BuildUVCoordinates(ref ParticleBufferState bufferState, ref ParticleList sorter, AttributeDescription texCoordsDescription);
 /// <summary>
 /// Patch the particle's vertex buffer which was already built by the <see cref="ShapeBuilders.ShapeBuilder"/>
 /// This involes animating hte uv coordinates and filling per-particle fields, such as the color field
 /// </summary>
 /// <param name="bufferState">The particle buffer state which is used to build the assigned vertex buffer</param>
 /// <param name="invViewX">Unit vector X (right) in camera space, extracted from the inverse view matrix</param>
 /// <param name="invViewY">Unit vector Y (up) in camera space, extracted from the inverse view matrix</param>
 /// <param name="sorter">Particle enumerator which can be iterated and returns sported particles</param>
 public virtual void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sortedList)
 {
 }
示例#34
0
 public override int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
                                       ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter, ref Matrix viewProj)
 {
     return(0);
 }
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, 
            ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
        {
            // Update the curve samplers if required
            base.BuildVertexBuffer(ref bufferState, invViewX, invViewY, ref spaceTranslation, ref spaceRotation, spaceScale, ref sorter);

            // Get all required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);
            if (!positionField.IsValid())
                return 0;
            var sizeField = sorter.GetField(ParticleFields.Size);
            var lifeField = sorter.GetField(ParticleFields.Life);
            var angleField = sorter.GetField(ParticleFields.Angle);
            var hasAngle = angleField.IsValid() || (SamplerRotation != null);


            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            var trsIdentity = (spaceScale == 1f);
            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));


            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            foreach (var particle in sorter)
            {
                var centralPos = GetParticlePosition(particle, positionField, lifeField);

                var particleSize = GetParticleSize(particle, sizeField, lifeField);

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;
                }

                // Use half size to make a Size = 1 result in a Billboard of 1m x 1m
                var unitX = invViewX * (particleSize * 0.5f); 
                var unitY = invViewY * (particleSize * 0.5f); 

                // Particle rotation. Positive value means clockwise rotation.
                if (hasAngle)
                {
                    var rotationAngle = GetParticleRotation(particle, angleField, lifeField);
                    var cosA = (float)Math.Cos(rotationAngle);
                    var sinA = (float)Math.Sin(rotationAngle);
                    var tempX = unitX * cosA - unitY * sinA;
                    unitY = unitY * cosA + unitX * sinA;
                    unitX = tempX;
                }

                // vertex.Size = particleSize;

                const float Sqrt3Half = 0.86602540378f;
                unitY *= Sqrt3Half;
                var halfX = unitX * 0.5f;

                var particlePos = centralPos - halfX + unitY;
                var uvCoord = new Vector2(0.25f, 0.5f - Sqrt3Half * 0.5f);


                // Upper half

                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX;
                uvCoord.X = 0.75f;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos += halfX;
                particlePos -= unitY;
                uvCoord.X = 1;
                uvCoord.Y = 0.5f;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                // Upper half

                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= halfX;
                particlePos -= unitY;
                uvCoord.X = 0.75f;
                uvCoord.Y = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX;
                uvCoord.X = 0.25f;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            var vtxPerShape = 4 * QuadsPerParticle;
            return renderedParticles * vtxPerShape;
        }
示例#36
0
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
                                                     ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter, ref Matrix viewProj)
        {
            // Update the curve samplers if required
            base.BuildVertexBuffer(ref bufferState, invViewX, invViewY, ref spaceTranslation, ref spaceRotation, spaceScale, ref sorter, ref viewProj);

            // Get all the required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);

            if (!positionField.IsValid())
            {
                return(0);
            }
            var lifeField      = sorter.GetField(ParticleFields.Life);
            var sizeField      = sorter.GetField(ParticleFields.Size);
            var directionField = sorter.GetField(ParticleFields.Direction);

            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            var trsIdentity = (spaceScale == 1f);

            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));


            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            // TODO Use viewProj
            Vector3 invViewZ;

            Vector3.Cross(ref invViewX, ref invViewY, out invViewZ);
            invViewZ.Normalize();

            foreach (var particle in sorter)
            {
                var centralPos = GetParticlePosition(particle, positionField, lifeField);

                var centralOffset = (directionField.IsValid()) ? particle.Get(directionField) : new Vector3(0, 1, 0);

                var particleSize = GetParticleSize(particle, sizeField, lifeField);

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos = centralPos * spaceScale + spaceTranslation;

                    spaceRotation.Rotate(ref centralOffset);
                    centralOffset = centralOffset * spaceScale;

                    particleSize *= spaceScale;
                }

                var unitX = invViewX;
                var unitY = invViewY;

                {
                    var centralAxis = centralOffset;

                    float dotZ;
                    Vector3.Dot(ref centralAxis, ref invViewZ, out dotZ);
                    centralAxis -= invViewZ * dotZ;
                    centralAxis.Normalize();

                    float dotX;
                    Vector3.Dot(ref centralAxis, ref unitX, out dotX);

                    float dotY;
                    Vector3.Dot(ref centralAxis, ref unitY, out dotY);

                    unitX = unitX * dotY - unitY * dotX;
                    unitX.Normalize();

                    unitY = centralOffset;
                }

                // Use half size to make a Size = 1 result in a Billboard of 1m x 1m
                unitX *= (particleSize * 0.5f);
                if (ScaleLength)
                {
                    unitY *= (LengthFactor * particleSize * 0.5f);
                }
                else
                {
                    unitY *= (LengthFactor * 0.5f);
                }

                var particlePos = centralPos - unitX + unitY;
                var uvCoord     = new Vector2(0, 0);
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y    = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X    = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            var vtxPerShape = 4 * QuadsPerParticle;

            return(renderedParticles * vtxPerShape);
        }
        /// <inheritdoc />
        public unsafe override void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sorter)
        {
            // If you want, you can implement the base builder here and not call it. It should result in slight speed up
            base.PatchVertexBuffer(ref bufferState, invViewX, invViewY, ref sorter);

            //  The UV Builder, if present, animates the basic (0, 0, 1, 1) uv coordinates of each billboard
            UVBuilder?.BuildUVCoordinates(ref bufferState, ref sorter, bufferState.DefaultTexCoords);
            bufferState.StartOver();

            // If the particles have color field, the base class should have already passed the information
            if (HasColorField)
                return;

            // If the particles don't have color field but there is no color stream either we don't need to fill anything
            var colAttribute = bufferState.GetAccessor(VertexAttributes.Color);
            if (colAttribute.Size <= 0)
                return;

            // Since the particles don't have their own color field, set the default color to white
            var color = 0xFFFFFFFF;

            // TODO: for loop. Remove IEnumerable from sorter
            foreach (var particle in sorter)
            {
                bufferState.SetAttributePerParticle(colAttribute, (IntPtr)(&color));

                bufferState.NextParticle();
            }

            bufferState.StartOver();
        }
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
            ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
        {
            // Get all the required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);
            if (!positionField.IsValid())
                return 0;
            var sizeField = sorter.GetField(ParticleFields.Size);

            var orderField = sorter.GetField(ParticleFields.Order);

            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            // ReSharper disable once CompareOfFloatsByEqualityOperator
            var trsIdentity = (spaceScale == 1f);
            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));

            var ribbonizer = new Ribbonizer(this, currentTotalParticles, currentQuadsPerParticle);

            var renderedParticles = 0;
            bufferState.StartOver();

            uint oldOrderValue = 0;

            foreach (var particle in sorter)
            {
                if (orderField.IsValid())
                {
                    var orderValue = (*((uint*)particle[orderField]));

                    if ((orderValue >> SpawnOrderConst.GroupBitOffset) != (oldOrderValue >> SpawnOrderConst.GroupBitOffset)) 
                    {
                        ribbonizer.Ribbonize(ref bufferState, invViewX, invViewY, QuadsPerParticle);
                        ribbonizer.RibbonSplit();
                    }

                    oldOrderValue = orderValue;
                }

                var centralPos = particle.Get(positionField);

                var particleSize = sizeField.IsValid() ? particle.Get(sizeField) : 1f;

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;
                }
                
                ribbonizer.AddParticle(ref centralPos, particleSize);
                renderedParticles++;
            }

            ribbonizer.Ribbonize(ref bufferState, invViewX, invViewY, QuadsPerParticle);

            ribbonizer.Free();

            var vtxPerShape = 4 * QuadsPerParticle;
            return renderedParticles * vtxPerShape;
        }
示例#39
0
 private void InkBuilder_LayoutUpdated(object sender, EventArgs e)
 {
     mAddedInterpolatedSpline     = new ParticleList();
     mPredictedInterpolatedSpline = new ParticleList();
 }
示例#40
0
        /// <inheritdoc />
        public unsafe override void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sorter)
        {
            // If you want, you can implement the base builder here and not call it. It should result in slight speed up
            base.PatchVertexBuffer(ref bufferState, invViewX, invViewY, ref sorter);

            //  The UV Builder, if present, animates the basic (0, 0, 1, 1) uv coordinates of each billboard
            UVBuilder?.BuildUVCoordinates(ref bufferState, ref sorter, bufferState.DefaultTexCoords);
            bufferState.StartOver();

            // If the particles have color field, the base class should have already passed the information
            if (HasColorField)
            {
                return;
            }

            // If the particles don't have color field but there is no color stream either we don't need to fill anything
            var colAttribute = bufferState.GetAccessor(VertexAttributes.Color);

            if (colAttribute.Size <= 0)
            {
                return;
            }

            // Since the particles don't have their own color field, set the default color to white
            var color = 0xFFFFFFFF;

            // TODO: for loop. Remove IEnumerable from sorter
            foreach (var particle in sorter)
            {
                bufferState.SetAttributePerParticle(colAttribute, (IntPtr)(&color));

                bufferState.NextParticle();
            }

            bufferState.StartOver();
        }
        /// <inheritdoc />
        public unsafe override int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, 
            ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
        {
            // Update the curve samplers if required
            base.BuildVertexBuffer(ref bufferState, invViewX, invViewY, ref spaceTranslation, ref spaceRotation, spaceScale, ref sorter);

            // Get all required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);
            if (!positionField.IsValid())
                return 0;
            var lifeField = sorter.GetField(ParticleFields.Life);
            var sizeField = sorter.GetField(ParticleFields.Size);
            var rotField = sorter.GetField(ParticleFields.Quaternion);
            var hasRotation = rotField.IsValid() || (SamplerRotation != null);


            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            var trsIdentity = (spaceScale == 1f);
            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));


            var renderedParticles = 0;

            var posAttribute = bufferState.GetAccessor(VertexAttributes.Position);
            var texAttribute = bufferState.GetAccessor(bufferState.DefaultTexCoords);

            foreach (var particle in sorter)
            {
                var centralPos = GetParticlePosition(particle, positionField, lifeField);

                var particleSize = GetParticleSize(particle, sizeField, lifeField);

                var unitX = new Vector3(1, 0, 0); 
                var unitY = new Vector3(0, 0, 1); 

                if (hasRotation)
                {
                    var particleRotation = GetParticleRotation(particle, rotField, lifeField);
                    particleRotation.Rotate(ref unitX);
                    particleRotation.Rotate(ref unitY);
                }

                // The TRS matrix is not an identity, so we need to transform the quad
                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;

                    spaceRotation.Rotate(ref unitX);
                    spaceRotation.Rotate(ref unitY);
                }

                // Use half size to make a Size = 1 result in a Billboard of 1m x 1m
                unitX *= (particleSize * 0.5f);
                unitY *= (particleSize * 0.5f);

                var particlePos = centralPos - unitX + unitY;
                var uvCoord = new Vector2(0, 0);
                // 0f 0f
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 0f
                particlePos += unitX * 2;
                uvCoord.X = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 1f 1f
                particlePos -= unitY * 2;
                uvCoord.Y = 1;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();


                // 0f 1f
                particlePos -= unitX * 2;
                uvCoord.X = 0;
                bufferState.SetAttribute(posAttribute, (IntPtr)(&particlePos));
                bufferState.SetAttribute(texAttribute, (IntPtr)(&uvCoord));
                bufferState.NextVertex();

                renderedParticles++;
            }

            var vtxPerShape = 4 * QuadsPerParticle;
            return renderedParticles * vtxPerShape;
        }
示例#42
0
        /// <inheritdoc />
        public override unsafe int BuildVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY,
                                                     ref Vector3 spaceTranslation, ref Quaternion spaceRotation, float spaceScale, ref ParticleList sorter)
        {
            // Get all the required particle fields
            var positionField = sorter.GetField(ParticleFields.Position);

            if (!positionField.IsValid())
            {
                return(0);
            }
            var sizeField = sorter.GetField(ParticleFields.Size);

            var orderField = sorter.GetField(ParticleFields.Order);

            // Check if the draw space is identity - in this case we don't need to transform the position, scale and rotation vectors
            // ReSharper disable once CompareOfFloatsByEqualityOperator
            var trsIdentity = (spaceScale == 1f);

            trsIdentity = trsIdentity && (spaceTranslation.Equals(new Vector3(0, 0, 0)));
            trsIdentity = trsIdentity && (spaceRotation.Equals(Quaternion.Identity));

            var ribbonizer = new Ribbonizer(this, currentTotalParticles, currentQuadsPerParticle);

            var renderedParticles = 0;

            bufferState.StartOver();

            uint oldOrderValue = 0;

            foreach (var particle in sorter)
            {
                if (orderField.IsValid())
                {
                    var orderValue = (*((uint *)particle[orderField]));

                    if ((orderValue >> SpawnOrderConst.GroupBitOffset) != (oldOrderValue >> SpawnOrderConst.GroupBitOffset))
                    {
                        ribbonizer.Ribbonize(ref bufferState, invViewX, invViewY, QuadsPerParticle);
                        ribbonizer.RibbonSplit();
                    }

                    oldOrderValue = orderValue;
                }

                var centralPos = particle.Get(positionField);

                var particleSize = sizeField.IsValid() ? particle.Get(sizeField) : 1f;

                if (!trsIdentity)
                {
                    spaceRotation.Rotate(ref centralPos);
                    centralPos    = centralPos * spaceScale + spaceTranslation;
                    particleSize *= spaceScale;
                }

                ribbonizer.AddParticle(ref centralPos, particleSize);
                renderedParticles++;
            }

            ribbonizer.Ribbonize(ref bufferState, invViewX, invViewY, QuadsPerParticle);

            ribbonizer.Free();

            var vtxPerShape = 4 * QuadsPerParticle;

            return(renderedParticles * vtxPerShape);
        }
        /// <inheritdoc />
        public override unsafe void PatchVertexBuffer(ref ParticleBufferState bufferState, Vector3 invViewX, Vector3 invViewY, ref ParticleList sorter)
        {
            // If you want, you can integrate the base builder here and not call it. It should result in slight speed up
            base.PatchVertexBuffer(ref bufferState, invViewX, invViewY, ref sorter);

            var colorField = sorter.GetField(ParticleFields.Color);
            if (!colorField.IsValid())
                return;

            var colAttribute = bufferState.GetAccessor(VertexAttributes.Color);
            if (colAttribute.Size <= 0)
                return;

            foreach (var particle in sorter)
            {
                // Set the vertex color attribute to the particle's color field
                var color = (uint)(*(Color4*)particle[colorField]).ToRgba();
                bufferState.SetAttributePerSegment(colAttribute, (IntPtr)(&color));

                bufferState.NextSegment();
            }

            bufferState.StartOver();
        }