C# XNA 3D Model not rendering - c#

The model is a .fbx
I have tried many models also, Nothing seems to be working i was wondering if anyone could help me, The following code is all I have thanks!
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 _3D
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Model model;
Matrix[] transforms;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
graphics.PreferredBackBufferHeight = 800;
graphics.PreferredBackBufferWidth = 1280;
}
protected override void Initialize()
{
base.Initialize();
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
model = Content.Load<Model>("3d/screwdriver");
transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
base.Update(gameTime);
}
// The draw method is one of the reasons I think nothing is working,
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix view = Matrix.CreateLookAt(
new Vector3(200, 300, 900),
new Vector3(0, 50, 0),
Vector3.Up);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45), GraphicsDevice.Viewport.AspectRatio, 0.1f, 10000.0f);
Matrix baseWorld = Matrix.CreateScale(0.4f) * Matrix.CreateRotationY(MathHelper.ToRadians(180));
foreach (ModelMesh mesh in model.Meshes)
{
Matrix localWorld = transforms[mesh.ParentBone.Index] * baseWorld;
foreach (ModelMeshPart part in mesh.MeshParts)
{
BasicEffect e = (BasicEffect)part.Effect;
e.World = localWorld;
e.View = view;
e.Projection = projection;
e.EnableDefaultLighting();
}
mesh.Draw();
}
base.Draw(gameTime);
}
}
}

I don't see anything really wrong with your code, so the problem may be on the model.
It might be caused by the model file in question. There is a know issue with the stock FBX Exporter on Blender (I don't know which modelling software you used to make the model, but the matter is still relevant) that makes the model be exported with a size 100x bigger than it is on Blender. The result is that the model is so big that it not only encloses the camera inside itself, but also is so big that it's polygons are beyond the viewing frustrum. Result: the model is indeed rendered, but it'll never appear onscreen unless you move the camera around until you realise the scaling problem.
I'm saying this because I dealed with this problem myself. If you are indeed using Blender, you should use the exporter found in this page:
http://blog.diabolicalgame.co.uk/2011/07/exporting-animated-models-from-blender.html

Related

Why do games sometimes skip frames in monogame/xna?

This is a simple project created from MonoGame Cross-Platform Desktop template. I created a ball Texture2D and tried to make it move.So I added some code to the Update function.
position.X += 3;
And then in the Draw function
_spriteBatch.Begin();
_spriteBatch.Draw(ballTexture, position, Color.White);
_spriteBatch.End();
I can see the ball flashing sometimes.
Why is that and what can I do to make it not skip frames?
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace SimpleTest
{
public class Game1 : Game
{
private GraphicsDeviceManager _graphics;
private SpriteBatch _spriteBatch;
private Texture2D dirtTexture;
private Vector2 position;
private int direction = 1;
public Game1()
{
_graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
IsMouseVisible = true;
}
protected override void Initialize()
{
// TODO: Add your initialization logic here
base.Initialize();
}
protected override void LoadContent()
{
_spriteBatch = new SpriteBatch(GraphicsDevice);
// TODO: use this.Content to load your game content here
dirtTexture = Content.Load<Texture2D>("dirt");
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
// TODO: Add your update logic here
base.Update(gameTime);
if (position.X > 600)
direction = -1;
else if (position.X < 100)
direction = 1;
position.X = position.X + direction * 3;
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(dirtTexture, position, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
}
}
I think base.Update(gameTime); should only be placed at the very end of the Update() Method, Just like base.Draw(gameTime);. That way it won't skip any lines.
I guess your PC might be running slowly which is the problem, and not your code. To test it, you can replace your Draw method as follows:
protected override void Draw(GameTime gameTime)
{
Color color=gameTime.IsRunningSlowly?Color.Red:Color.CornflowerBlue;
GraphicsDevice.Clear(color);
// TODO: Add your drawing code here
_spriteBatch.Begin();
_spriteBatch.Draw(dirtTexture, position, Color.White);
_spriteBatch.End();
base.Draw(gameTime);
}
Everything is the same, except now we are colouring the screen as Red instead of the usual blue only if the game is in fact running slow (Which is due to your PC). We can know this by the gameTime variable as shown in the first two lines of the method. Test it out and see if you can see the game background going red when the "frame-skipping" happens.
I did test your exact code in my PC and it was working fine. Needless to say, I did use some other png I had instead of the "dirt" Texture2D you used but I don't think that it should be necessary.
Perhaps it's due to GC. You could use my -almost- garbage free build to verify.
You can install the updated SDK from here or the nuget package.

Redraw only one texture, not all of them

I'm a little noob with XNA and I've encountered a problem. I have one texture called "dot", that I use to draw a line across the screen. Then I have a texture that I call "tool", that I want to move around when I touch it with my finger. The problem I have is that for the tool to be cleared and redrawn I call the graphicsDevice.Clear-method in XNA. But when I do that, my lines also disappears. So my question is how can i move around the tool, without causing my lines to disappear? Is there a way to only redraw the tool, without redrawing the lines? Heres a snippet of my code, first update-method:
protected override void Update (GameTime gameTime)
{
float elapsed = (float)gameTime.ElapsedGameTime.TotalSeconds;
TouchCollection touchCollection = TouchPanel.GetState ();
foreach (TouchLocation tl in touchCollection) {
if ((tl.State == TouchLocationState.Pressed) || (tl.State == TouchLocationState.Moved)) {
toolPos = touchCollection [0].Position;
}
}
base.Update (gameTime);
}
And the draw-method:
protected override void Draw (GameTime gameTime)
{
graphics.GraphicsDevice.Clear (Color.Black);
newVector = nextVector (oldVector);
spriteBatch.Begin ();
DrawEvenlySpacedSprites (dot, oldVector, newVector, 0.9f);
spriteBatch.Draw (tool, toolPos, Color.White);
spriteBatch.End ();
oldVector = new Vector2 (newVector.X, newVector.Y);
base.Draw (gameTime);
}
Try using a RenderTarget2D with RenderTargetUsage.PreserveContents. If you didn't use render targets yet, here's a tutorial: http://rbwhitaker.wikidot.com/render-to-texture
All you have to do is to specify RenderTargetUsage.PreserveContents in target's constructor, draw dots to it, and draw the target and tool to the screen. It should look like this:
protected override void Draw (GameTime gameTime)
{
graphics.GraphicsDevice.Clear (Color.Black);
newVector = nextVector (oldVector);
GraphicsDevice.SetRenderTarget(renderTarget);
spriteBatch.Begin ();
DrawEvenlySpacedSprites (dot, oldVector, newVector, 0.9f);
spriteBatch.End ();
GraphicsDevice.SetRenderTarget(null);
spriteBatch.Begin();
spriteBatch.Draw(renderTarget, new Vector2(), Color.White);
spriteBatch.Draw (tool, toolPos, Color.White);
spriteBatch.End()
oldVector = new Vector2 (newVector.X, newVector.Y);
base.Draw (gameTime);
}

Problems rotating a model in XNA

I'm new to 3D models so apologises if these seems basic. I've been searching the web and through my books but I'm lost.
I've made a model in 3D Studio Max 9. It consists of a variety of cubes, clyinders etc.
In Xna I've imported the model okay and it shows correctly. However, when I apply rotation, each component in the model rotates around it's own centre rather. I want the model to rotate as a singal unit rather than each component rotating on the spot.
I've linked the components in 3D Max and they rotate as I want in Max.
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
model = Content.Load<Model>("Models/Alien1");
}
protected override void Update(GameTime gameTime)
{
camera.Update(1f, new Vector3(), graphics.GraphicsDevice.Viewport.AspectRatio);
rotation += 0.1f;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
Matrix worldMatrix = Matrix.Identity;
Matrix rotationYMatrix = Matrix.CreateRotationY(rotation);
Matrix translateMatrix = Matrix.CreateTranslation(location);
worldMatrix = rotationYMatrix * translateMatrix;
foreach (ModelMesh mesh in model.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = worldMatrix * transforms[mesh.ParentBone.Index];
effect.View = camera.viewMatrix;
effect.Projection = camera.projectionMatrix;
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
}
mesh.Draw();
}
base.Draw(gameTime);
}
EDIT: Rotating the object via it's properties works fine so I'm guessing there's something up with the code rather than with the object itself.
Translating the object also causes the objects to get moved independently of each other rather than as a single model and each piece becomes spread around the scene.

Timer drawing on top of itself, Not clearing

Interesting problem! Basically I have a timer for my UI that counts down from 99. Everything works fine save for the fact its drawing the new time on top of the old time. (The previous time is not clearing) There is a clear happening within the GameplayScreens draw call though... its just weird.
Here are my related functions:
GameplayScreen.cs (or our usual Game1)
public override void Update(GameTime gameTime)
{
m_GameUI.Update(gameTime);
m_GameCam.lookAt(m_Hero.Position);//feeds the camera's lookAt function the players vector2 position
m_GameUI.lookAt(m_GameCam.Position); //Look at the camera's position :D
}
public override void Draw(GameTime gameTime)
{
ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
Color.CornflowerBlue, 0, 0);
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
m_BackgroundManager.Draw(spriteBatch, m_GameCam);
//Begin the Spritebatch Drawing
spriteBatch.Begin(SpriteSortMode.Immediate, null,
null,
null,
null,
null, m_GameCam.ViewMatrix);
//Call EntityManager.DrawAllEntities()
EntityManager.Instance.DrawAllEntities(gameTime, spriteBatch);
//End the spritebatch drawing
spriteBatch.End();
spriteBatch.Begin();
m_GameUI.Draw(gameTime, spriteBatch);
m_PlayerUI.Draw(gameTime, spriteBatch);
spriteBatch.End();
}
GameUI.cs
SpriteFont m_Font;
double m_Timer;
public virtual void Update(GameTime gameTime)
{
m_Timer -= gameTime.ElapsedGameTime.TotalSeconds;
}
public virtual void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
spriteBatch.Draw(UITexture, Position, Color.White);
spriteBatch.DrawString(m_Font, "" + (int)m_Timer + "", new Vector2(380, 45), Color.White);
}
Ended up being a really silly mistake, I had a class deriving from the UI that was calling base.draw() so both the updated clock and the original value were being displayed on the screen at once. Basically poor code design, everyone is a newbie when they start out right?
Thanks for looking into it :)

Drawing a "floor" texture

Alright, let's say that I have a tile texture of some floor or something. And I'd like that my player will walk on that.
How can I set this tile to make it a as a floor?
I need this tile texture to be all over the screen width right?
How am I doing it?
Thanks
If you want a really easy way, here it is:
First you create a new Class and name it Tile:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework; // Don't forget those, they will let you
using Microsoft.Xna.Framework.Content; // access some class like:
using Microsoft.Xna.Framework.Graphics; // Texture2D or Vector2
namespace Your_Project _Name
{
class Tile
{
}
{
So far so good, now create the Texture and Position in your class just like this:
namespace Your_Project _Name
{
class Tile
{
Texture2D texture;
Vector2 position;
public void Initialize()
{
}
public void Draw()
{
}
}
{
As you can see I also created two Methods, Initialize and Draw, now we will Initialize our
texture and position for the tile texture in the public void Initialize(),
I don't know how you use your ContentManager but here is a easy way:
public void Initialize(ContentManager Content)
{
texture = Content.Load<Texture2D>("YourfloorTexture"); //it will load your texture.
position = new Vector2(); //the position will be (0,0)
}
Now we need to draw our texture a number of time how will we do that? The way thasc said, the code can be more complex but here is one that you will understand, I will add a SpriteBatch so I can Draw. All this is done in the public void Draw():
public void Draw(SpriteBatch spriteBatch)
{
for (int i=0; i<30;i++) //will do a loop 30 times. Each Time i will =
//a valor from 0 to 30.
{
spriteBatch.Draw(texture, position, Color.White);
//Will draw the texture once, at the position Vector2
//right now position = (0,0)
spriteBatch.Draw(texture, new Vector2((int)i,(int)i), Color.White);
//Will Draw the texture 30 times, the first time on the position (0,0)
//Second Time on (1,1) .. third (2,2) etc...
spriteBatch.Draw(texture, new Vector2((int)position.X + (i * texture.Width), (int)position.Y + (i * texture.Height), Color.White));
//Will Draw the Texture 30 times Spaced by the Width and height
//of the texture (this is the code you need)
}
}
I didn't tried it but it should work, now its just a sample, you can figure out the rest. There is a lot of other methods to do it but this one is really easy. Ok, now the final step is to implement this class so go in your principal class where you have all your code and before this:
public Game1()
Create a new instance of your tile class
Tile tile;
and Initialize it in the protected override void Initialize():
tile = new Tile();
tile.Initialize(Content);
Now you have to draw it on the screen go at the end of the class and find protected override void Draw(GameTime gameTime) and call the draw method of our class:
spriteBatch.Begin();
tile.Draw(spriteBatch);
spriteBatch.End();
This is all the steps to complete a plain simple tile system. As I said there is a lot of others methods you just have to read tutorials about them or create them on your own.
If you don't plan on doing anything extra with the tiled background, I'd recommend thasc's solution and tile the sprite in a single call.
To do that, you create a rectangle as large as your background, and pass SamplerState.LinearWrap to SpriteBatch.Begin, then call Draw on the background rectangle.
Rectangle backgroundRect = new Rectangle(0, 0, backWidth, backHeight);
spriteBatch.Begin(..., ..., SamplerState.LinearWrap, ..., ...);
spriteBatch.Draw(backgroundTexture, backgroundRect, Color.White);
spriteBatch.End();
In case you're curious, what this does is create a single polygon that covers the background area, which will grab coordinates off your texture from 0.0f to backWidth. Textures are usually mapped between (0.0f, 0.0f) and (1.0f, 1.0f), which represent the corners of the given texture. If you go beyond these boundaries, TextureAddressMode defines how these coordinates will be treated:
Clamp will cut down the coordinates back into the 0-1 range.
Wrap will wrap the coordinates back to 0, so 0.0 = 2.0 = 4.0 = etc. and 1.0 = 3.0 = 5.0 = etc.
Mirror will also wrap, but mirroring the texture every other pass, basically going left-to-right-to-left-etc. as the polygon is rendered.

Categories

Resources