XNA Sphere

As mentioned in the previous post, this is bout creating a sphere in XNA.
I forgot to mention in my previous post, that these are useful for visualizing stuff in 3d world, this actually doesn't create surface - just lines.

I'll be using the Circle created in before to setup my sphere.

The funny thing about a sphere is that projection on any plane will always be a circle.Hence, when creating the circles we ensure that they lie on the circumference

Refer image below for clarity:




Here is the complete code:

//Generic Sphere for XNA Debugging / Visualizing.
//This is just a set of lines - no surface
//Author: Vikram N [ makubex ] 
//Blog: 8bitmemories.blogspot.com
public class Sphere
{        
//Color of the verttices
Color _VertexColor;
 
//List of Circles that make up the sphere
//Refer to post on Circles
List<Circle> _Verticals;
List<Circle> _Horizontals;
 
//Save original position
//Becomes easy to transform the sphere
Vector3[] _HBasePositions;
Vector3[] _VBasePositions;
 
//Main game reference
Game _Game;
BasicEffect _Effect;
 
//Not used
//NFS: May be useful someother day
Matrix _Transforms;
//Store pos, scale and rotation
//Only pos is useful. Others have not been implemented
//Rotation - no diff
//Scale - why dude..  create a new one with diff radius :P
Vector3 _Position, _Scale, _Rotation;
//Radius of the sphere
float _Radius;
 
public Vector3 Position
{
get
{
return _Position;
}
 
set
{
_Position = value;
Transform();
}
}
 
public Vector3 Rotation
{
get
{
return _Rotation;
}
 
set
{
_Rotation = value;
Transform();
}
}
 
public Vector3 Scale
{
get
{
return _Scale;
}
 
set
{
_Scale = value;
Transform();
}
}
 
public Matrix Transforms
{
get
{
return _Transforms;
}
 
set
{
_Transforms = value;
}
}
 
//No of circles to be used for creating the sphere
//Higher the number, better it looks
//10 seems to look nice :P
int LEVELS = 10;
//Constructor
public Sphere(Game game, Color color, float radius)
{
_Game = game;
_Effect = new BasicEffect(_Game.GraphicsDevice, null);
_Effect.VertexColorEnabled = true;
_VertexColor = color;
_Transforms = Matrix.Identity;
_Radius = radius;
 
_Verticals = new List<Circle>();
_Horizontals = new List<Circle>();
 
Setup();
}
 
//Function to create circles
void Setup()
{
float offset = _Radius / (float)LEVELS;
float rOffset = 90 / LEVELS;
//Add one on each side of the center
//For expln refer the blog - 8bitmemories.blogspot.com
for (int i = 0; i <= LEVELS; i++)
{        
Circle tmpPos = new Circle(_Game, _VertexColor, _Radius * (float) Math.Cos(MathHelper.ToRadians(i*rOffset)));
tmpPos.Position = new Vector3(0, _Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)), 0);
 
Circle tmpNeg = new Circle(_Game, _VertexColor, _Radius * (float)Math.Cos(MathHelper.ToRadians(i * rOffset)));
tmpNeg.Position = new Vector3(0, -_Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)), 0);
 
_Verticals.Add(tmpPos);
_Verticals.Add(tmpNeg);
}
 
//Same logic but set rotation of 90 degrees on z axis
for (int i = 0; i <= LEVELS; i++)
{
Circle tmpPos = new Circle(_Game, _VertexColor, _Radius * (float)Math.Cos(MathHelper.ToRadians(i * rOffset)));
tmpPos.Position = new Vector3(_Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)), 0, 0);
tmpPos.Rotation = new Vector3(0, 0, MathHelper.PiOver2);
 
Circle tmpNeg = new Circle(_Game, _VertexColor, _Radius * (float)Math.Cos(MathHelper.ToRadians(i * rOffset)));
tmpNeg.Position = new Vector3( -_Radius * (float)Math.Sin(MathHelper.ToRadians(i * rOffset)),0,  0);
tmpNeg .Rotation = new Vector3(0, 0, MathHelper.PiOver2);
 
_Horizontals.Add(tmpPos);
_Horizontals.Add(tmpNeg);
}
 
//Save original positions 
//Useful for translation        
_HBasePositions = _Horizontals.Select(x => x.Position).ToArray();
_VBasePositions = _Verticals.Select(x => x.Position).ToArray();
 
}
 
//Move the sphere
void Transform()
{
//Not used 
_Transforms = Matrix.CreateScale(_Scale) * Matrix.CreateFromYawPitchRoll(_Rotation.Y, _Rotation.X, _Rotation.Z) * Matrix.CreateTranslation(_Position);
 
//Use the base positions + translation value
for (int i = 0; i < _Verticals.Count; i++)
{
_Verticals[i].Position = _VBasePositions[i] + _Position;
}
 
for (int i = 0; i < _Horizontals.Count; i++)
{
_Horizontals[i].Position = _HBasePositions[i] + _Position;
}
}
 
//Draw spheres
public void Draw()
{
//Draw horizontal and vertical circles
for (int i = 0; i < _Verticals.Count; i++)
{
_Verticals[i].Draw();
}
 
for (int i = 0; i < _Horizontals.Count; i++)
{
_Horizontals[i].Draw();
}
}
}

Screen shots:


Pretty Ok for debugging I think.
NFS: I get confused with sin and cos!Hope you've learnt something in the future!

Simple Circle in XNA


This post is about creating a simple circle in XNA using VertexPositionColor elements and LineStrip primitive.
Lets call our class Circle.

Members:
//List of vertices
List<VertexPositionColor> _Vertices;
 
//Convert to array to avoid ToArray for every draw
VertexPositionColor[] _VertexArray;
 
//Color of the vertices
Color _VertexColor;
 
//Main game class
Game_Game;
BasicEffect _Effect;
 
//Transforms for the circle
Matrix _Transforms;
Vector3 _Position, _Scale, _Rotation;
 
//Radius of the circle
float _Radius;

Properties:
public Vector3 Position
{
get{ return_Position; }
set{_Position=value;Transform();}
}
 
public Vector3 Rotation
{
get{return_Rotation;}
set{_Rotation=value;Transform();}
}
 
public Vector3 Scale
{
get{return_Scale;}
set{_Scale=value;Transform();}
}
 
public MatrixTransforms
{
get{return_Transforms;}
set{_Transforms=value;}
}


Constants:
//This indicates that every 5 degree 
//a point on the cirumference will be added
//Ex: 360/5 = 72 points will be used
int DEGREE_INCREMENT = 5;

Constructor:
public Circle(Game game, Color color, float radius)
{
_Game = game;
_Effect = new BasicEffect(_Game.GraphicsDevice, null);
_Effect.VertexColorEnabled = true;
_VertexColor = color;
_Transforms = Matrix.Identity;
_Radius = radius;
_Scale = Vector3.One;
 
_Vertices = new List<VertexPositionColor>();
Setup();
 
_VertexArray = _Vertices.ToArray();
}

Setup Function:
void Setup()
{
//For each number of points : 360/ DEGREE_INCREMENT
for (int i = 0; i <= 360; i+= DEGREE_INCREMENT)
{
VertexPositionColor tmp = new VertexPositionColor();
 
// X => R * Cos(Angle), Y = 0, Z => R * Sin(Angle)
tmp.Position = new Vector3(_Radius * (float)Math.Cos(MathHelper.ToRadians(i)), 0, _Radius * (float)Math.Sin(MathHelper.ToRadians(i)));
tmp.Color = _VertexColor;
_Vertices.Add(tmp);                
} 
}

Transform Function:
//Update transform when pos, rot, scale is changed
void Transform()
{
_Transforms = Matrix.CreateScale(_Scale) * 
Matrix.CreateFromYawPitchRoll(_Rotation.Y, _Rotation.X, _Rotation.Z) * 
Matrix.CreateTranslation(_Position);
}

Draw Function:
public void Draw()
{
//Tell the device we are sending Vertexpositioncolor elements
_Game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(_Game.GraphicsDevice, VertexPositionColor.VertexElements);
_Effect.Begin();
foreach (EffectPass pass in _Effect.CurrentTechnique.Passes)
{
pass.Begin();
 
//Set the world, view, projection matrices
_Effect.World = _Transforms;
_Effect.View = Camera.View;
_Effect.Projection = Camera.Projection;
 
//Draw primitive: n points => n-1 lines
_Game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineStrip, _VertexArray, 0, _Vertices.Count - 1);
pass.End();
}
 
_Effect.End(); 
}

Screen shots with different Degree increments:


Next up - Sphere

Simple Grid in XNA

I created a simple Grid-Display system for debugging my games.
Pretty useful when I want to know the position of any object in the game.
It helps a lot in visualization.

Required class members:
public int Width;
public int Height;
public int Rows;
public int Columns;
public Vector3 Position;
List<VertexPositionColor> vertices;
BasicEffect effect;
Game game;

Constructor:
public Grid(Vector3 Position, int Width, int Height, int Rows, int Columns, Game game)

Constructor logic:
this.game = game;
effect = new BasicEffect(game.GraphicsDevice, null);
effect.VertexColorEnabled = true;  
this.Width = Width;
this.Height = Height;
this.Rows = Rows;
this.Columns = Columns;
this.Position = Position;
vertices = new List<VertexPositionColor>();
int xDiff = this.Width / this.Columns;
int zDiff = this.Height / this.Rows;
float xBase = this.Position.X - this.Width/ 2f;
float zBase = this.Position.Z - this.Height / 2f;
float yBase = this.Position.Y;
for (int i = 0; i <= this.Rows;i++)
{
   vertices.Add(new VertexPositionColor(new Vector3(xBase + i * xDiff, yBase, zBase), Color.Green));   vertices.Add(new VertexPositionColor(new Vector3(xBase + i * xDiff, yBase, zBase + this.Height), Color.Green));
}
for (int i = 0; i <= this.Columns;i++)
{
   vertices.Add(new VertexPositionColor(new Vector3(xBase, yBase, zBase + i* zDiff), Color.Green));
   vertices.Add(new VertexPositionColor(new Vector3(xBase + this.Width, yBase, zBase + i * zDiff), Color.Green));
}

The Draw method:
public void Draw()
{
     game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(game.GraphicsDevice, VertexPositionColor.VertexElements);
     effect.Begin();
     foreach (EffectPass pass in effect.CurrentTechnique.Passes)
     {
        pass.Begin();
        effect.View = Camera.View;
        effect.Projection = Camera.Projection; 
        //Draw vertices as Primitive                 
       effect.End();
     }    
     effect.End();
}

To draw the lines:
game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor>(PrimitiveType.LineList,vertices.ToArray(),0,vertices.Count/2);

Logic explained:
Assume that the given position is the center of the Grid.
Grid extends on each side, i.e x and z axis by the amount width/2 and height/2.
The xDiff and xDiff are the distance between each column and row.
Start adding lines for each column and row.
Note the <= operator for the loop construct!

Game Completed!

Well, I completed my first game. Whew!!! Simple one.. but learnt a lot.
Based on the available tuts over net, I managed to add:
Ocean [ Shaders ]
Terrains
Collision detection [ Custom, no 3rd party engine ]
Cameras and lights
Skyboxes etc etc
UI Widgets 

Then I downloaded some XNA engines available over the web and discovered that in essence -
I had created my own mini - game engine!

I plan on posting some source-code and useful stuff when I find time. Right now I'm thinking of creating a Racing game.

NFS: The most painful thing in game-dev is debugging.