XNA UK User Group

A helping hand for bedroom coders throughout the land.
in

RandomChaos

March 2008 - Posts

  • 2D Particle Tutorial V

    http://www.youtube.com/v/0_qMAyr7RJY <p><a href="http://www.youtube.com/v/0_qMAyr7RJY">http://www.youtube.com/v/0_qMAyr7RJY</a></p>

    In this tutorial I am going to bind the emitter to a game agent, now you will have to forgive me as I have been very lazy, I have taken textures from the Creators Club particle example as well as some of the facing methods, have not bothered to write a new agent class, rather just derived it from the Particle2D class and it's texture I have taken from a game I was writing for this years DBP warm up challenge and never finished. BUT, having said all that I think it should give you enough to see how you can bolt the emitters into your own game agents.

    Where to start, well as I want to setup and draw the emitters from my Agent, I have removed the base class from it and made it's protected methods public. In doing so I have had to add a Game object to the class, and as I wanted to have two emitters per agent, one for smoke and one for fire and one to have a larger particle than the other so introduced a baseScale. Also added a texture asset parameter to the constructor as well as the new baseScale. I have also replaced the targetPos with a Particle2D object so we can bind to the agent, this also has been added to the constructor. So save me confusing you any more, here is the class as it stands now.

    public class ParticleEmitter2D
    {
        SpriteBatch spriteBatch;
    
        public Particle2D[] particles;
        public Vector2 position;
        public int particleCount;
        public Color particleColor;
    
        int nextParticle = 0;
        Particle2D targetObj;
        Vector2 myLastpos;
    
        string myTextureAsset;
        float baseScale = 1;
    
        Game Game;
    
        public ParticleEmitter2D(Game game,int particleCount,string textureAsset,float scale,Particle2D target)
        {
            Game = game;
            this.position = Vector2.Zero;
            this.particleCount = particleCount;
            particleColor = Color.White;
            myTextureAsset = textureAsset;
            baseScale = scale;
    
            targetObj = target;
        }
        public void LoadContent()
        {
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
    
            Texture2D tmpTexture = Game.Content.Load<Texture2D>(myTextureAsset);
    
            LoadParticles(tmpTexture);
    
            myLastpos = targetObj.position;
    
        }
        public void LoadParticles(Texture2D tmpTexture)
        {
            particles = new Particle2D[particleCount];
    
            for (int p = 0; p < particles.Length; p++)
            {
                particles[p] = new Particle2D();
                particles[p].position = position;
                particles[p].Texture = tmpTexture;
                particles[p].color = new Color(particles[p].color.R, particles[p].color.G, particles[p].color.B, 0);
                particles[p].scale = baseScale;
                particles[p].width = (int)(32 * baseScale);
                particles[p].height = (int)(32 * baseScale);
            }
        }
        public void Update(GameTime gameTime)
        {
            for (int p = 0; p < particles.Length; p++)
            {
                if (p == nextParticle && myLastpos != position)
                {
                    particles[p].position = myLastpos;
                    particles[p].color = particleColor;                    
                }
                if (particles[p].position != position) // Particle is in use
                {
                    particles[p].scale = 1 - (Vector2.Distance(particles[p].position, targetObj.position) / 400);
                    particles[p].color = new Color(particles[p].color.R, particles[p].color.G, particles[p].color.B, (byte)(particles[p].scale * 255));
                }
            }
            nextParticle++;
    
            if (nextParticle >= particles.Length)
                nextParticle = 0;
    
            myLastpos = targetObj.position;            
        }
        public void Draw(GameTime gameTime)
        {
            spriteBatch.Begin(SpriteBlendMode.Additive , SpriteSortMode.Immediate, SaveStateMode.SaveState);
    
            for (int p = 0; p < particles.Length; p++)
            {
                if(particles[p].position != targetObj.position)
                    particles[p].Draw(spriteBatch);
            }
    
            spriteBatch.End();
        }
    }

    Now we create our Agent class, this is derived from the Particle2D class, I add a Game object, a velocity and two ParticleEmitter2Ds, one for smoke and one for fire. A reasonably simple constructor to set the base values, a LoadContent to, well load the content, an Update method where I can code the behaviour of the agent, a Draw method and then three methods acquired from the Creators Club samples. This gives me a class that looks like this

    public class Agent : Particle2D
    {
        Game game;
        public Vector2 velocity;
    
        ParticleEmitter2D emitterFire;
        ParticleEmitter2D emitterSmoke;
    
    
        public Agent(Game game,Vector2 velocity)
        {
            this.game = game;
            scale = 1;
            height = 42;
            width = 42;
    
            this.velocity = velocity;
    
            emitterFire = new ParticleEmitter2D(game, 75,"Textures/fire",1,this);
            emitterSmoke = new ParticleEmitter2D(game, 75, "Textures/smoke",1.5f,this);
    
        }
    
    
        public void LoadContent()
        {
            emitterFire.LoadContent();
            emitterSmoke.LoadContent();
            Random rnd = new Random(DateTime.Now.Millisecond);            
            position = new Vector2(game.GraphicsDevice.Viewport.Width * (float)rnd.NextDouble(), game.GraphicsDevice.Viewport.Height * (float)rnd.NextDouble());
        }
    
        public void Update(GameTime gameTime)
        {
            position += velocity;
    
            if (velocity != Vector2.Zero)
                LookAt(position + velocity, 1f);
    
            if(position.X + width/2 > game.GraphicsDevice.Viewport.Width)
                velocity = Vector2.Reflect(velocity,new Vector2(-1,0));
    
            if (position.Y + height/2 > game.GraphicsDevice.Viewport.Height)
                velocity = Vector2.Reflect(velocity, new Vector2(0, -1));
    
            if (position.X - width/2 <= 0)
                velocity = Vector2.Reflect(velocity, new Vector2(1, 0));
    
            if (position.Y - height/2 <= 0)
                velocity = Vector2.Reflect(velocity, new Vector2(0, 1));
    
            emitterFire.Update(gameTime);
            emitterSmoke.Update(gameTime);
        }
    
        public void Draw(GameTime gameTime,SpriteBatch spriteBatch)
        {
            emitterFire.Draw(gameTime);
            emitterSmoke.Draw(gameTime);
            spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.SaveState);
            base.Draw(spriteBatch);
            spriteBatch.End();
        }
    
        public void LookAt(Vector2 target, float speed)
        {
            rotation = TurnToFace(position, 2 * target - position, rotation, 1f);
        }
    
        private static float TurnToFace(Vector2 position, Vector2 faceThis, float currentAngle, float turnSpeed)
        {
    
            float x = faceThis.X - position.X;
            float y = faceThis.Y - position.Y;
    
            float desiredAngle = (float)Math.Atan2(y, x);
    
            float difference = WrapAngle(desiredAngle - currentAngle);
    
            difference = MathHelper.Clamp(difference, -turnSpeed, turnSpeed);
    
            return WrapAngle(currentAngle + difference);
        }
        private static float WrapAngle(float radians)
        {
            while (radians < -MathHelper.Pi)
            {
                radians += MathHelper.TwoPi;
            }
            while (radians > MathHelper.Pi)
            {
                radians -= MathHelper.TwoPi;
            }
            return radians;
        }
    }

    So with that all in place I create an Agent array and in each key Game method (LoadContent,Update and Draw) I loop through my agents and call the respective method.

    Now the code around the whole Agent and related emitters is not great, best thing would be to move ALL this into a single draw call, as I said at the top, I have been very lazy with this tutorial. I have not even done a 3D version, but the principles will carry over just the same.

    Now what we end up with is the clip you see at the top of this post, yes that's right ROCKET SHEEP!!!

    Solution project can be downloaded here.

  • 2D Particle Tutorial IV

    We have our classes so all I am going to do is now apply some pixel shader effects to both the particle system and the background image. I am going to describe how the pixel shader is applied to the particle emitter as the technique is the same for the background image.

    So, to our ParticleEmitter2D class we are going to add an Effect object called shader and in the LoadContent method we need to load the shader we want to use, I have written 2 very simple pixel shaders for this tutorial, one to fade the edge of a texture and another to invert the colors in a texture. In the particle emitter class I am going to use the color inversion shader, to show this to better effect I am using my second particle texture as it has more color in it. The LoadContent method now looks like this so we can load the effect file

    protected override void LoadContent()
    {
        shader = Game.Content.Load<Effect>("Shaders/InverseColor");            
    
        position = new Vector2(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
        spriteBatch = new SpriteBatch(Game.GraphicsDevice);
    
        Texture2D tmpTexture = Game.Content.Load<Texture2D>("Textures/particleII");
    
        LoadParticles(tmpTexture);
    
        targetPos = position;
        myLastpos = targetPos;
    
        base.LoadContent();
    }

    Now to put this shader into effect we have to alter the Draw method by calling the begin method of the shader and it's first technique and once the particles are drawn, ended. The Draw call now looks like this

    public override void Draw(GameTime gameTime)
    {
        spriteBatch.Begin(SpriteBlendMode.AlphaBlend   , SpriteSortMode.Immediate, SaveStateMode.SaveState);
    
        shader.Begin();
        shader.CurrentTechnique.Passes[0].Begin();
    
        for (int p = 0; p < particles.Length; p++)
            particles[p].Draw(spriteBatch);
    
        shader.CurrentTechnique.Passes[0].End();
        shader.End();
    
        spriteBatch.End();
    
        base.Draw(gameTime);
    }

    And that is how I apply pixel shaders to 2D textures, in this case a particle array.

    Here are the two pixel shaders

    EdgeAlphaFade.fx

    sampler TextureSampler : register(s0);
    
    struct VertexShaderOutput
    {
        float4 color : COLOR0;
        float2 texCoord : TEXCOORD0;
    };
    
    float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    {    
        float4 col = tex2D(TextureSampler,input.texCoord);
        
        if(input.texCoord.x < .5)
            col.a =  input.texCoord.x * 1;
        else
            col.a =  1-input.texCoord.x;
            
        if(input.texCoord.y < .5)
            col.a +=  input.texCoord.y * 1;
        else
            col.a +=  1-input.texCoord.y;
        
        return col;
    }
    
    technique Technique1
    {
        pass Pass1
        {
            PixelShader = compile ps_2_0 PixelShaderFunction();        
        }
    }

    InverseColor.fx

    sampler TextureSampler : register(s0);
    
    struct VertexShaderOutput
    {
        float4 color : COLOR0;
        float2 texCoord : TEXCOORD0;
    };
    
    float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
    {    
        float4 col = tex2D(TextureSampler,input.texCoord);
        
        float orgA = col.a;
        
        col = (float4)1.0f - col;
        
        col.a = orgA;
        
        return col;
    }
    
    technique Technique1
    {
        pass Pass1
        {
            PixelShader = compile ps_2_0 PixelShaderFunction();        
        }
    }

    As a side note, you can also use this method to texture your fonts.

    Solution can be located here.

  • 2D Particle Tutorial III

    http://www.youtube.com/v/fMPHW7tKUTI <p><a href="http://www.youtube.com/v/fMPHW7tKUTI">http://www.youtube.com/v/fMPHW7tKUTI</a></p>

    Well now onto something I know even less about, 2D particles. As you may or may not have seen I have had a play with these in my GSM Library where I have put a star field in as an optional background, but I said I would post my current knowledge of particles both 3D and 2D so here is my tutorial on 2D particles.

    Like the previous tutorial I am going to create a simple trail particle emitter and as before I am going to start by creating my particle definition. So created a new source file called Particle2D.cs and again setup what I think will be the very basic elements you will want in a 2D particle, created a default constructor and a Draw method.

    public class Particle2D
    {
        private Texture2D texture;
        public Vector2 position;
        public float rotation;
        public float scale;
        public Color color;
        public int width;
        public int height;
        public Vector2 origin;
        public int depth;
    
        public Texture2D Texture
        {
            get { return texture; }
            set
            {
                texture = value;
                origin = new Vector2(texture.Width / 2, texture.Height / 2);
            }
        }
    
        public Particle2D()
        {
            position = Vector2.Zero;
            rotation = 0;
            scale = 1;
            color = Color.White;
            origin = Vector2.Zero;
            depth = 0;
        }
    
        public void Draw(SpriteBatch spriteBatch)
        {
            spriteBatch.Draw(texture, new Rectangle((int)position.X, (int)position.Y, (int)(width * scale),(int)(height * scale)), new Rectangle(0, 0, texture.Width, texture.Height), color, rotation, origin, SpriteEffects.None, depth);
        }
    }

    So what we have in this class is the texture to be used when drawing our particle, the position it is to be drawn at, it's rotation, scale, color, width and height. The origin is the point on the texture that is going to be used when drawing the default of this is 0,0, so the top left hand corner of the texture, I am going to place this in the centre of our particle, the depth is used when you want layers of texture on the screen, I have included this as you may want particles on different levels. Most of this stuff we probably wont use in this tutorial but thought I would show what can be done with a texture in 2D.

    You will also notice a property in there called Texture, I have wrapped the texture field in a property as I will need to re calculate the origin if this texture changes, also in here if you were using something like my GGR implementation you may want to calculate the bounds of the particle in here to.

    The constructor is pretty simple, it just sets all my fields to some default values. The draw method you will see is a little different, it is passed a SpriteBatch object and uses this to draw the particle. This is because you don't want to go doing a SpriteBatch.Begin() for each particle as this would be very expensive on FPS so we bundle them all into one draw call. In a later tutorial I am going to show how you can apply 2D pixel shader effects to your particles and using this method makes it easy to apply a single effect to many particles.

    Now we have a particle definition we need an emitter, so I create another new source file in the project called ParticleEmitter2D.cs  (I know, inventive names eh..). Like in the 3D tutorials I am going to create a trail emitter, so we need similar fields in our class but naturally for a 2D system.

    public class ParticleEmitter2D : DrawableGameComponent
    {
        SpriteBatch spriteBatch;
    
        public Particle2D[] particles;
        public Vector2 position;
        public int particleCount;
        public Color particleColor;
    
        int nextParticle = 0;
        Vector2 targetPos;
        Vector2 myLastpos;
    
        public ParticleEmitter2D(Game game,int particleCount) : base(game)
        {
            this.position = Vector2.Zero;
            this.particleCount = particleCount;
            particleColor = Color.White;
        }
        protected override void LoadContent()
        {
            position = new Vector2(Game.GraphicsDevice.Viewport.Width / 2, Game.GraphicsDevice.Viewport.Height / 2);
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
    
            Texture2D tmpTexture = Game.Content.Load<Texture2D>("Textures/particle");
    
            LoadParticles(tmpTexture);
    
            targetPos = position;
            myLastpos = targetPos;
    
            base.LoadContent();
        }
        public void LoadParticles(Texture2D tmpTexture)
        {
            particles = new Particle2D[particleCount];
    
            for (int p = 0; p < particles.Length; p++)
            {
                particles[p] = new Particle2D();
                particles[p].position = position;
                particles[p].Texture = tmpTexture;
                particles[p].color = new Color(particles[p].color.R, particles[p].color.G, particles[p].color.B, 0);
                particles[p].width = 32;
                particles[p].height = 32;
            }
        }
        public override void Update(GameTime gameTime)
        {
            for (int p = 0; p < particles.Length; p++)
            {
                if (p == nextParticle && myLastpos != position)
                {
                    particles[p].position = myLastpos;
                    particles[p].color = particleColor;                    
                }
                if (particles[p].position != position) // Particle is in use
                {
                    particles[p].scale = 1 - (Vector2.Distance(particles[p].position, targetPos) / 400);
                    particles[p].color = new Color(particles[p].color.R, particles[p].color.G, particles[p].color.B, (byte)(particles[p].scale * 255));
                }
            }
            nextParticle++;
    
            if (nextParticle >= particles.Length)
                nextParticle = 0;
    
            myLastpos = targetPos;
            targetPos = new Vector2((float)Math.Cos(gameTime.TotalGameTime.TotalSeconds) * 200, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds) * 200) + position;
    
            base.Update(gameTime);
        }
        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin(SpriteBlendMode.Additive, SpriteSortMode.Immediate, SaveStateMode.SaveState);
            
            for (int p = 0; p < particles.Length; p++)
                particles[p].Draw(spriteBatch);
    
            spriteBatch.End();
    
            base.Draw(gameTime);
        }
    }

    As you can see there are a few differences here, first of all is the addition of a SpriteBatch object, this is going to be used to draw our batch of particles. As before we have an array of our particles, a position for the emitter as well as a particle count and color. We also have the three variables used to manage out trail. A simple constructor to set the emitters values.

    In the LoadContent method I am setting the position of the emitter to the centre of my game screen, initialising my sprite batch object, loading a temporary Texture2D with the texture to e used in the particles, calling my LoadParticle method and then setting the trail management variables.

    In my LoadParticles method I set the particle array size, then move through the array setting each particle up ready for use. You can see here I have set the particle width and height to 32.

    The Update method is pretty much the same as before, setting the next particles position, color, scale and opacity.

    The Draw method begins the sprite batch (note this is doing an Additive blend, for no blending set to None and for AlphaBlend, guess what, set it to normal AlphaBlend) and moves through the particle array and draws each particle and then ends the sprite batch draw.

    So, now just as before all we need to do is add the component to the Game.Components collection and away it goes.

    In the next tutorial I am going to show how you can bind these emitters to a game agent (ship/missile etc..), will also introduce a basic explosion particle effect to show how I instance an effect.

    Correction, the next tutorial will show how to apply pixel shaders to your particle emitter, then I will follow this with binding the emitters to game agents.

    You can download the solution project here.

  • 3D PointSprite Particle Tutorial II

    Now we have a simple particle and emitter we can have a look at other blending modes, in the previous tutorial we did what is called and additive blend, this type of blending is called Frame Buffer Alpha Blending and a full description of this can be found in your DirectX SDK documentation. Additive blending is just one of many types of alpha blending. In the Draw call of the emitter we set up the additive alpha blending by using these three values in the RenderState

    game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
    game.GraphicsDevice.RenderState.SourceBlend = Blend.One;
    game.GraphicsDevice.RenderState.DestinationBlend = Blend.One;
    

    If you take a look at you DirectX documentation you will see the final pixel color is calculated like this

    Final Color = ObjectColor * SourceBlendFactor + PixelColor * DestinationBlendFactor

    Where ObjectColor will be our particle, SourceBlendFactor is our SourceBlend RenderState value, PixelColor is the color of the pixel before we draw our particles pixel and DestinationBlendFactor is our DestinationBlend RenderState value. so with both values set to One, the color is added to and so gives rise to the name additive blend. This is great for bright particle effects like sparks or I guess Lasers, where you have a high density of particles you get a brightening effect, but a bit crap if you want smoke and detail from the particle texture.

    So how to keep this texture integrity is to use the following settings

    game.GraphicsDevice.RenderState.SourceBlend = Blend.SourceAlpha;
    game.GraphicsDevice.RenderState.DestinationBlend = Blend.InverseSourceAlpha;

    You will now be able to use the PointSpriteElemets AlphaValue to thin the particle. Also we will need a new particle texture as the one in the first tutorial has a black background but we want a nice transparent texture to be used with this blend mode, so I am going to use one I have created my self, it is a png file so we can have a transparent back ground.

    So now we can also play with the alpha value in the PointSpriteElement structure. In the Update method of the project we add another line just after where we set the particle size so that we can have a faded tail. The Update method now looks like this

    public override void Update(GameTime gameTime)
    {
        for (int p = 0; p < particleArray.Length; p++)
        {
            if (p == nextParticle && myLastpos != myPosition)
            {
                particleArray[p].Position = myLastpos;
                particleArray[p].Color = particleColor;                        
            }                
            particleArray[p].SpriteSize = 1 - (Vector3.Distance(particleArray[p].Position, targetPos) / 25);
            particleArray[p].AlphaValue = 1 - (Vector3.Distance(particleArray[p].Position, targetPos) / 15);
        }
        nextParticle++;
    
        if (nextParticle >= particleArray.Length)
            nextParticle = 0;
    
        myLastpos = targetPos;
        targetPos = new Vector3((float)Math.Cos(gameTime.TotalGameTime.TotalSeconds) * 10, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds) * 10, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds));
    }

    Source for this tutorial can be found here.

  • 3D PointSprite Particle Tutorial I

    http://www.youtube.com/v/AjsQiYaZ-po <p><a href="http://www.youtube.com/v/AjsQiYaZ-po">http://www.youtube.com/v/AjsQiYaZ-po</a></p>  

    Was browsing the boards as I do and came across a thread on Ziggyware where a member was looking for a Particle Engine tutorial, at first I did not quite get what he wanted, so tried to clarify what he wanted with a post and suggested I could create a simple particle library, to which another member and the original poster said it would be a good idea and so I though the best thing would be a very simple tutorial describing what I know of particle system.

    Now, I am no expert but I think I have an idea of the basic principles of a particle system and so I am going to put up a series of tutorials describing how to create a simple particle system. I know I have already got 2 samples up here, but it it just holds code samples and no explanation of what is going on under the hood.

    In this series I am going to do both a 3D and 2D tutorial. As I already have a 3D sample I will start with the 3D system. In this first tutorial I am going to cover a PonitSprite particle system.

    So, where do I start when creating a particle system, well I guess the best place is the particle it's self, to me this means the data structure I am going to use to hold the data required to draw and move my particle, think about what you want the particle to represent, what data you will want to store to draw the particle. So I create my own vertex element, this describes the primitive to be used to draw the particle. Now this is a tutorial so I am going to be quite generic in my particle description, it is going to contain what I think are the basic elements for any particle, you will probably want to add more to this structure for your system(s) or this might just do the job. It is going to hold position, colour, sprite size and an alpha value.

    So I create a new source file in my project and name it after the structure, in this case I have called it PointSpriteElement.cs. In the file I create a new structure definition

      public struct PointSpriteElement
      {
      }

     

     

    I now add my elements

      public struct PointSpriteElement
      {
          Vector3 position;
          Color color;
          Vector2 data;
      }

    So, my position is a vector 3 and will store this particles position in space, colour (I am in the habit of using the American spelling now) will store the color I want to draw the particle in and data is a vector 2 that is going to hold my sprite size in the X and the alpha value in the Y.

    I now give this structure some properties so I can access the particle elements.

        public struct PointSpriteElement
        {
            Vector3 position;
            Color color;
            Vector2 data;
    
            public Vector3 Position
            {
                get { return position; }
                set { position = value; }
            }
    
            public Vector2 Data
            {
                get { return data; }
                set { data = value; }
            }
    
            public Color Color
            {
                get { return color; }
                set { color = value; }
            }
    
            public float SpriteSize
            {
                get { return data.X; }
                set { data.X = value; }
            }
            public float AlphaValue
            {
                get { return data.Y; }
                set { data.Y = value; }
            }
        }

    I now need to create the definition of the particle that will be used by my shader, this is done using a VertexElement array.

    public static readonly VertexElement[] VertexElements = new VertexElement[] 
    {
        new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
        new VertexElement(0, sizeof(float)*3, VertexElementFormat.Color, VertexElementMethod.Default, VertexElementUsage.Color, 0),                
        new VertexElement(0, sizeof(float)*4, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),                
    };

    Right, as you can see this looks a bit messy, but all it is doing is describing my vertex input structure, or I guess a simpler description is how the particle is passed to the shader. So the first line describes the vector 3 that is used for the position, the first parameter is the stream to be used and can be used for stuff like multi texturing as it saves the duplication of vertex data (see this link for a better description), I have only ever used 0. As this is the first element in the element array it has an offset of 0, a format of Vector 3 as that is the data type, the method is default, usage is Position and the channel is 0. So in the shader this would be described as half3 Position : Position0; And so the other to elements are described in the same vein, you can see the offset (second parameter) increased by the last elements size.

    I also include a property so I don't have to keep typing in the particle element size.

    public static int SizeInBytes
    {
        get
        {
            return sizeof(float) * 6;
        }
    }

    So this just returns the size if the structure, which in this case is the size of 6 floats. This could also be described like this (3 + 1 + 2) * 4.

    The whole structure now looks like this:

        public struct PointSpriteElement
        {
            Vector3 position;
            Color color;
            Vector2 data;
    
            public Vector3 Position
            {
                get { return position; }
                set { position = value; }
            }
    
            public Vector4 Data
            {
                get { return data; }
                set { data = value; }
            }
    
            public Color Color
            {
                get { return color; }
                set { color = value; }
            }
    
            public float SpriteSize
            {
                get { return data.X; }
                set { data.X = value; }
            }
            public float AlphaValue
            {
                get { return data.Y; }
                set { data.Y = value; }
            }
      
            public static readonly VertexElement[] VertexElements = new VertexElement[] 
            {
                new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0),
                new VertexElement(0, sizeof(float)*3, VertexElementFormat.Color, VertexElementMethod.Default, VertexElementUsage.Color, 0),                
                new VertexElement(0, sizeof(float)*4, VertexElementFormat.Vector2, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0),                
            };
    
            public static int SizeInBytes
            {
                get
                {
                    return sizeof(float) * 6;
                }
            }
        }

     

    Right we now have a definition for our particle that is going to be used in the shader to draw our particle in the game world. We now need an array of these particles and a class to manage this particle array. In my project I create a new source file called PointSpriteParticleEmitter.cs, this is going to hold my particle emitter class. Again, you need to think about what kind of particle emitter you want to create, in this tutorial I am going to create a simple trail.

    So we start by creating our class

    public class PointSpriteParticleEmitter : DrawableGameComponent
    {
    }

    Now, like any other object in the game world we will need a position a scale and rotation. I am also going to give it a color so I can set all the particle colors if I wish. We will also need a variable to store the number of particles to have in this instance. I also have in this emitter some variables for my particle physics, I will go into more detail in the Update override. Also, we need an Effect object to load the shader into. Oh, and a Game object to bind to the calling game class.

    So the class now looks like this

    public class PointSpriteParticleEmitter : DrawableGameComponent
    {
        public PointSpriteElement[] particleArray;
    
        public Vector3 myPosition;
        public Vector3 myScale;
        public Quaternion myRotation;
    
        public Color particleColor;
        
        public int partCount;
    
        Effect shader;
    
        Game game;
    
        int nextParticle = 0;
        Vector3 targetPos;
        Vector3 myLastpos;
    }

    Now for the constructor (ctor), very simple, the calling game and the particle count are passed and used to build the emitter and all values are set to arbitrary default values.

    public PointSpriteParticleEmitter(Game game, int particleCount) : base(game)
    {
        this.game = game;
        myPosition = Vector3.Zero;
        myScale = Vector3.One;
        myRotation = new Quaternion(0, 0, 0, 1);
    
        partCount = particleCount;
    
        particleColor = Color.White;
    }

    We are inheriting from DrawableGameComponent so we now need to override some of the base methods to load, update and draw our particles. Lets start with LoadContent. In this method we are going to load the shader, texture and load our particle array. I will go into more detail regarding the shader and the particle texture later on, but for now I will concentrate on the loading of our particles. We are also setting up some of the particle physics variables ready for use. Also, at the top of the method we will setup the vertex declaration on the graphics device.

    protected override void LoadContent()
    {
        game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(game.GraphicsDevice, PointSpriteElement.VertexElements);
    
        shader = game.Content.Load<Effect>("Shaders/PointSpriteParticleShader");
        shader.Parameters["particleTexture"].SetValue(game.Content.Load<Texture2D>("Textures/particle"));
        
        targetPos = myPosition;
        myLastpos = targetPos;
    
        LoadParticles();
    }

    I have put the loading of particles into a separate method as you might want to call it again at a later date. So our method to load the particle array is going define the size of out particle array, and set each particle up ready for use in the system. Now in here if you were using it for say a weather effect like rain or snow you would want to set the positions to random values in the scene, as I say it all depends on what you want the effect to achieve.

    My LoadParticles method looks like this

    private void LoadParticles()
    {
        particleArray = new PointSpriteElement[partCount];
    
        for (int i = 0; i < particleArray.Length; i++)
        {
            particleArray[i].Position = myPosition;
            particleArray[i].Color = Color.Black;
            particleArray[i].SpriteSize = 1f;                
        }
    }

    Pretty simple stuff, we are setting the position of each particle to the emitters position, then (as in this example we are going to do additive blending and so the alpha value is redundant, but will show that in the next tutorial) setting the particle color to black and it's size to 1.

    Now for the fun bit, this is where the behaviour of your particle emitter will be defined. In this tutorial we are doing a trail so we have a target position we are chasing, we need to know what the targets last position was, so that too is stored as well as the current particle we want to work with. I have been terming this particle physics, this is a very lose term, what I really mean is particle behaviour. In this sample we are doing all the particle physics on the CPU, in a later tutorial I will show how you can move this to the GPU.

    So here is the work horse of the emitter, the Update override.

    public override void Update(GameTime gameTime)
    {
        for (int p = 0; p < particleArray.Length; p++)
        {
            if (p == nextParticle && myLastpos != myPosition)
            {
                particleArray[p].Position = myLastpos;
                particleArray[p].Color = particleColor;                        
            }                
            particleArray[p].SpriteSize = 1 - (Vector3.Distance(particleArray[p].Position, targetPos)/25);
        }
        nextParticle++;
    
        if (nextParticle >= particleArray.Length)
            nextParticle = 0;
    
        myLastpos = targetPos;
        targetPos = new Vector3((float)Math.Cos(gameTime.TotalGameTime.TotalSeconds) * 10, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds) * 10, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds));
    }

    All we are doing here is moving through our particle array, finding the particle we want to work with and setting it's new position and color, also we are sizing the particle based on how far it is from the target so giving a tapering effect to the trail. We then store the last position of the target and (as this is a tutorial and I don't want to code another object to use as a target) we move the target.

    And now onto the draw method. This is where we are going to define out blending method, in this tutorial, additive blending. We are also setting up a few parameters in the shader, but I will explain those in the shader code it's self in a short while.

    public override void Draw(GameTime gameTime)
    {
        bool PointSpriteEnable = game.GraphicsDevice.RenderState.PointSpriteEnable;
    
        float PointSize = game.GraphicsDevice.RenderState.PointSize;
    
        bool AlphaBlendEnable = game.GraphicsDevice.RenderState.AlphaBlendEnable;
        Blend DestinationBlend = game.GraphicsDevice.RenderState.DestinationBlend;
        Blend SourceBlend = game.GraphicsDevice.RenderState.SourceBlend;
        bool DepthBufferWriteEnable = game.GraphicsDevice.RenderState.DepthBufferWriteEnable;
        BlendFunction BlendFunc = game.GraphicsDevice.RenderState.BlendFunction;
    
        game.GraphicsDevice.RenderState.PointSpriteEnable = true;
    
        game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
        game.GraphicsDevice.RenderState.SourceBlend = Blend.One;
        game.GraphicsDevice.RenderState.DestinationBlend = Blend.One;
    
        game.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
    
        Matrix wvp = (Matrix.CreateScale(myScale) * Matrix.CreateFromQuaternion(myRotation) * Matrix.CreateTranslation(myPosition)) * Camera.myView * Camera.myProjection;
    
        shader.Parameters["Projection"].SetValue(Camera.myProjection);
        shader.Parameters["ViewportHeight"].SetValue(Camera.myViewport.Height);
        shader.Parameters["WorldViewProj"].SetValue(wvp);
    
        shader.Begin();
        for (int ps = 0; ps < shader.CurrentTechnique.Passes.Count; ps++)
        {
            shader.CurrentTechnique.Passes[ps].Begin();
            game.GraphicsDevice.DrawUserPrimitives<PointSpriteElement>(PrimitiveType.PointList, particleArray, 0, particleArray.Length);
            shader.CurrentTechnique.Passes[ps].End();
        }
        shader.End();
    
        game.GraphicsDevice.RenderState.PointSpriteEnable = PointSpriteEnable;
    
        game.GraphicsDevice.RenderState.AlphaBlendEnable = AlphaBlendEnable;
    
        game.GraphicsDevice.RenderState.DestinationBlend = DestinationBlend;
        game.GraphicsDevice.RenderState.SourceBlend = SourceBlend;
    
        game.GraphicsDevice.RenderState.BlendFunction = BlendFunc;
    
        game.GraphicsDevice.RenderState.DepthBufferWriteEnable = DepthBufferWriteEnable;
    
        base.Draw(gameTime);
    }     

    So our emitter class now looks like this

    public class PointSpriteParticleEmitter : DrawableGameComponent
    {
        public PointSpriteElement[] particleArray;
    
        public Vector3 myPosition;
        public Vector3 myScale;
        public Quaternion myRotation;
    
        public Color particleColor;
        
        public int partCount;
    
        Effect shader;
    
        Game game;
    
        int nextParticle = 0;
        Vector3 targetPos;
        Vector3 myLastpos;
    
        public PointSpriteParticleEmitter(Game game, int particleCount) : base(game)
        {
            this.game = game;
            myPosition = Vector3.Zero;
            myScale = Vector3.One;
            myRotation = new Quaternion(0, 0, 0, 1);
    
            partCount = particleCount;
    
            particleColor = Color.White;
        }
        
        protected override void LoadContent()
        {
            game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(game.GraphicsDevice, PointSpriteElement.VertexElements);
    
            shader = game.Content.Load<Effect>("Shaders/PointSpriteParticleShader");
            shader.Parameters["particleTexture"].SetValue(game.Content.Load<Texture2D>("Textures/particle"));
            
            targetPos = myPosition;
            myLastpos = targetPos;
    
            LoadParticles();
        }
    
        private void LoadParticles()
        {
            particleArray = new PointSpriteElement[partCount];
    
            for (int i = 0; i < particleArray.Length; i++)
            {
                particleArray[i].Position = myPosition;
                particleArray[i].Color = Color.Black;
                particleArray[i].SpriteSize = 1f;                
            }
        }
        
        public override void Update(GameTime gameTime)
        {
            for (int p = 0; p < particleArray.Length; p++)
            {
                if (p == nextParticle && myLastpos != myPosition)
                {
                    particleArray[p].Position = myLastpos;
                    particleArray[p].Color = particleColor;                        
                }                
                particleArray[p].SpriteSize = 1 - (Vector3.Distance(particleArray[p].Position, targetPos)/25);
            }
            nextParticle++;
    
            if (nextParticle >= particleArray.Length)
                nextParticle = 0;
    
            myLastpos = targetPos;
            targetPos = new Vector3((float)Math.Cos(gameTime.TotalGameTime.TotalSeconds) * 10, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds) * 10, (float)Math.Sin(gameTime.TotalGameTime.TotalSeconds));
        }
        public override void Draw(GameTime gameTime)
        {
            bool PointSpriteEnable = game.GraphicsDevice.RenderState.PointSpriteEnable;
    
            float PointSize = game.GraphicsDevice.RenderState.PointSize;
    
            bool AlphaBlendEnable = game.GraphicsDevice.RenderState.AlphaBlendEnable;
            Blend DestinationBlend = game.GraphicsDevice.RenderState.DestinationBlend;
            Blend SourceBlend = game.GraphicsDevice.RenderState.SourceBlend;
            bool DepthBufferWriteEnable = game.GraphicsDevice.RenderState.DepthBufferWriteEnable;
            BlendFunction BlendFunc = game.GraphicsDevice.RenderState.BlendFunction;
    
            game.GraphicsDevice.RenderState.PointSpriteEnable = true;
    
            game.GraphicsDevice.RenderState.AlphaBlendEnable = true;
            game.GraphicsDevice.RenderState.SourceBlend = Blend.One;
            game.GraphicsDevice.RenderState.DestinationBlend = Blend.One;
    
            game.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
    
            Matrix wvp = (Matrix.CreateScale(myScale) * Matrix.CreateFromQuaternion(myRotation) * Matrix.CreateTranslation(myPosition)) * Camera.myView * Camera.myProjection;
    
            shader.Parameters["Projection"].SetValue(Camera.myProjection);
            shader.Parameters["ViewportHeight"].SetValue(Camera.myViewport.Height);
            shader.Parameters["WorldViewProj"].SetValue(wvp);
    
            shader.Begin();
            for (int ps = 0; ps < shader.CurrentTechnique.Passes.Count; ps++)
            {
                shader.CurrentTechnique.Passes[ps].Begin();
                game.GraphicsDevice.DrawUserPrimitives<PointSpriteElement>(PrimitiveType.PointList, particleArray, 0, particleArray.Length);
                shader.CurrentTechnique.Passes[ps].End();
            }
            shader.End();
    
            game.GraphicsDevice.RenderState.PointSpriteEnable = PointSpriteEnable;
    
            game.GraphicsDevice.RenderState.AlphaBlendEnable = AlphaBlendEnable;
    
            game.GraphicsDevice.RenderState.DestinationBlend = DestinationBlend;
            game.GraphicsDevice.RenderState.SourceBlend = SourceBlend;
    
            game.GraphicsDevice.RenderState.BlendFunction = BlendFunc;
    
            game.GraphicsDevice.RenderState.DepthBufferWriteEnable = DepthBufferWriteEnable;
    
            base.Draw(gameTime);
        }     
    }

    Now we have a particle system we need to implement it, as we have derived our emitter from DrawableGameComponent this is pretty easy. We just create an instance of the object and add it to the game components like this

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    
        PointSpriteParticleEmitter emitter1 = new PointSpriteParticleEmitter(this, 100);
        emitter1.myPosition = new Vector3(0, 0, -20);
        Components.Add(emitter1);
    }

    As you can see I have created an emitter with 100 particles in it and placed it 20 units in front of the Camera (see sample download for Camera code)

    HLSL

    OK, now it's time for the shader. I have adapted this from the shader that can be found in my previous 3D particle sample. It is pretty simple, we have a texture to use for the particle, two matrices for world view projection and projection, and view port height, used to calculate the particles size.

    In the other particle sample the shader is written so it can be used on the PC and the XBox 360, as this it a tutorial, I have removed the XBox 360 elements so the shader is easier to read.

    I have created one data structure for passing data from the application to the Vertex Shader and one to pass data from the Vertex Shader to the Pixel Shader. As you can see the former matches the structure we created in our PointSpriteElement structure (Now I am still pretty new to this, but you will notice the color element in out application structure is represented by a single float, yet in the shader it is 4, if I set the application structure up so the color is size 4*4 rather 1*4 then I get some odd results...)

    So the structures looks like this

    struct VS_OUTPUT
    {
        half4 Position : POSITION0;
        half2 TexCoord : TEXCOORD0;
        half4 Color : COLOR0;
        half psize : PSIZE0;
    };
    
    struct VS_INPUT
    {
        half4 pos : POSITION0;
        half4 color : COLOR0;
        half2 data : TEXCOORD0;
    };

    Our Vertex Shader looks like this

    VS_OUTPUT VertexShader(VS_INPUT input)
    {
        VS_OUTPUT Output = (VS_OUTPUT)0;
        
        Output.Position = mul(input.pos, WorldViewProj);    
        
        Output.Color = input.color;    
        
        Output.Color.a = input.data.y;                
        
        Output.psize = input.data.x * Projection._m11 / Output.Position.w * ViewportHeight / 2;
        
        return Output;
    }

    So in here we tell the Vertex Shader to expect out VS_INPUT structure as the incoming parameters and that it is going to return a VS_OUTPUT structure. We create a VS_OUTPUT structure and initalize it setting all the values to 0. We then calculate the position of the vertex in the world and load it into our return structure, then load the color, color alpha and the particle size and finally return the structure to the calling pass.

    Our Pixel Shader looks like this

    half4 PixelShader(VS_OUTPUT input) : COLOR0
    {
        half4 Color = tex2D(Sampler, input.TexCoord.xy);
        Color *= input.Color;   
        return Color;   
    }

    In this Pixel Shader we tell it to expect a VS_OUITPUT structure as the input from the Vertex Shader and that is will return a half4 and that this half4 is a COLOR. We get the color of the pixel ath this TexCoord, multiply it by the color we want to tint the texture by and then pass it out to the calling pass.

    So the complete shader looks like this

    texture particleTexture;
    sampler Sampler = sampler_state
    {
        Texture = <particleTexture>;
        MinFilter = Linear;
        MagFilter = Linear;
        MipFilter = Linear;
    };
    
    half4x4 WorldViewProj : WorldViewProjection;
    half4x4 Projection : Projection;
    
    half ViewportHeight;
    
    struct VS_OUTPUT
    {
        half4 Position : POSITION0;
        half2 TexCoord : TEXCOORD0;
        half4 Color : COLOR0;
        half psize : PSIZE0;
    };
    
    struct VS_INPUT
    {
        half4 pos : POSITION0;
        half4 color : COLOR0;
        half2 data : TEXCOORD0;
    };
    
    VS_OUTPUT VertexShader(VS_INPUT input)
    {
        VS_OUTPUT Output = (VS_OUTPUT)0;
        
        Output.Position = mul(input.pos, WorldViewProj);    
        
        Output.Color = input.color;    
        
        Output.Color.a = input.data.y;                
        
        Output.psize = input.data.x * Projection._m11 / Output.Position.w * ViewportHeight / 2;
        
        return Output;
    }
    half4 PixelShader(VS_OUTPUT input) : COLOR0
    {
        half4 Color = tex2D(Sampler, input.TexCoord.xy);
        
        Color *= input.Color;    
        
        return Color;    
    }
    technique PointSpriteTechnique
    {
        pass P0
        {   
            vertexShader = compile vs_2_0 VertexShader();
            pixelShader = compile ps_2_0 PixelShader();        
        }
    }

    I guess that brings this first tutorial to a close, hope you find it of help and has made particles a little clearer. As I say at the top, I am no expert, but this is how I am implementing PointSprite particles and it seems to be doing the job for me.

    If you want the example source for this tutorial you can find it here.

  • 3D Clouds in XNA - Update

    http://www.youtube.com/v/DNz_VdqHG_E <p><a href="http://www.youtube.com/v/DNz_VdqHG_E">http://www.youtube.com/v/DNz_VdqHG_E</a></p>  

    Just posting a new clip of the cloud system I am playing with. As you can see using billboards gives a better effect when close to the clouds and/or passing through them.

    Need to sharpen up the shader now and get some nice lighting in there as well as derived cloud classes for cloud types, at the moment the textures are picked randomly from the sprite sheet but need to some up with some nice cloud types using the sprite sheet.

    Oh, and Happy Easter all, don't eat too many eggs.....

  • 3D Clouds in XNA

    Well, I was asked by a member of our comunity (Jonathan Tan) to comment my skysphere cloud shader a little better, and he also mentioned to me a system written for Microsoft Flight Simulator 2004: A Century of Flight by Niniane Wang, so I took a look and was totaly blown away by it. So decided to try and come up with an XNA version of it.

    Now all I have to go on is my amature XNA skills and the description given by Niniane in her video, I also found on her site her full paper of the system wich gave me some of the sprite textures which I took and modified a few of them for what you will see here.

    So what I am putting up here is three clips showing the progress of this project so far, now I think it is looking quite cool, but still needs a fair bit of work. I think I will put this with the skysphere sample when I put the code up as I think they will play welltogether. Anyway, as ever your comments are welcome.

    http://www.youtube.com/v/qRMO_VlJ9zw <p><a href="http://www.youtube.com/v/qRMO_VlJ9zw">http://www.youtube.com/v/qRMO_VlJ9zw</a></p> http://www.youtube.com/v/QOUyCXDcjOI <p><a href="http://www.youtube.com/v/QOUyCXDcjOI">http://www.youtube.com/v/QOUyCXDcjOI</a></p> http://www.youtube.com/v/W4gz-tAm4nM <p><a href="http://www.youtube.com/v/W4gz-tAm4nM">http://www.youtube.com/v/W4gz-tAm4nM</a></p>

  • Software License

    I have had a few people ask me now, "what license is your source released under?" and I always answer "eh?". So I have decided to take a look at a license for my downloads and have come across this one thanks to Amnesiasoft who posted it up on the HazyMind forum.

    It's called the BSD License and can be found here.

    The license will read:

    * Copyright (c) 2008, Charles Humphrey http://xna-uk.net/blogs/randomchaos/default.aspx
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions are met:
    *     * Redistributions of source code must retain the above copyright
    *       notice, this list of conditions and the following disclaimer.
    *     * Redistributions in binary form must reproduce the above copyright
    *       notice, this list of conditions and the following disclaimer in the
    *       documentation and/or other materials provided with the distribution.
    *     * Neither the name of the RandomChaos nor the
    *       names of its contributors may be used to endorse or promote products
    *       derived from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY CHARLES HUMPHREY ``AS IS'' AND ANY
    * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL CHARLES HUMPHREY BE LIABLE FOR ANY
    * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

    This applies to ALL RandomChaos downloads. I will start putting this license in with my zips too.

    As you can see it is a pretty open license, and I think it fits the sort of stuff I release here. If you have any issues or questions about this, please let me know.

  • Geographic Grid Registration - An alternative to Quadtrees and Octrees

    I guess you know what Octrees and Quadtrees are so wont go into too much detail on them here, but they are basically a great way to hold static (none moving) game objects in groups for the use of culling and the like. As stated this is great for game objects that don't move, terrain, buildings and trees etc... So what you could do is only draw the objects that are in your node of the tree and so you don't have to send the every object in the game to the GPU, just the ones in your bit. This is great for none moving object as the tree places the objects in the correct node as they are added, but if it moves position and into an adjacent node you have to re build the tree as it is based on a maximum number of objects in a node and so can result in a rebuild of the tree each time objects move.

    Geographic Grid Registration (GGR) I think is a good alternative to this as it will handle both static and dynamic game objects. What it does is split the game world up into a grid, objects then register and un-register in the grid nodes as they move between them. So all I have to do is request all the objects that are in my node (or the nodes I can see) from the GGR system. This reduces the number of objects you need to check against for collision, LOS and even culling.

    For example, if you have 10 objects in the game a LOS or collision check will require you to make 10 * 9 checks, 100 would result in 100 * 99 and so on, so not a great way to go. With GGR you may only have 10 of the 100 objects in your node and so you only need to many 90 checks rather than 999000 checks.

    So I have decide to have a go at writing one and this is my first version, as ever I don't think it is perfect, but it does the job. I have written 2 types of GGR, a 3D and a 2D version, the principles are exactly the same so I will just describe the 3D version here. The only real difference is naturally the coordinate system; Vector3 as opposed to Vector2, and the bounds checking; BoundingBox rather than Rectangles.

    So to the code, first off we need a base class that our game objects can derive from and so be used by the GGR system, the base class for this I have called GridObject3D, this object has all the basics needed, position,scale, and so we know if it has moved or not a last position and a field that gets set if they are not the same HasMoved. In this example it also has methods to draw it's bounds.

    GridObject3D

    public class GridObject3D
    {
        BasicEffect shader;
    
        public Color boxColor = Color.Red;
    
        private Vector3 lastPos;
        public Vector3 Position;
        public Vector3 Scale;
        public bool HasMoved;
        public Model Mesh;
    
        protected VertexPositionColor[] points;
        protected short[] index;
    
        private BoundingBox myDrawBounds;
        public List<BoundingBox> Bounds
        {
            get
            {
                if (Mesh != null)
                {
                    List<BoundingBox> bounds = (List<BoundingBox>)((object[])Mesh.Tag)[0];
                    List<BoundingBox> redBounds = new List<BoundingBox>(bounds.Count);
                    for (int b = 0; b < bounds.Count; b++)
                        redBounds.Add(new BoundingBox((bounds[b].Min * Scale) + Position, (bounds[b].Max * Scale) + Position));
    
                    return redBounds;
                }
                else
                {
                    List<BoundingBox> bounds = new List<BoundingBox>();
                    bounds.Add(new BoundingBox(-Vector3.One + Position, Vector3.One + Position));
    
                    return bounds;
                }
            }
        }
    
        public void Update(GameTime gameTime)
        {
            if (lastPos != Position)
                HasMoved = true;
            else
                HasMoved = false;
    
            lastPos = Position;
    
            float ang = (float)gameTime.TotalGameTime.TotalSeconds;
            //ang = 10;
            float x = ((float)Math.Cos(ang)/10);
            float z = ((float)Math.Sin(ang)/10);
    
            Position += new Vector3(x, 0, z);   
        }
        
        public GridObject3D()
        { 
        
        }
        public void DrawBounds(GraphicsDevice myDevice, List<BoundingBox> bounds)
        {
            if(shader == null)
                shader = new BasicEffect(myDevice, null);
    
            for (int b = 0; b < bounds.Count; b++)
            {
                myDrawBounds = bounds[b];
                BuildBoxCorners();
    
                myDevice.VertexDeclaration =