Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am trying to create a little fun 3D game in XNA, but I am having some problems with scaling my models. I use models from random sites, so my battleship is for an example 10 times larger than my planet.

I thought I had found out how to scale my model, but it does not show up when I do, or the coordinates get really messed up. Is there a way to scale my models but still keep the same position system?

Here is my model base class.

public class BaseModel
{
    protected Matrix world = Matrix.Identity;
    protected Matrix RotationMatrix = Matrix.Identity;
    protected Model model;
    protected float scale = 1.0f;
    protected Vector3 direction;

    public Vector3 Position
    {
        get
        {
            return world.Translation;
        }
        set
        {
            world = Matrix.CreateTranslation(value);
        }
    }

    public BaseModel(Model model, Vector3 position, float scale = 1)
        : this(model, position, Vector3.Zero, Matrix.Identity, scale)
    {
    }
    public BaseModel(Model model, Vector3 position, Vector3 direction, float scale = 1)
        : this(model, position, direction, Matrix.Identity, scale)
    {
    }
    public BaseModel(Model model, Vector3 position, Vector3 direction, Matrix rotationMatrix, float scale = 1)
    {
        this.model = model;
        this.Position = position;
        this.direction = direction;
        this.RotationMatrix = rotationMatrix;
        this.scale = scale;
    }

    public virtual void Update(GameTime gameTime)
    {
        world *= Matrix.CreateTranslation(direction);
    }

    public virtual void Draw(GameTime gameTime, Camera camera)
    {
        Matrix[] modelTransforms = new Matrix[model.Bones.Count];
        model.CopyAbsoluteBoneTransformsTo(modelTransforms);
        Matrix wworld = GetWorld();

        foreach (ModelMesh mesh in model.Meshes)
        {
            foreach (BasicEffect effect in mesh.Effects)
            {
                effect.EnableDefaultLighting();
                effect.World = modelTransforms[mesh.ParentBone.Index] * wworld;
                effect.View = camera.view;
                effect.Projection = camera.projection;
            }
            mesh.Draw();
        }
    }

    public virtual Matrix GetWorld()
    {
        return RotationMatrix * world * Matrix.CreateScale(scale);
    }

    public virtual Model GetModel()
    {
        return model;
    }

    public virtual bool CollidesWith(Model otherModel, Matrix otherWorld)
    {
        // Loop through each ModelMesh in both objects and compare
        // all bounding spheres for collisions
        foreach (ModelMesh myModelMeshes in model.Meshes)
        {
            foreach (ModelMesh hisModelMeshes in otherModel.Meshes)
            {
                if (myModelMeshes.BoundingSphere.Transform(
                    GetWorld()).Intersects(
                    hisModelMeshes.BoundingSphere.Transform(otherWorld)))
                    return true;
            }
        }
        return false;
    }
}
share|improve this question
    
Is there a reason for the scale to be in the world matrix and not in the model matrix? I suggest simply putting return Matrix.CreateScale(scale) * model; in GetModel(). –  Sam Hocevar May 12 '12 at 12:00
    
@SamHocevar Model is not a matrix. It's a XNA class that represents a collection of 3D meshes and bones. –  David Gouveia May 13 '12 at 14:40
    
The world variable has a misleading name, and from the context, I'd recommend changing it to TranslationMatrix instead. –  David Gouveia May 13 '12 at 14:43
add comment

2 Answers

Try Scale * rotate * translate

public virtual Matrix GetWorld()
{
    return Matrix.CreateScale(scale) * RotationMatrix * world; 
}

when scale is after translate, it scales the translation values. Think SRT when building a final matrix.

share|improve this answer
add comment

Swap the order of multiplication in the GetWorld method so that the scale comes first:

public virtual Matrix GetWorld()
{
    return Matrix.CreateScale(scale) * RotationMatrix * world;
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.