I'm not really sure why nobody can help me with that problem. Is it a stupid or a hard question?
Well after one week of messing around with that problem managed to finaly draw the bounding-boxes. The shader issue persists though. I will try to describe it more precise this time.
Here is my BasicModel.cs. It is a little messy but the functionality should be clear. It is responsible for drawing the Model and the corresponding bounding-box.
It contains a method called DrawModel. Here I have two possibilities implemented, drawing the model with basic effect and drawing it with a diffuse light (taken from
here).
I also have a method DebugDraw which uses a basic effect in order to draw the bounding box.
(really sorry for posting the entire class, it is a mess I admit)
namespace XNA3Editor
{
public class BasicModel : DrawableGameComponent
{
public Model model { get; protected set; }
public String name { get; set; }
public String id { get; set; }
public float yawAngle { get; set; }
public float pitchAngle { get; set; }
public float rollAngle { get; set; }
Matrix rotation = Matrix.Identity;
Vector3 vRotation = Vector3.Zero;
Matrix translation = Matrix.Identity;
Vector3 position = Vector3.Zero;
Vector3 direction = new Vector3(0, 0, 0);
private BasicEffect renderer;
private Effect effect;
private BoundingBox aabb { get; set; } //axis-aligned boundin box
private Camera camera;
private short[] indexData; //The index array used to render the AABB
private VertexPositionColor[] aabbVertices; //The AABB vertex array used for rendering
protected Matrix world = Matrix.Identity;
public BasicModel(Game game,Model m, String name) : base(game)
{
model = m;
this.name = name;
// Vertex declaration for rendering our 3D model.
Game.GraphicsDevice.VertexDeclaration = new VertexDeclaration(Game.GraphicsDevice, VertexPositionNormalTexture.VertexElements);
camera = ((Editor)game).camera;
}
private void CreateAABB(Model model)
{
aabb = new BoundingBox();
foreach(ModelMesh mesh in model.Meshes)
{
//Create an array to store the vertex data.
VertexPositionNormalTexture[] modelVertices =
new VertexPositionNormalTexture[mesh.VertexBuffer.SizeInBytes /
VertexPositionNormalTexture.SizeInBytes];
//Get the models vertices
mesh.VertexBuffer.GetData<VertexPositionNormalTexture>(modelVertices);
//Create a new array to store the position of each vertex
Vector3[] vertices = new Vector3[modelVertices.Length];
//Loop throught the vertices
for (int i = 0; i < vertices.Length;i++)
{
//Get the position of the vertex.
vertices = modelVertices.Position;
}
//Create a AABB from the model's vertices.
aabb = BoundingBox.CreateMerged(aabb,
BoundingBox.CreateFromPoints(vertices));
}
}
protected override void LoadContent()
{
effect = Game.Content.Load<Effect>("Effects/Diffuse");
//Create the bounding box from the model's vertices
CreateAABB(model);
base.LoadContent();
}
public virtual void Update()
{
// Rotate model
rotation *= Matrix.CreateFromYawPitchRoll(yawAngle,
pitchAngle, rollAngle);
}
public override void Draw(GameTime gameTime)
{
//Create a new vertex declaration
Game.GraphicsDevice.VertexDeclaration =
new VertexDeclaration(Game.GraphicsDevice,
VertexPositionColor.VertexElements);
//Draw bounding box.
DebugDraw(aabb,Color.White);
//Draw model.
DrawModel(model);
base.Draw(gameTime);
}
private void DrawModel(Model model)
{
#region draw model with diffuse effect
Matrix[] transforms = new Matrix[model.Bones.Count];
model.CopyAbsoluteBoneTransformsTo(transforms);
// worldMatrix = Matrix.CreateWorld(position, rotationMatrix.Forward, rotationMatrix.Up);
// Use the DiffuseLight technique from Shader.fx. You can have multiple techniques in a effect file. If you don't specify
// what technique you want to use, it will choose the first one by default.
effect.CurrentTechnique = effect.Techniques["DiffuseLight"];
// Begin our effect
effect.Begin();
// A shader can have multiple passes, be sure to loop trough each of them.
foreach (EffectPass pass in effect.CurrentTechnique.Passes)
{
// Begin current pass
pass.Begin();
foreach (ModelMesh mesh in model.Meshes)
{
foreach (ModelMeshPart part in mesh.MeshParts)
{
// calculate our worldMatrix..
//world = GetWorld() * mesh.ParentBone.Transform;
world = Matrix.CreateWorld(position, rotation.Forward, rotation.Up);
// .. and pass it into our shader.
// To access a parameter defined in our shader file ( Shader.fx ), use effectObject.Parameters["variableName"]
Matrix worldInverse = Matrix.Invert(world);
Vector4 vLightDirection = new Vector4(0.0f, 0.0f, 1.0f, 1.0f);
effect.Parameters["matWorldViewProj"].SetValue(world * camera.view * camera.projection);
effect.Parameters["matInverseWorld"].SetValue(worldInverse);
effect.Parameters["vLightDirection"].SetValue(vLightDirection);
// Render our meshpart
Game.GraphicsDevice.Vertices[0].SetSource(mesh.VertexBuffer, part.StreamOffset, part.VertexStride);
Game.GraphicsDevice.Indices = mesh.IndexBuffer;
Game.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList,
part.BaseVertex, 0, part.NumVertices,
part.StartIndex, part.PrimitiveCount);
}
}
// Stop current pass
pass.End();
}
// Stop using this effect
effect.End();
#endregion
/*
#region draw model using basic effect
//Create a rotation matrix from GameModel's rotation.
Matrix rotatioMatrix = Matrix.CreateFromYawPitchRoll(
vRotation.X,
vRotation.Y,
vRotation.Z);
//Create the world matrix from the GameModel's position and rotation.
world = Matrix.CreateWorld(position,rotation.Forward,
rotation.Up);
foreach(ModelMesh mesh in model.Meshes)
{
foreach(BasicEffect Beffect in mesh.Effects)
{
//Set effect lightning.
Beffect.EnableDefaultLighting();
Beffect.PreferPerPixelLighting = true;
//Set effect matrices.
Beffect.World = world;
Beffect.View = camera.view;
Beffect.Projection = camera.projection;
}
mesh.Draw();
}
#endregion
*/
}
public Matrix GetWorld()
{
return world;//* Matrix.CreateTranslation(position)
}
private void SetupRenderer()
{
//Create a new Basiceffect instance.
renderer = new BasicEffect(Game.GraphicsDevice,null);
//This lets you color the the AABB
renderer.VertexColorEnabled = true;
//Set renderer matrix.
renderer.World = world;
renderer.View = camera.view;
renderer.Projection = camera.projection;
}
private void DebugDraw(BoundingBox aabb, Color color)
{
//Setup the debug renderer.
SetupRenderer();
//Create an array to store the AABB's vertices.
aabbVertices = new VertexPositionColor[8];
//Get an array of points that make up the corners of the AABB.
Vector3[] corners = aabb.GetCorners();
//Fill the AABB vertex array.
for (int i = 0; i < 8; i++ )
{
aabbVertices.Position = corners;
aabbVertices.Color = color;
}
//Create the index array.
indexData = new short[]
{
0,1,
1,2,
2,3,
3,0,
0,4,
1,5,
2,6,
3,7,
4,5,
5,6,
6,7,
7,4,
};
//Start drawing the AABB.
renderer.Begin();
//Loop through each effect pass.
foreach(EffectPass pass in renderer.CurrentTechnique.Passes)
{
//Start pass.
pass.Begin();
//Draw AABB.
Game.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>
(PrimitiveType.LineList,aabbVertices,0,8,indexData,0,12);
//End pass.
pass.End();
}
//End rendering.
renderer.End();
}
public Vector3 _position
{
get { return this.position; }
set
{
world = Matrix.Identity;
world *= Matrix.CreateTranslation(this.position = value); }
}
public Model _model
{
get { return model; }
}
}
}
Now my problem is, if I draw the model using basic effect, everything looks fine. The bounding box and the Model are drwan as expected. But if I try to apply the diffuse effect to the model, it is drawn wrong. Like there is no shader on it it just looks flat.
Now the thing is in the Draw Method I have a vertex declaration. If I comment that out and remove the bounding box he actually draws the model with diffuse light on it. But it still looks wrong.
I have no idea what is going wrong there! Maybe the vertex declaration somehow screws up between the basic effect for the BB and the diffuse effect on the model?
Help would be great,
Thanks.