xna

XNA MD2Model with Normal calculation

Ive been playing around with the excellent MD2Model class RCade provides on his blog(http://www.varcade.com/blog/).

I did some experiments (nothing too fancy) but I wanted to use dynamic lighting on some old doom 1 models I found on the internet. Unfortunately  I was not able to do so because I did not have access to the Normals on the mesh.

I did a little Google search (my math skills are a little rusty) and I refresh my mind on how normals are calculated so I patched the code to support them.

Continue reading “XNA MD2Model with Normal calculation”

phone7, xna

XNA – Your first Phone 7 Game in 3D !!!

Heiya guys ! I’ll post a small tutorial on how to compile your first 3d game on windows phone 7 (using the emulator).

First, you’ll need the developer tools WHICH ARE FREE !!! Get them RIGHT now:

http://www.microsoft.com/express/Phone/

Now, lets get this started. First open VS2010 and create a new Windows Game.

Camera

I’ve prepared a 3d camera suitable for a shooter. This means the camera is looking from upside down. You can feel free to use it in your projects. Here is the code:

   public static class Camera
   {
       public static Matrix World { get; private set; }
       public static Matrix View { get; set; }
       public static Matrix Projection { get; private set; }

       public static BoundingFrustum BoundingFrustum { get; private set; }

       public static Vector3 Position { get; set; }

       // needed attributes
       private static float nearClip = 1.0f;
       private static float farClip = 1000.0f;

       private static float aspectRatio = 800 / 600; // default aspect ratio
       public static float AspectRatio
       {
           get { return aspectRatio; }

           set
           {
               aspectRatio = value;
               UpdateMatrices();
           }

       }

       public static void Update()
       {
           UpdateMatrices();
       }

       public static void UpdateMatrices()
       {

           Matrix rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(90));
           Vector3 transformedReference = Vector3.Transform(Vector3.Forward, rotationMatrix);

           View = Matrix.CreateLookAt(Position, new Vector3(0, 0, 0), Vector3.Forward);
           Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, nearClip, farClip);
           World = Matrix.Identity;

           World = Matrix.Identity;

           BoundingFrustum = new BoundingFrustum(View * Projection);
       }
   }

The code is quite simple. The UpdateMatrices does all the work.  Notice I’ll I’m doing is transform the Forward vector with a 90 degrees angle. I know this is lame but I’ve choose this way to make it more graphical: In a normal FPS game you are pointing forward, if I rotate 90 degrees… well I know you get it 🙂

Note this:

Before we load the graphical device, we don’t know the viewport’s aspect ratio, so I’ve done it in a dynamic fashion, once you change the Camera’s ratio, it’ll recalculate the projection Matrix; this means you have to manually set the aspect ratio of the camera:

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            Camera.AspectRatio = GraphicsDevice.Viewport.AspectRatio;
        }

Also ! remember to update the camera !!

Model

Here is the great part. Nothing has changed ! You can draw your models just the way you did it in the XNA 3.1 versions.

In a few steps:

  1. Declare your model
  2. Load it (notice the changes in the Content directory)
  3. Transform it
  4. Draw it

The declaration is easy, but the process to add it to the project is a little bit different. Here is a screenshoot:

loadModel

To load it, we use the same procedure as before:

protected override void LoadContent()
{
    // Create a new SpriteBatch, which can be used to draw textures.
    spriteBatch = new SpriteBatch(GraphicsDevice);

    // TODO: use this.Content to load your game content here
    Camera.AspectRatio = GraphicsDevice.Viewport.AspectRatio;
    model = Content.Load<Model>("raptorxxi");
}

Here is our code to draw it (you can see the rest in the project).

/// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            // TODO: Add your drawing code here

            // Copy any parent transforms.
            Matrix[] transforms = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(transforms);

            // Draw the model. A model can have multiple meshes, so loop.
            foreach (ModelMesh mesh in model.Meshes)
            {
                // This is where the mesh orientation is set, as well 
                // as our camera and projection.
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.EnableDefaultLighting();
                    effect.View = Camera.View;
                    effect.World = transforms[mesh.ParentBone.Index] * Matrix.CreateTranslation(Vector3.Zero);
                    effect.Projection = Camera.Projection;
                }
                // Draw the mesh, using the effects set above.
                mesh.Draw();

            }

            base.Draw(gameTime);
        }

And there you go:

 final

Download the solution from HERE !!!!!

xna

Multiple textures (or materials) on models

Hi, this time I’ll play a little with effects (don’t worry, I’m awful at HLSL so this won’t be complicate).

Generally, the problem in multi texture effects is to decide “how much” of each material apply. There are hundreds of approaches and different algorithms. I’ll use a very simple one: We have two textures, a base texture (for example a base skin texture for a character) and a brush texture (lets say, a piece of cloth). The second texture is a transparent texture with some areas painted.

What we are going to do is, take the base texture, and remove the areas that are not transparent on the second one. Although this sound complicated, this is super easy to do. I’ll post some code of the .fx file now:

First, notice I’ll be using two samplers. One for each texture I’ll be using.

texture TextureMap;
sampler2D TextureMapSampler = sampler_state
{
    texture = (TextureMap);
    AddressU = WRAP;
    AddressV = WRAP;
    MinFilter = LINEAR;
    MipFilter = LINEAR;
    MagFilter = LINEAR;
};

texture Brush0;
sampler2D Brush0Sampler = sampler_state
{
    texture = (Brush0);
    AddressU = WRAP;
    AddressV = WRAP;
    MinFilter = LINEAR;
    MipFilter = LINEAR;
    MagFilter = LINEAR;
};

I’ll skip the vertex shader since it’s very simple. I’ll go straight to the algorithm:

  // this will remove part of the base texture in order to apply the second material
    float amount = 1 – tex2D(Brush0Sampler, input.UV).a;
   output = (tex2D(TextureMapSampler, input.UV)) * amount;
   output += (tex2D(Brush0Sampler, input.UV));  

As you see, it’s really simple. 1 means full color without transparency. I’m removing the amount of color of the second texture. Piece of cake !

Now some XNA – C# code. First I’m loading an effect and applying to the model. Since a lot of people don’t know how to do this I’ll pos it.

model = Content.Load<Model>("cube");
effect = Content.Load<Effect>("MultiTexture");

// apply the effect
foreach (ModelMesh mesh in model.Meshes)
{
    foreach (ModelMeshPart meshPart in mesh.MeshParts)
    {
        meshPart.Effect = effect;
    }
}

And now, the drawing part where we assign the textures:

Matrix View = Matrix.CreateLookAt(new Vector3(0, 2, -6), Vector3.Zero, Vector3.UnitX);

Matrix Projection = 
    Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, GraphicsDevice.Viewport.AspectRatio, 1, 100);

Matrix[] container = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(container);

foreach (ModelMesh mesh in model.Meshes)
{
    foreach (Effect effect in mesh.Effects)
    {
        effect.Parameters["view"].SetValue(View);
        effect.Parameters["projection"].SetValue(Projection);
        effect.Parameters["world"].SetValue(container[mesh.ParentBone.Index] 
            * Matrix.CreateRotationY(MathHelper.ToRadians(rotation)));

        effect.Parameters["TextureMap"].SetValue(baseTexture);
        effect.Parameters["Brush0"].SetValue(secondTexture);
    }
    mesh.Draw();
}  

And of course, here is the solution to download !

1254270360_page_white_visualstudio[2]

xna

Blender to XNA (fbx) – understanding the model

I’ll apologize for my English since it’s not my native language, but I’ll try to make myself as clear as possible.

Many people don’t understand very well the process (or at least the basics) of exporting a mesh to XNA from Blender. There are a few basic concepts that the user should know.

First, I’ll describe a scenario and then, I’ll enumerate what you should know: Suppose we have our game and we need a 3d object to be displayed. We all have done this in the past, but sometimes we just don’t understand why our object is not behaving the way it should we we apply a transformation. Even worse, some times we don’t even know where to place a camera because we don’t understand the “size” of the model.

I’ll try to explain those points here, I cannot assure I’ll be able to do it in a simple way, maybe because of my rusty english or maybe because it’s just a little hard (I’,m sure it’s because of my enlgish).

Object’s center position:

In blender, we you are creating or editing a model, you will notice a pink dot; This dot is used as reference to apply transforms. When you export the model to XNA, this little dot is also exported as a parent bone, and we apply a transformation this bone is also used as reference.

s1

For example, we have a scenario with a plane as a the floor placed in Y = 0 and we want to add a cube in some position, so we go to blender to create our cube:

In blender we add a cube to an empty project (as shown in the picture above) and we export it (without ANY modification), the reference point will be in the center of the volume. (Notice the pink dot in the screenshot above).

As I said before, our floor is at Y = 0, and we want the cube to be placed above the floor (the bottom face should be at Y = 0 too). To achieve this, we translate our cube to (2,0,1) . This position, should be above the floor, since our Y component is 0.

If we do such transformation, we’ll notice our cube is half above, half under the floor: this is because we have tell XNA to move THE PINK DOT to (2,0,1). If you understood all this, you already know how to fix this: We have to change the position of the pink dot in blender.

How to do this:

Create a cube in blender and be sure it’s on the 0,0,0 position. You can do this by selecting the cube and open the transform properties dialog (N shortcut). You’ll notice 3 fields: LocX, LocY and LocZ. Set them with 0 and you’ll have it centered.

Go to edit mode (TAB key) and  choose face as selection mode (Ctrl + Tab –> faces). Now select the bottom face:

s2 

Nothing strange so far, we have just added a new object (in this case a cube), we have centered it  and now we have selected a face we want as reference in our game.

Now, we are going to move that little dot from the center of the volume to the center of the bottom face: With the bottom face selected,  press SHIFT + S; this will bring the “align dialog” popup, Choose “Cursor –> Active”. You’ll notice that the cursor (not the pink dot) will be placed in the center of the bottom face.

Now, to translate the pink dot, exit edit mode (TAB key) and in the buttons window choose, in the Mesh tab choose “Center Cursor”. Now, you should have your reference centered in the bottom face.

s3

s4

Important !!!

Many people doesn’t know this, but when you modify a model, the transformations are not directly mapped to XNA. If you are noticing different units or scales ALWAYS apply all transformation to the model: Select the model and press Ctrl + A  + 1. You can also achieve this by selecting the model and from the menu go to:

Object –> Clear/Apply –> Apply Scale/rotation to Obj Data

About the size:

There seems to be a bug or something with the fbx exporter and objects are scaled 10 times from blender to XNA. To solve this, in the export window change the Scale to 0.01.

s5

Please notice that this can be applied to several type of objects. Characters and trees may have the reference under their feet but maybe planets or stars will be OK with their reference point in the center.

xna

XNA tutorial 3 – colisiones :serie 1:

En este artículo voy a comentar como estoy manejando la detección de colisiones con los limites del área dibujada.

Antes de empezar, hay que aclarar el concepto de “bounding frustum”. Básicamente y en cristiano es el área o volumen que estamos dibujando. Esta limitado por planos donde los mas importantes son el front y el back (que por ahora no vamos a usar). Para ver mejor el concepto pueden visitar esta dirección.

Este es el gráfico (el cual es bastante auto explicativo):

Bb195165.BoundingFrustum_ViewFrustum(en-us,XNAGameStudio.31)

La única diferencia es que nosotros tenemos girado todo 90º:

camaraOtro concepto que debemos conocer es el de Collision Sphere: esto es una esfera con el volumen suficiente para contener un modelo en tres dimensiones.  Lo bueno de utilizar este tipo de objetos para la detección de colisiones es que cuando rotamos o movemos el modelo, actualizar  la esfera es muy fácil (ya que no varía, es solo un punto y un radio). Un punto muy negativo es que para cálculos complejos no es precisa, pero para este ejemplo sobra.

El algoritmo para crearla se sitúa en el método load (necesitamos la información del modelo)

foreach (ModelMesh mesh in model.Meshes)
    collisionSphere = BoundingSphere.CreateMerged(collisionSphere, mesh.BoundingSphere);

Algoritmo

Como dije antes, el bounding frustum es un área delimitada por planos. Lo que vamos a hacer, utilizando métodos de las clases, es ver si existe una intersección entre la esfera (bounding sphere) que contiene a la nave y los limites del frutum. Esta prueba debemos hacerla en la próxima posición, por lo que creamos un vector y una esfera de prueba.

// control de posicion para la coordenada x
Vector3 collisionTestVector = Vector3.Zero;
BoundingSphere collisionTestSphere;

collisionTestVector.X = position.X + movement.X;
collisionTestVector.Z = position.Z;
collisionTestVector.Y = movement.Y;

collisionTestSphere = new BoundingSphere(collisionTestVector, collisionSphere.Radius);

if (Camera.BoundingFrustum.Contains(collisionTestSphere) == ContainmentType.Intersects)
    movement.X = 0;

Ese código muestra como fue realizado para la coordenada X. En el ejemplo esta también implementado para Z.

Desde este link pueden descargar la solución.

xna

XNA tutorial 2 – clase AirCraft

En el artículo anterior use un modelo para mostrar que la cámara funcionaba como era esperado, pero la forma de dibujarlo era desprolija y estaba dentro de la clase Game1. Hoy voy a separar esa información para tenerla ordenada y de paso discutir un poco la clase AirCraft que vendría siendo el avión que vamos a controlar.

Entre los atributos principales tenemos el modelo, la textura y la posición. Los demás atributos son secundarios (pero aún útiles) y están explicados en el código.

Estoy haciendo un esfuerzo y voy a dejar algunos comentarios en español (aunque parezca mentira me cuesta recordar esto), pero si algún lector tiene una duda puede preguntar vía comentario.

public class AirCraft
{
    private Model model;
    private Texture2D texture;
    private Vector3 position;

    private string modelAsset = "untitled";
    private string textureAsset = "Ship_06";

    private float speed = 20;

    public AirCraft(Vector3 position)
    {
        this.position = position;
    }

    public void Load(ContentManager content)
    {
        model = content.Load<Model>(modelAsset);
        texture = content.Load<Texture2D>(textureAsset);
    }

    public void Update(GameTime gameTime)
    {
        Vector3 movement = Vector3.Zero;

        // cuanto tiempo paso desde el ultimo frame hasta el actual
        float deltaT = (float)gameTime.ElapsedGameTime.TotalSeconds;
        /*
         * DeltaT sirve para calcular la cantidad de unidades que nos movemos en este frame.
         * Si decidimos que la velocidad de la entidad (nave) es de 1 metro por segundo,
         * hay que realizar una regla de tres
         * ya que en un segundo pueden entrar varios (muchos generalmente) frames.
         * */

        // actualizamos el vector movement que indica cuanto nos movemos en este frame particular
        if (Keyboard.GetState().IsKeyDown(Keys.Left))
            movement.X -= deltaT * speed;
        else if (Keyboard.GetState().IsKeyDown(Keys.Right))
            movement.X += deltaT * speed;

        // actualizamos la posicion
        position += movement;
    }

    public void Draw()
    {
        /*
         * Para dibujar el modelo copiamos sus transformaciones a una matriz.
         * Esto sirve para luego aplicar calculos matematicos a cada set de
         * transformaciones de cada mesh.
         * */

        Matrix[] contenedor = new Matrix[model.Bones.Count];
        model.CopyAbsoluteBoneTransformsTo(contenedor);

        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.World = contenedor[mesh.ParentBone.Index]
                    * Matrix.CreateTranslation(position);
                effect.View = Camera.View;
                effect.Projection = Camera.Projection;
                effect.TextureEnabled = true;
                effect.Texture = texture;
            }
            mesh.Draw();
        }
    }
}

La clase es bastante auto explicativa, pero si tienen dudas dejen el comentario.

Acá dejo la solución para que la descarguen.

xna

XNA – tutorial 1 – upside down camera

Introducción

La idea es hacer un juego de aviones tipo raptor (si, aquel que jugabamos en D.O.S.) pero realizado en 3D.

A diferencia de mis otros tutoriales, estos van a ser mucho mas complejos y apuntan a programadores con conocimientos avanzados de orientación a objetos y análisis matemático. Esta vez tengo novia, trabajo y vivo solo por lo tanto el tiempo escasea y no da para detenerme en tantas explicaciones. Lo siento…

Camara “Upside Down”

Como dije, la idea es un juego en 3d que se ve de arriba. A diferencia de los juegos en dos dimensiones, para dibujar modelos y objetos con volumen necesitamos una cámara virtual. La idea es mas o menos esta:

public static class Camera
{
    public static Matrix World { get; private set; }
    public static Matrix View { get; private set; }
    public static Matrix Projection { get; private set; }

    public static Vector3 Position { get; set; }

    // needed attributes
    private static float nearClip = 1.0f;
    private static float farClip = 1000.0f;
    private static float fov = MathHelper.PiOver4;

    private static float ratio = 800 / 600; // default aspect ratio
    public static float Ratio
    {
        get { return ratio; }
        set { ratio = value; }
    }

    // helper utils
    private static Matrix rotationMatrix = Matrix.CreateRotationX(MathHelper.ToRadians(90));

    public static void Update()
    {
        UpdateMatrices();
    }

    private static void UpdateMatrices()
    {
        Vector3 transformedReference = Vector3.Transform(Vector3.Forward, rotationMatrix);

        View = Matrix.CreateLookAt(Position + transformedReference, Vector3.Zero, Vector3.Up);
        Projection = Matrix.CreatePerspectiveFieldOfView(fov, ratio, nearClip, farClip);
        World = Matrix.Identity;
    }
}

El método UpdateMatrices es el mas importante. No tiene nada que no se haya visto anteriormente. Se genera una transformación en un vector y se gira 90 grados para poder ver el modelo desde arriba.

alert Nota: en el ejemplo deje algo de lógica para que vean la cámara en acción.

Ahora dejo como descarga el proyecto de prueba.

download

descargar ejemplo