Moving Models

Nov 9, 2009 at 6:24 PM

Hey guys,

I'm just getting to grips with Xen, and the Xna thing in general. I've been going through example code and tutorials and the like, However I'm having an issue when i use xen.

In my little games I did using Xna, I could get my models to move very easily (mainly because I was just modifying the sample code given), but with xen, they just seem to stay in place, and never move.

Now I'm sure I'm just being very stupid here but I'd appreciate any help I can get :)

The jeepposition variable is getting updated, but when it comes to drawing the jeep at the new position, it isnt working.

 

Thanks in advance for any help :)

 

(the Actor & Class1 are the exact same as the actor class in tutorial 10 of the tutorials provided)

using System;
using System.Collections.Generic;
using System.Text;

using Xen;
using Xen.Camera;
using Xen.Graphics;
using Xen.Graphics.State;
using Xen.Ex.Graphics;
using Xen.Ex.Graphics2D;
using Xen.Ex.Material;
using Xen.Ex.Graphics.Content;
using Xen.Input.State;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace XenTestGame{
    public class Game : Application{
        private DrawTargetScreen drawToScreen;
        private Camera3D camera = new Camera3D();
        private Class1 Jeep;
        public Vector3 jeepPosition = new Vector3(0, 0, 4);
        private Vector3 planePosition = new Vector3(0, 0, 0);

        protected override void Initialise(){
            camera.LookAt(new Vector3(0, 0, 0), new Vector3(0, 15, 8), new Vector3(0, 0, 10));
            
            drawToScreen = new DrawTargetScreen(this, camera);
            drawToScreen.ClearBuffer.ClearColour = Color.CornflowerBlue;
            drawToScreen.Add(new Actor(this.Content, planePosition));
            
            Jeep = new Class1(this.Content, jeepPosition);
            
            drawToScreen.Add(Jeep);
        }
        
        protected override void Update(UpdateState state){
            KeyboardInputState keyboardState = state.KeyboardState;
            if (keyboardState.KeyState.B.IsDown)
                this.Shutdown();
            
            Vector3 jeepPositionAdd = Vector3.Zero;

            if (keyboardState.KeyState.W.IsDown)
                jeepPositionAdd.X += 100;
            if (keyboardState.KeyState.S.IsDown)
                jeepPositionAdd.X -= 100;
            if (keyboardState.KeyState.A.IsDown)
                jeepPositionAdd.Z += 100;
            if (keyboardState.KeyState.D.IsDown)
                jeepPositionAdd.Z -= 100;

            this.jeepPosition += jeepPositionAdd;
            
        }

        protected override void Draw(DrawState state){
            //Console.WriteLine(jeepPosition);
            drawToScreen.Draw(state);
        }
    }
}

Nov 9, 2009 at 6:53 PM

Hi there,

The Actor class in tutorial 10 has a constructor that looks like this:

 

public Actor(ContentRegister content, Vector3 position)
{
    Matrix.CreateTranslation(ref position, out this.worldMatrix);

    //A ModelInstance can be created without any content...
    //However it cannot be used until the content is set

    model = new ModelInstance();

    //add to the content register
    content.Add(this);
}

The relevant line here is the call to Matrix.CreateTranslation. This creates the World Matrix that the Actor uses to render itself (in this case I assume to render the jeep). However, you'll notice that there is nothing in the Actor class to update the world matrix when the jeepPosition is updated. So you'll probably want to write some kind of property in the Actor that sets the world matrix for you:

 

public Vector3 Position 
{
    get { /* do something here, if you like */ }
    set { worldMatrix = Matrix.CreateTranslation(value); }
}

And in when you update XnaTestGame.jeepPosition, you'll want to update your Class1.Position property. Something like:

 

protected override void Update(UpdateState state){
    KeyboardInputState keyboardState = state.KeyboardState;
    if (keyboardState.KeyState.B.IsDown)
        this.Shutdown();
            
    Vector3 jeepPositionAdd = Vector3.Zero;

    if (keyboardState.KeyState.W.IsDown)
        jeepPositionAdd.X += 100;
    /* more of the if key down, update position */

    this.jeepPosition += jeepPositionAdd;

    Jeep.Position = jeepPosition;
}

Hope that helps!

Cheers,

Noah Callaway

 

 

 

Nov 9, 2009 at 7:21 PM

Ah now I understand :) Thank you very much :)

Coordinator
Nov 9, 2009 at 11:47 PM

Hi :-)

ncallaway is exactly right. This is an aspect of .net (and programming) that can take a little bit of getting used to. Especially if you have come from java.
It's a hard one to explain, but the Vector3 is a structure - and in .net, a structure is 'pass by value'.

So, the call to the constructor:

new Class1(this.Content, jeepPosition);

the position is 'passed by value'. Ie, a copy of the position is passed into the constructor method. That is because it's a structure.
The 'Content' object is 'passed by reference'. (Note I said 'object' not 'structure'). This means the object itself is *not* copied, just the reference to the object is copied.

You may notice a lot of xen code uses the 'ref' keyword, for example:

state.PushWorldMatrix(ref worldMatrix);

This is an optimisation for the xbox .net runtime. When 'ref' is used on a structure (in this case, the world matrix) then the structure *is* passed by reference. So the value is *not* copied. This is because the runtime on the xbox doesn't perform inlining optimisations - and doesn't optimise out the copy. A Matrix is moderately large, so this memory copy (while small) would add up if happening thousands of time per frame.

You may have noticed, if you used 'ref' on an object, then you'd be passing a reference by reference... ;-) 

I highly recommend searching for copy by reference, etc, and figuring out the difference. It's a very critical concept and will help you out a lot. I've only just scratched the surface here.
For example, it would explain the *huge* difference between 'new' object and 'new' structure.

Start small, work from there.. 
Good luck.

Jun 15, 2010 at 7:02 PM

public Vector3 Position 
{
    get { /* do something here, if you like */ }
    set { worldMatrix = Matrix.CreateTranslation(value); }
}

What would go in the getter area here? Im just learning xen too.

Coordinator
Jun 16, 2010 at 9:32 AM
Edited Jun 16, 2010 at 9:33 AM

worldMatrix.Translation,

which internally means:

new Vector3(worldMatrix.M41, worldMatrix.M42, worldMatrix.M43);

 

I highly recommend learning about Homogeneous Matrices in computer graphics - it's a critical area to understanding the 3D pipeline.

I wrote up a very basic introduction a while ago. It's much deeper than that, but it gives you are good starting point.