Ciao a tutti.
Ho creato un game 3D che disegna un cubo (vedi figura) in cui ogni faccia è costruita con 2 primitive (triangoli)
codice:
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
namespace Modello3D
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
Matrix view, projection;
Effect shader;
VertexPositionColor[] vertices = new VertexPositionColor[8];
int[] indices = new int[36];
Vector3 view_pos = new Vector3(10, 10, 100);
Vector3 view_pun = Vector3.Zero;
Vector3 view_up = Vector3.Up;
KeyboardState k;
MouseState m, pre;
VertexBuffer vBuf;
IndexBuffer iBuf;
public void KeybInput()
{
k = Keyboard.GetState();
if (k.IsKeyDown(Keys.Escape))
{ }//Exit
else if (k.IsKeyDown(Keys.Right))
{ } //Freccia a destra
else if (k.IsKeyDown(Keys.Left))
{ } //Freccia a sinistra
else if (k.IsKeyDown(Keys.Up))
view_pos -= Vector3.UnitZ;
else if (k.IsKeyDown(Keys.Down))
view_pos += Vector3.UnitZ;
}
public void MouseInput()
{
m = Mouse.GetState();
if (pre.X != m.X)
{ } //
if (pre.Y != m.Y)
{ } //
pre = Mouse.GetState();
}
public void Set_Buffers()
{
vBuf = new VertexBuffer(GraphicsDevice,
typeof(VertexPositionColor),
vertices.Length,
BufferUsage.WriteOnly);
iBuf = new IndexBuffer(GraphicsDevice,
typeof(System.Int32),
indices.Length,
BufferUsage.WriteOnly);
GraphicsDevice.SetVertexBuffer(vBuf);
GraphicsDevice.Indices = iBuf;
}
public void Set_Vertices()
{
vertices[0] = new VertexPositionColor(new Vector3(0, 0, 0), Color.White);
vertices[1] = new VertexPositionColor(new Vector3(5, 0, 0), Color.White);
vertices[2] = new VertexPositionColor(new Vector3(5, 0, -5), Color.White);
vertices[3] = new VertexPositionColor(new Vector3(0, 0, -5), Color.White);
vertices[4] = new VertexPositionColor(new Vector3(0, 5, 0), Color.White);
vertices[5] = new VertexPositionColor(new Vector3(5, 5, 0), Color.White);
vertices[6] = new VertexPositionColor(new Vector3(5, 5, -5), Color.White);
vertices[7] = new VertexPositionColor(new Vector3(0, 5, -5), Color.White);
}
public void Set_Indices()
{
indices[0] = 0;
indices[1] = 4;
indices[2] = 1;
indices[3] = 4;
indices[4] = 5;
indices[5] = 1;
indices[6] = 1;
indices[7] = 5;
indices[8] = 2;
indices[9] = 5;
indices[10] = 6;
indices[11] = 2;
indices[12] = 2;
indices[13] = 6;
indices[14] = 3;
indices[15] = 6;
indices[16] = 7;
indices[17] = 3;
indices[18] = 7;
indices[19] = 4;
indices[20] = 3;
indices[21] = 3;
indices[22] = 4;
indices[23] = 0;
indices[24] = 4;
indices[25] = 7;
indices[26] = 5;
indices[27] = 7;
indices[28] = 6;
indices[29] = 5;
indices[30] = 1;
indices[31] = 2;
indices[32] = 3;
indices[33] = 3;
indices[34] = 0;
indices[35] = 1;
}
public void Raster_State()
{
//dobbiamo istanziare questa classe se vogliamo disegnare
//primitive senza riempimento di colore
RasterizerState rs = new RasterizerState();
rs.FillMode = FillMode.WireFrame; //Alternativa: .Solid
rs.CullMode = CullMode.CullCounterClockwiseFace;
GraphicsDevice.RasterizerState = rs;
}
public Game1()
{
graphics = new GraphicsDeviceManager(this);
graphics.PreferredBackBufferWidth = 1000;
graphics.PreferredBackBufferHeight = 500;
Content.RootDirectory = "Content";
}
protected override void Initialize()
{
Raster_State();
Set_Buffers();
Set_Vertices();
Set_Indices();
base.Initialize();
}
protected override void LoadContent()
{
shader = Content.Load<Effect>("MyShader");
projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.Pi / 3,
this.GraphicsDevice.Viewport.AspectRatio,
0.1f, 500);
}
protected override void UnloadContent()
{
}
protected override void Update(GameTime gameTime)
{
KeybInput();
view = Matrix.CreateLookAt(view_pos, view_pun, view_up);
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.Black);
shader.Parameters["World"].SetValue(Matrix.Identity);
shader.Parameters["View"].SetValue(view);
shader.Parameters["Projection"].SetValue(projection);
shader.CurrentTechnique.Passes[0].Apply();
GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList,
vertices, 0, vertices.Length, indices, 0, indices.Length / 3);
//base.Draw(gameTime);
}
}
}
Questo è il mio shader:
codice:
float4x4 World;
float4x4 View;
float4x4 Projection;
struct VertexShaderInput
{
float4 Position : POSITION0;
float4 Color : COLOR;
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float4 Color : COLOR;
};
VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
VertexShaderOutput output;
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
output.Color = input.Color;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
return input.Color;
}
technique Technique1
{
pass Pass1
{
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}
Volevo evitare le diagonali delle facce ed ho pensato di usare come primitive le linee che formano i lati del cubo. Ho sostituito gli indices con questi
codice:
//Faccia inferiore
indices[0] = 0;
indices[1] = 1;
indices[2] = 1;
indices[3] = 2;
indices[4] = 2;
indices[5] = 3;
indices[6] = 3;
indices[7] = 0;
//Faccia superiore
indices[8] = 4;
indices[9] = 5;
indices[10] = 5;
indices[11] = 6;
indices[12] = 6;
indices[13] = 7;
indices[14] = 7;
indices[15] = 4;
//Facce laterali
indices[16] = 0;
indices[17] = 4;
indices[18] = 1;
indices[19] = 5;
indices[20] = 2;
indices[21] = 6;
indices[22] = 3;
indices[23] = 7;
e al posto di PrimitiveType.TriangleList uso questa riga
codice:
GraphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.LineList,
vertices, 0, vertices.Length, indices, 0, indices.Length / 2);
Il risultato è che mi disegna TUTTI i lati, anche quelli che dovrebbero essere nascosti! E non c'è CullMode che tenga. D'altra parte non sono ammesse primitive oltre le linee e i triangoli (o si?) Come devo fare?
Grazie e scusate per questo mattone.