CreateOrthographicOffCenter - Can't see anything

Started by
3 comments, last by basil4j 11 years, 11 months ago
Hi All,

I'm having a little trouble getting an Orthographic Camera working.

I'm trying to create isometric terrain for a tile based 2.5D Game using quads for the height mapped terrain

I am drawing a bunch of textured quads, and can view them at an arbitrary angle using CreatePerspectiveFieldofView, but when trying ortographic view I can not see anything sad.png

For now the quads are just a 10x10 grid of quads are per the MSDN TexturedQuad tutorial.

This works (the CreateLookAt numbers mean nothing, just an example of what I can use to view something)


static public Matrix View = Matrix.CreateLookAt(new Vector3(5, -10, 16), new Vector3(5, 0, 5),Vector3.Up);
static public Matrix Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 4.0f / 3.0f, 1, 100);


This doesn't:




static public Matrix View = Matrix.CreateLookAt(new Vector3(5, -10, 16), new Vector3(5, 0, 5),Vector3.Up);
OR
static public Matrix View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 30.0f), Vector3.Zero, Vector3.Up);

static public Matrix Projection = Matrix.CreateOrthographicOffCenter(0, Camera.windowWidth, Camera.windowHeight, 0.0f, 100.0f, 1);

I'm pretty sure its my CreateLookAt thats mucking up.

Can someone steer me in the right direction to get something on screen?

Thanks!
Advertisement
I'm guessing the order of parameters you are using in CreateOrthographicOffCenter() function is incorrect... (or you're doing something wierd smile.png)


Try the function this way:

static public Matrix Projection = Matrix.CreateOrthographicOffCenter(-Camera.windowWidth/2, Camera.windowWidth/2, -Camera.windowHeight/2t, Camera.windowHeight/2, 1.0f, 100.0f);
Hi Tiago,

Thanks for your response :) Still not working, but that function call does make more sense!

Using the following, I get a very close, top down view of my tiles


static public Matrix View = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1.0f), Vector3.Zero, Vector3.Up);
static public Matrix Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 4.0f /3.0f , 0.1f, 100.0f);


But still nothing when I change to the orthographic view. I am using BasicEffects, should I be changing something in my rendering of the quads to make this work?

This is baffling me...
Can you post how you create the quads (vertices position) and the world matrix?

Plus, have you ever used PIX? It might help you find the problem...
Never heard of PIX smile.png

Here is my code. I have only just gotten started and am slowly modifying the textured quad example to work for me.
I know there are probably more efficient ways to draw the map using textured quads, but i'm new at this so am trying to keep it simple :)

Appreciate you looking :)


Game1:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA3D2D
{
/// <summary>
/// This is the main type for your game
/// </summary>
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
this.IsMouseVisible = true;
graphics.PreferredBackBufferWidth = 1024;
graphics.PreferredBackBufferHeight = 768;
graphics.ApplyChanges();
Window.Title = "3D Engine";
Camera.windowWidth = this.graphics.PreferredBackBufferWidth;
Camera.windowHeight = this.graphics.PreferredBackBufferHeight;
base.Initialize();
}
/// <summary>
/// LoadContent will be called once per game and is the place to load
/// all of your content.
/// </summary>
Map Map;
Texture2D texture, heightMap, textureMap;
BasicEffect quadEffect;
Quad quad;
VertexDeclaration vertexDeclaration;
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
quadEffect = new BasicEffect(graphics.GraphicsDevice);
//Load resources
texture = Content.Load<Texture2D>(@"Textures\TileSets\Tileset");
heightMap = Content.Load<Texture2D>(@"Maps\heightmap");
textureMap = Content.Load<Texture2D>(@"Maps\texturemap");
//Create map
Map = new Map(heightMap, textureMap, texture);
//Set up camera
quadEffect.World = Matrix.Identity;
quadEffect.View = Camera.View;
quadEffect.Projection = Camera.Projection;
quadEffect.TextureEnabled = true;

}
/// <summary>
/// Allows the game to run logic such as updating the world,
/// checking for collisions, gathering input, and playing audio.
/// </summary>
/// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Update(GameTime gameTime)
{
if (Keyboard.GetState().IsKeyDown(Keys.Escape))
this.Exit();
// TODO: Add your update logic here
base.Update(gameTime);
}
/// <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);
DrawMapBase();
base.Draw(gameTime);
}
public void DrawMapBase()
{
for (float y = 0; y < 10; y++)
{
for (float x = 0; x < 10; x++)
{
DrawQuad(x, y, texture);
}
}
}
private void DrawQuad(float cellX, float cellY, Texture2D tex)
{
//Create new textured quad
Vector3 quadCenter = new Vector3(cellX, cellY, 0);//tileHeight);
quad = new Quad(quadCenter, Vector3.Backward, Vector3.Up, 1, 1, tex);
quadEffect.Texture = tex;
vertexDeclaration = new VertexDeclaration(new VertexElement[]
{
new VertexElement(0, VertexElementFormat.Vector3, VertexElementUsage.Position, 0),
new VertexElement(12, VertexElementFormat.Vector3, VertexElementUsage.Normal, 0),
new VertexElement(24, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
}
);
foreach (EffectPass pass in quadEffect.CurrentTechnique.Passes)
{
pass.Apply();
GraphicsDevice.DrawUserIndexedPrimitives
<VertexPositionNormalTexture>(
PrimitiveType.TriangleList,
quad.Vertices, 0, 4,
quad.Indexes, 0, 2);
}
}
}
}


Map:



using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA3D2D
{
class MapRow
{
public List<Cells> Columns = new List<Cells>();
}

class Map
{
public List<MapRow> Rows = new List<MapRow>();
public int TotalMapWidth = 16*3;
public int TotalMapHeight = 16*3;
public int BlockHeight = 16;
public int BlockWidth = 16;
private Vector2 firstBlock;
public Vector2 FirstBlock
{
get
{
return firstBlock;
}

}
private Vector2 firstCell;
public Vector2 FirstCell
{
get
{
return firstCell;
}

}

private Texture2D HeightMap;
private Texture2D TextureMap;
private Texture2D TileSet;

public Map(Texture2D heightMap, Texture2D textureMap, Texture2D tileset)
{
//Load resources
HeightMap = heightMap;
TextureMap = textureMap;
TileSet = tileset;

TotalMapWidth = HeightMap.Width;
TotalMapHeight = HeightMap.Height;
//Initiate cell list
for (int y = 0; y < BlockHeight * 3; y++)
{
MapRow thisRow = new MapRow();
for (int x = 0; x < BlockWidth * 3; x++)
{
thisRow.Columns.Add(new Cells(0));
}
Rows.Add(thisRow);
}
//Populate list with data
LoadMapFileIntoList(Player.Position);
}

private void LoadMapFileIntoList(Vector2 playerPos)
{
int MapWidth = BlockWidth * 3;
int MapHeight = BlockWidth * 3;

firstBlock.X = (int)MathHelper.Clamp((playerPos.X / BlockWidth) - 1, 0, (TotalMapWidth / BlockWidth)-3);
firstBlock.Y = (int)MathHelper.Clamp((playerPos.Y / BlockHeight) - 1, 0, (TotalMapHeight / BlockHeight)-3);
firstCell.X = firstBlock.X * BlockWidth;
firstCell.Y = firstBlock.Y * BlockHeight;
Console.WriteLine("First Block (x,y): " + firstBlock.X+", "+ firstBlock.Y + " First Cell (x,y): " + firstCell.X+", "+ firstCell.Y);

//Create array to hold image data
Color[] HeightColors = new Color[ MapWidth * MapHeight ];
Color[] TerrainColors = new Color[ MapWidth * MapHeight ];

HeightMap.GetData<Color>(
0, //Mipmap level
new Rectangle( //Source rectangle
(int)firstCell.X,
(int)firstCell.Y,
BlockWidth * 3,
BlockHeight * 3),
HeightColors, //Destination array
0, //start index
MapWidth * MapHeight); //number of elements

TextureMap.GetData<Color>(
0, //Mipmap level
new Rectangle( //Source rectangle
(int)firstCell.X,
(int)firstCell.Y,
BlockWidth * 3,
BlockHeight * 3),
TerrainColors, //Destination array
0, //start index
MapWidth * MapHeight); //number of elements

for (int x = 0; x < MapWidth; x++)
{
for (int y = 0; y < MapHeight; y++)
{
Rows[x].Columns[y].Height = HeightColors[x + y * MapWidth].R - 127;
Rows[x].Columns[y].TextureID = TerrainColors[x + y * MapWidth].R;
//Load objects here
}
}
}

}
}


Camera:

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA3D2D
{

static public class Camera
{
static public int windowWidth, windowHeight;
static public Vector2 position = Vector2.Zero;
static public Vector2 FirstCell = Vector2.Zero;

static public Matrix View = Matrix.CreateLookAt(new Vector3(0.0f, -1.0f, 1.0f), Vector3.Zero, Vector3.Up);
//static public Matrix Projection = Matrix.CreateOrthographicOffCenter(0, Camera.windowWidth, Camera.windowHeight, 0, 0.0f, 1.0f);

//static public Matrix Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 4.0f /3.0f , 0.1f, 100.0f);
static public void MoveCamera()
{

}

}
}



Quad:


using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;

namespace XNA3D2D
{
public struct Quad
{
public Vector3 Origin;
public Vector3 UpperLeft;
public Vector3 LowerLeft;
public Vector3 UpperRight;
public Vector3 LowerRight;
public Vector3 Normal;
public Vector3 Up;
public Vector3 Left;

public VertexPositionNormalTexture[] Vertices;
public short[] Indexes;

public Quad(Vector3 origin, Vector3 normal, Vector3 up, float width, float height, Texture2D texture)
{
Vertices = new VertexPositionNormalTexture[4];
Indexes = new short[6];
Origin = origin;
Normal = normal;
Up = up;

// Calculate the quad corners
Left = Vector3.Cross( normal, Up );
Vector3 uppercenter = (Up * height / 2) + origin;
UpperLeft = uppercenter + (Left * width / 2);
UpperRight = uppercenter - (Left * width / 2);
LowerLeft = UpperLeft - (Up * height);
LowerRight = UpperRight - (Up * height);

FillVertices();
}

private void FillVertices()
{
// Fill in texture coordinates to display full texture
// on quad
Vector2 textureUpperLeft = new Vector2( 0.0f, 0.0f );
Vector2 textureUpperRight = new Vector2( 1.0f, 0.0f );
Vector2 textureLowerLeft = new Vector2( 0.0f, 1.0f );
Vector2 textureLowerRight = new Vector2( 1.0f, 1.0f );

// Provide a normal for each vertex
for (int i = 0; i < Vertices.Length; i++)
{
Vertices.Normal = Normal;
}

// Set the position and texture coordinate for each
// vertex
Vertices[0].Position = LowerLeft;
Vertices[0].TextureCoordinate = textureLowerLeft;
Vertices[1].Position = UpperLeft;
Vertices[1].TextureCoordinate = textureUpperLeft;
Vertices[2].Position = LowerRight;
Vertices[2].TextureCoordinate = textureLowerRight;
Vertices[3].Position = UpperRight;
Vertices[3].TextureCoordinate = textureUpperRight;

// Set the index buffer for each vertex, using
// clockwise winding
Indexes[0] = 0;
Indexes[1] = 1;
Indexes[2] = 2;
Indexes[3] = 2;
Indexes[4] = 1;
Indexes[5] = 3;
}

}
}


Cells:


using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA3D2D
{
public class Cells
{
public int Height { get; set; }
public int TextureID { get; set; }

//Called when a new cell is created
public Cells(int height)
{
Height = height;
}

public Cells(int height, int texture)
{
Height = height;
TextureID = texture;
}
}
}


Player:


using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace XNA3D2D
{
static class Player
{
static public Vector2 Position { get; set; }
}
}

This topic is closed to new replies.

Advertisement