XNA - Model mit Vertex

  • C#

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von AliveDevil.

    XNA - Model mit Vertex

    Hab von hier einen Code um aus einem Model eine List aus Vector3 und TriangleVertexIndices zu erzeugen. Ja, Copy&Paste.
    Ist derzeit aber vollkommen belanglos.

    Nun habe ich vorher immer per

    C#-Quellcode

    1. foreach ( ModelMesh mesh in Types.Entities.GetEntity( Type ).Model.Meshes ) {
    2. foreach ( BasicEffect be in mesh.Effects ) {
    3. if ( Types.Entities.GetEntity( Type ).Textures.Any( p => p.Key.Equals( mesh.Name ) ) ) {
    4. be.TextureEnabled = true;
    5. be.Texture = Types.Entities.GetEntity( Type ).Textures[ mesh.Name.ToLower() ];
    6. } else {
    7. be.TextureEnabled = false;
    8. }
    9. be.EnableDefaultLighting();
    10. be.Projection = proj;
    11. be.View = view;
    12. be.World = Matrix.CreateTranslation( this.X * 2, this.Y * 2, this.Z * 2 );
    13. }
    14. mesh.Draw();
    15. }

    Das Model dargestellt, was bei 1k und mehr Elementen die gezeigt werden sollen einen totalen Frameeinbruch erzeugt.
    Nun, wie kann ich nun die zwei Listen statt dem mesh.Draw() nutzen? Texture ist derzeit erstmal egal, geht nur um die Darstellung der Objekte (sind Würfel).
    Du hast dir den Link im ersten Beitrag angesehen? Ich lasse eine Liste von Vertexen und Indexen erzeugen, aus einem Model.
    Der XNA.mag Artikel, behandelt aber nicht das.
    Außer du kannst mir sagen, wie ich aus der List<TriangleVertexIndices> ein int[] erzeuge.
    Weil ich keine Ahnung habe wie?
    Außerdem: hab mal mit ner andren Person per Skype etwas rumprobiert....
    das Ergebnis: Record.7z
    Wenn du mir sagen kannst, wie ich das behebe, bist du gut :D

    C#-Quellcode

    1. BasicEffect effect = GameResources.Resource<BasicEffect>( "Effect" );
    2. effect.World = Matrix.CreateTranslation( this.X * 2, this.Y * 2, this.Z * 2 );
    3. foreach ( EffectPass pass in effect.CurrentTechnique.Passes ) {
    4. pass.Apply();
    5. this.GraphicsDevice.Indices = IndexBuffer;
    6. this.GraphicsDevice.SetVertexBuffer( VertexBuffer );
    7. this.GraphicsDevice.DrawPrimitives( PrimitiveType.TriangleList, 0, VertexBuffer.VertexCount );
    8. }

    So wird jedes Model gezeichnet.

    Die Welt aktualisiert in ihrer Update-Routine immer View und Projection des Effects.

    C#-Quellcode

    1. GameResources.Resource<BasicEffect>( "Effect" ).View = player.ViewMatrix;
    2. GameResources.Resource<BasicEffect>( "Effect" ).Projection = player.ProjectionMatrix;


    Erzeugen lasse ich die vertices mit

    C#-Quellcode

    1. public void BuildVertices () {
    2. base.Initialize();
    3. List<StaticThings.VertexHelper.TriangleVertexIndices> Indices = new List<StaticThings.VertexHelper.TriangleVertexIndices>();
    4. List<Vector3> Vertices = new List<Vector3>();
    5. StaticThings.VertexHelper.ExtractTrianglesFrom( Types.Entities.GetEntity( Type ).Model, Vertices, Indices, Matrix.CreateTranslation( X * 2, Y * 2, Z * 2 ) );
    6. int[] indices = new int[ Indices.Count * 3 ];
    7. for ( int x = 0; x < Indices.Count; x++ ) {
    8. indices[ x + 0 ] = Indices[ x ].A;
    9. indices[ x + 1 ] = Indices[ x ].B;
    10. indices[ x + 2 ] = Indices[ x ].C;
    11. }
    12. IndexBuffer = new IndexBuffer( this.GraphicsDevice, IndexElementSize.ThirtyTwoBits, indices.Length, BufferUsage.WriteOnly );
    13. IndexBuffer.SetData( indices );
    14. VertexPositionColor[] items = Vertices.Select( p => new VertexPositionColor( p, Color.WhiteSmoke ) ).ToArray();
    15. VertexBuffer = new VertexBuffer( this.GraphicsDevice, typeof( VertexPositionColor ), items.Length, BufferUsage.WriteOnly );
    16. VertexBuffer.SetData( items );
    17. }

    Die Vertices werden gebildet, wenn die Welt die Blöcke haben möchte:

    C#-Quellcode

    1. public IEnumerable<Entity> GetBlocks () {
    2. foreach ( Entity item in chunk.Nodes<Entity>().Values )
    3. yield return item.WithRef( p => { p.X += X * Size; p.Z += Z * Size; p.BuildVertices(); } );
    4. }

    Und nun zeige mir, was falsch ist.
    Dateien
    • Record.7z

      (17,28 MB, 245 mal heruntergeladen, zuletzt: )
    Dass die Blöcke im Vordergrund verschwinden, oder dass es keine Blöcke sind?
    Und beim zweiten Video versteh ich das Problem nicht, was dort falsch sein soll...

    Für das verschwinden solltest du dir das NearPlane mal angucken, für die komischen Blöcke, solltest du dich allgemein mal informieren wie das mit den Vertices funktioniert unterschiede zwischen TriangleList/Strip/Fan usw. und das beste dementsprechend aussuchen...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Naa, mtlw funktionierts.
    Hatte statte DrawIndexedPrimitives nur DrawPrimitives genutzt. NearPlane ist bei 0.01f :D
    Was das mit dem verschwinden aufsich hatte: kA, war irgendetwas mit der Positionsbestimmung beim Extrahieren der Daten...
    muss ich nurnoch HardwareInstancing implementieren und dann sollte das hoffentlich bestens bis 75.000 Elemente funktioniert :)
    Also wenn du jetzt fùr jeden Würfel einen vertexbuffer verwendet ists natürlich Blödsinn...denn instacing kannst einwandfrei mit meshes verwenden...denn ein mess verwendet automatisch einen vertexbuffer und wenns entsprechend gespeichert wurde einen indexbuffer...also keine nachteile...und dann bist du natürlich auch um einiges flexibler, als wenn du alles in einen vertexbuffer packt und kannst vlt sogar bessere Performance rausholen wenn du entsprechend nur nötiges zeichnen lässt
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    halt....

    ich habe eine Klasse "EntityType":

    C#-Quellcode

    1. public class EntityType : GameComponent {
    2. public string Name { get; set; }
    3. public Dictionary<string, Texture2D> Textures { get; set; }
    4. public Model Model { get; set; }
    5. public EntityType ( Game game ) : base( game ) { }
    6. }


    und die Klasse Entity:
    lang

    C#-Quellcode

    1. public class Entity : DrawableGameComponent {
    2. private bool isVisible;
    3. public float X { get; set; }
    4. public float Y { get; set; }
    5. public float Z { get; set; }
    6. public Color Color { get; set; }
    7. public IndexBuffer IndexBuffer;
    8. public VertexBuffer VertexBuffer;
    9. public Entity ( Game game ) : base( game ) { }
    10. public void BuildVertices () {
    11. base.Initialize();
    12. List<StaticThings.VertexHelper.TriangleVertexIndices> Indices = new List<StaticThings.VertexHelper.TriangleVertexIndices>();
    13. List<Vector3> Vertices = new List<Vector3>();
    14. StaticThings.VertexHelper.ExtractTrianglesFrom( Types.Entities.GetEntity( Type ).Model, Vertices, Indices, Matrix.CreateTranslation( X, Y, Z ) );
    15. int[] indices = new int[ Indices.Count * 3 ];
    16. for ( int x = 0; x < Indices.Count; x++ ) {
    17. indices[ ( x * 3 ) + 0 ] = Indices[ x ].A;
    18. indices[ ( x * 3 ) + 1 ] = Indices[ x ].B;
    19. indices[ ( x * 3 ) + 2 ] = Indices[ x ].C;
    20. }
    21. IndexBuffer = new IndexBuffer( this.GraphicsDevice, IndexElementSize.ThirtyTwoBits, indices.Length, BufferUsage.WriteOnly );
    22. IndexBuffer.SetData( indices );
    23. VertexPositionColorNormal[] items = Vertices.Select( p => new VertexPositionColorNormal() { Position = p, Color = Color, Normal = Vector3.One } ).ToArray();
    24. VertexBuffer = new VertexBuffer( this.GraphicsDevice, VertexPositionColorNormal.VertexDeclaration, items.Length, BufferUsage.WriteOnly );
    25. VertexBuffer.SetData( items );
    26. }
    27. public string Type { get; set; }
    28. public void DrawModel () {
    29. BasicEffect effect = GameResources.Resource<BasicEffect>( "Effect" );
    30. effect.World = Matrix.CreateTranslation( this.X, this.Y, this.Z );
    31. foreach ( EffectPass pass in effect.CurrentTechnique.Passes ) {
    32. pass.Apply();
    33. this.GraphicsDevice.Indices = IndexBuffer;
    34. this.GraphicsDevice.SetVertexBuffer( VertexBuffer );
    35. this.GraphicsDevice.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, IndexBuffer.IndexCount, 0, VertexBuffer.VertexCount );
    36. }
    37. }
    38. public BoundingBox Bounding {
    39. get {
    40. Matrix worldMatrix = Matrix.CreateTranslation( X * 2, Y * 2, Z * 2 );
    41. return new BoundingBox( new Vector3( -1, -1, -1 ) + worldMatrix.Translation, new Vector3( 1, 1, 1 ) + worldMatrix.Translation );
    42. }
    43. }
    44. }

    Und zeichnen tu ich so:

    C#-Quellcode

    1. visible.ForEach( p => world.GetNode<Entity>( p ).DrawModel() );


    Du willst mir jetzt sagen, das geht noch besser? (25k Elemente in der Liste (world, List<Entity>): 0 FPS, lagging ohne Ende)
    Sag ma, wie du das machen würdest. Am besten basierend auf den Klassen, die ich schon habe. (Yaay, beste Vorlage für C&P. Nein will ich nicht.)
    wie du selbst schon gesagt hast Instancing, damit holst viel raus, und als nächstes kommen dann halt die Sichtbarkeitsberechnungen, d.h. wenn würfel an würfel ist, ohne abstand, gibt es sicherlich auch würfel, die hinter anderen würfeln versteckt sind z.B. mit Raycollision könnte man da was regeln...

    was ich nicht verstehe, warum du den VertexBuffer und IndexBuffer aus dem Model holst und dann direkt nochmal setzt und den dann verwendest...Das Model macht doch selbst nichts anderes? Models verwenden glaube ich sogar einen Static VertexBuffer, was heißt, dass diese nur einmalig zur Graka geschickt werden und dort dann im Speicher bleiben...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Weil ich keine Ahnung habe, wie ich das mache.
    Wie kann ich denn eine Masse von Models ( 25k ) so darstellen, dass die Anwendung in den Frames praktisch garnicht einbricht?
    Bzw. wie kann ich ein Model per hardware Instanzieren?
    Zur Raycollision: erstma solls laufen, dann kann ich darüber nachdenken.
    Kann ich da auch den BasicEffect nutzen?
    Hab jetzt nicht so die Lust, da was eigenes noch zu schreiben fürn Shader. Bzw. einen zu kopieren um dann zu gucken, wo da der Fehler liegen kann.


    Tritt komischerweise auf...
    ich seh jdfs, dasses nicht an meinen Zeichen-Routinen liegt, dass der so eine Kartoffelperformance hat...

    evtl. liegts an den Update-Sachen:

    C#-Quellcode

    1. BoundingFrustum cam = new BoundingFrustum( player.ViewMatrix * player.ProjectionMatrix );
    2. visible = world.Nodes<Entity>().Values.Where( p => cam.Intersects( p.Bounding ) ).Select( p => string.Format( "{0}.{1}.{2}", p.X, p.Y, p.Z ) ).ToList();

    Bei 25k und mehr Elementen dauerts natürlich, bis der alle durch hat...gibts da was performanteres?
    Gleiches gilt auch für die Kollisionen:

    C#-Quellcode

    1. items = world.Nodes<Entity>().Values.Where( p => new BoundingSphere( Vector3.Zero + new Vector3( player.X, player.Y, player.Z ), player.Acceleration.Length() ).Intersects( p.Bounding ) ).ToList();

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „AliveDevil“ ()

    machs einmal und beweg die kamera dabei nicht, dann siehste wie die Performance ist, und ja an sowas liegt das höchstwahrscheinlich, das macht man nicht immerwieder, sowas würd ich dann in nem extra thread machen...
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---