2011-08-30 10 views
6

Ho qualche tipo di problema. Sono nuovo di XNA e voglio disegnare una forma poligonale che sembra qualcosa di simile (Alla fine, voglio questi punti per essere casuale):Creazione di un poligono 2D in XNA

Polygon within a rectangle

così ho letto alcuni articoli, e questo è ciò che ho finito con:

private VertexPositionColor[] vertices; 

public TextureClass() 
{ 
    setupVertices(); 
} 

public override void Render(SpriteBatch spriteBatch) 
{ 
    Texture2D texture = createTexture(spriteBatch); 
    spriteBatch.Draw(texture, new Rectangle((int)vertices[0].Position.X, (int)vertices[0].Position.Y, 30, 30), Color.Brown); 
} 

private Texture2D createTexture(SpriteBatch spriteBatch) 
{ 
    Texture2D texture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1, false, SurfaceFormat.Color); 
    texture.SetData<Color>(new Color[] { Color.Brown }); 
    return texture; 
} 

Quando chiamo Render è inizia a disegnare alcune piazze come se si dove in un ciclo. Sto solo supponendo che stia sbagliando tutto. Mi piacerebbe se qualcuno mi indicasse la giusta direzione. Basta creare un poligono e disegnarlo. Sembrava così semplice ...

+0

Cambiate i vertici dopo averli impostati per la prima volta? – Cameron

+0

No, ho appena chiamato Render una volta –

+0

Da dove chiami Render? –

risposta

3

Qui quello che ho in questo momento.

Una classe che genera un BasicEffect con alcune assegnazioni desiderate.

public class StandardBasicEffect : BasicEffect 
{ 
    public StandardBasicEffect(GraphicsDevice graphicsDevice) 
     : base(graphicsDevice) 
    { 
     this.VertexColorEnabled = true; 
     this.Projection = Matrix.CreateOrthographicOffCenter(
      0, graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 0, 0, 1); 
    } 

    public StandardBasicEffect(BasicEffect effect) 
     : base(effect) { } 

    public BasicEffect Clone() 
    { 
     return new StandardBasicEffect(this); 
    } 
} 

Qui è la mia classe PolygonShape

/// <summary> 
/// A Polygon object that you will be able to draw. 
/// Animations are being implemented as we speak. 
/// </summary> 
/// <param name="graphicsDevice">The graphicsdevice from a Game object</param> 
/// <param name="vertices">The vertices in a clockwise order</param> 
public PolygonShape(GraphicsDevice graphicsDevice, VertexPositionColor[] vertices) 
{ 
    this.graphicsDevice = graphicsDevice; 
    this.vertices = vertices; 
    this.triangulated = false; 

    triangulatedVertices = new VertexPositionColor[vertices.Length * 3]; 
    indexes = new int[vertices.Length]; 
} 

/// <summary> 
/// Triangulate the set of VertexPositionColors so it will be drawn correcrly   
/// </summary> 
/// <returns>The triangulated vertices array</returns>} 
public VertexPositionColor[] Triangulate() 
{ 
    calculateCenterPoint();{ 
    setupIndexes(); 
    for (int i = 0; i < indexes.Length; i++) 
    { 
     setupDrawableTriangle(indexes[i]); 
    } 

    triangulated = true; 
    return triangulatedVertices; 
} 

/// <summary> 
/// Calculate the center point needed for triangulation. 
/// The polygon will be irregular, so this isn't the actual center of the polygon 
/// but it will do for now, as we only need an extra point to make the triangles with</summary> 
private void calculateCenterPoint() 
{ 
    float xCount = 0, yCount = 0; 

    foreach (VertexPositionColor vertice in vertices) 
    { 
     xCount += vertice.Position.X; 
     yCount += vertice.Position.Y; 
    } 

    centerPoint = new Vector3(xCount/vertices.Length, yCount/vertices.Length, 0); 
} 

private void setupIndexes() 
{ 
    for (int i = 1; i < triangulatedVertices.Length; i = i + 3) 
    { 
     indexes[i/3] = i - 1; 
    } 
} 

private void setupDrawableTriangle(int index) 
{ 
    triangulatedVertices[index] = vertices[index/3]; //No DividedByZeroException?... 
    if (index/3 != vertices.Length - 1) 
     triangulatedVertices[index + 1] = vertices[(index/3) + 1]; 
    else 
     triangulatedVertices[index + 1] = vertices[0]; 
    triangulatedVertices[index + 2].Position = centerPoint; 
} 

/// <summary> 
/// Draw the polygon. If you haven't called Triangulate yet, I wil do it for you. 
/// </summary> 
/// <param name="effect">The BasicEffect needed for drawing</param> 
public void Draw(BasicEffect effect) 
{ 
    try 
    { 
     if (!triangulated) 
      Triangulate(); 

     draw(effect); 
    } 
    catch (Exception exception) 
    { 
     throw exception; 
    } 
} 

private void draw(BasicEffect effect) 
{ 
    effect.CurrentTechnique.Passes[0].Apply(); 
    graphicsDevice.DrawUserPrimitives<VertexPositionColor>(
     PrimitiveType.TriangleList, triangulatedVertices, 0, vertices.Length); 
} 

Ci dispiace, è una specie di sacco. Ora per la mia prossima missione. Animazione il mio poligono.

Spero che abbia aiutato i colleghi con lo stesso problema.

1

ho lavorato con XNA in passato su una simulazione fisica in cui ho dovuto disegnare delimitazione scatole con GraphicsDevice.DrawIndexedPrimitives (Si dovrebbe google o MSDN per questa funzione per gli esempi più lavorati.)

Il codice seguente è quello che ho usato nel mio progetto per disegnare una geometria 3D.

/// <summary> 
/// Draw the primitive. 
/// </summary> 
/// <param name="world">World Matrix</param> 
/// <param name="view">View Matrix</param> 
/// <param name="projection">Projection Matrix</param> 
/// <param name="color">Color of the primitive</param> 
public void Draw(Matrix world, Matrix view, Matrix projection, Color color) 
{ 
    _mGraphicsDevice.VertexDeclaration = _mVertexDeclaration; 
    _mGraphicsDevice.Vertices[0].SetSource(_mVertexBuffer, 0, VertexPositionNormal.SizeInBytes); 
    _mGraphicsDevice.Indices = _mIndexBuffer; 

    _mBasicEffect.DiffuseColor = color.ToVector3(); 
    _mBasicEffect.World = _mTransform * world; 
    _mBasicEffect.View = view; 
    _mBasicEffect.Projection = projection; 

    int primitiveCount = _mIndex.Count/3; 

    _mBasicEffect.Begin(); 
    foreach (EffectPass pass in _mBasicEffect.CurrentTechnique.Passes) 
    { 
     pass.Begin(); 
     _mGraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, _mVertex.Count, 0, primitiveCount); 
     pass.End(); 
    } 
    _mBasicEffect.End(); 
} 

Questa funzione è un metodo membro di un oggetto di geometria (classe) e viene chiamato dalla classe gioco Draw(GameTime) metodo

+0

Puoi mostrarmi come sono gli oggetti _mVertexDeclaration, _mIndexBuffer e _mVertexBuffer? –

+0

Sembrano esattamente come sono. Controllare l'API per GraphicsDevice.VertexDeclaration, GraphicsDevice.Indices e Microsoft.Xna.Framework.Graphics.VertexBuffer, rispettivamente. – Jake

2

questo codice è utile per disegnare linee 2D, alcuni calcs può essere fatto in un chiamata di inizializzazione, ma preferisco che questo esempio tenga tutti insieme.

public void DrawLine(VertexPositionColor[] Vertices) 
    {   
     Game.GraphicsDevice.DepthStencilState = DepthStencilState.Default; 

     Vector2 center; 
     center.X = Game.GraphicsDevice.Viewport.Width * 0.5f; 
     center.Y = Game.GraphicsDevice.Viewport.Height * 0.5f; 

     Matrix View = Matrix.CreateLookAt(new Vector3(center, 0), new Vector3(center, 1), new Vector3(0, -1, 0)); 
     Matrix Projection = Matrix.CreateOrthographic(center.X * 2, center.Y * 2, -0.5f, 1); 
     Effect EffectLines = Game.Content.Load<Effect>("lines"); 
     EffectLines.CurrentTechnique = EffectLines.Techniques["Lines"]; 

     EffectLines.Parameters["xViewProjection"].SetValue(View * Projection); 
     EffectLines.Parameters["xWorld"].SetValue(Matrix.Identity); 

     foreach (EffectPass pass in EffectLines.CurrentTechnique.Passes) 
     { 
      pass.Apply(); 
      Game.GraphicsDevice.DrawUserPrimitives<VertexPositionColor> 
       (PrimitiveType.LineList, Vertices, 0, Vertices.Length/2); 
     }    
    } 

LINES.FX

uniform float4x4 xWorld; 
uniform float4x4 xViewProjection; 

void VS_Basico(in float4 inPos : POSITION, in float4 inColor: COLOR0, out float4  outPos: POSITION, out float4 outColor:COLOR0) 
{ 
    float4 tmp = mul (inPos, xWorld); 
    outPos = mul (tmp, xViewProjection); 
    outColor = inColor; 
} 

float4 PS_Basico(in float4 inColor:COLOR) :COLOR 
{ 
return inColor; 
} 


technique Lines 
{ 
pass Pass0 
    { 
     VertexShader = compile vs_2_0 VS_Basico(); 
     PixelShader = compile ps_2_0 PS_Basico(); 
     FILLMODE = SOLID; 
     CULLMODE = NONE;   
    } 
} 
+0

Ho provato la tua soluzione ma sto ricevendo questo errore: sia il vertex shader che il pixel shader devono essere impostati sul dispositivo prima di poter eseguire qualsiasi operazione di disegno. –

+0

ho aggiunto il pixel shader a lines.fx – Blau