IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

XNA/Monogame Discussion :

Optimisation d'une heightmap


Sujet :

XNA/Monogame

  1. #1
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut Optimisation d'une heightmap
    Bonjour,

    Je suis sur mon Éditeur de carte XNA et je charge / travaille mes cartes (heightmap) comme je le souhaite. Je peut modifier le terrain, peindre etc...

    Mon problème se situe lorsque je charge des cartes assez grandes, c'est long, ça lag... bref, ce n'est pas super !

    J'ai regardé un peu partout et je suis tombé sur des personnes donnant des explications d'optimisations etc... En faite, ce que je cherche, c'est un rendu optimisé me permettant de pouvoir modifier ma carte en temps réel (éditeur) tout en étant un minimum optimisé (car j'avoue qu'entre le rendu et le picking qui tourne... ça commence à bien laguer sur une carte de plus de 512*512).

    Quel optimisation de rendu me conseillez vous (je cherche un algo qui optimise bien et qui ne soit pas trop difficile tout en me permettant de pouvoir travailler mes cartes).

    Si vous auriez un lien avec un exemple concret, ça serais super (j'ai trouvé 2-3 choses mais je ne sais pas si ça me conviendrais et je comprend pas grand chose, je debute la dedans, je suis un peut perdu )

    Merci !

  2. #2
    Membre régulier Avatar de LeonardL
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 57
    Points : 71
    Points
    71
    Par défaut
    Salut !

    Lis donc cet article de notre très cher MVP XNA Français :
    http://msmvps.com/blogs/valentin/arc...ue-billod.aspx

    Je pense que ça devrait déjà te faire gagner en perf.

  3. #3
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    J'avais déjà vu mais je cherche à faire du geomipmap

    J'ai commencé par créer une classe QuadTree, voici les membres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class Quad
    {
            public BoundingBox zone;
            public Quad Q1 = null;
            public Quad Q2 = null;
            public Quad Q3 = null;
            public Quad Q4 = null;
    }
    J'obtient après un petit calcul une liste de bounding box sous forme d'arbre. Sur l'image en pièce jointe il y a le résultat mais il faut savoir qu'en vrai la carte est divisé en 4 et chaque zone et 4 etc... jusqu'à un seuil que je défini depuis ma classe Terrain.

    J'ai une méthode qui extrait sous forme de tableau de short mes indices et j'arrive grâce à une petite méthode à retirer dans les indices la zone défini par mon quad.

    J'ai effectué des tests lors de la création de l'indice au chargement de la carte, j'ai bien la zone que je ne veut pas afficher, disparaitre.

    Après, j'ai voulu implémenter ça à l'affichage et la.... catastrophe. Non seulement j'ai la zone "normale" qui disparais (ce qui est bien), mais j'ai tout une autre partie ou j'ai un triangle / 2.

    De plus, je passe à 10fps en fesant ça....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
     
    // Methode qui defini si un indice est dans la zone
            public bool Desactive(int position, int longueur)
            {
                // On vire le delta de longueur de merde
                position -= longueur;
                int debutLigne = 0;
                int finLigne = 0;
                for (int i = 0; i < Q1.taille; i++)
                {
                    debutLigne = Convert.ToInt32(Q1.zone.Max.X) + (i * longueur);
                    finLigne = Convert.ToInt32(Q1.zone.Max.X + Q1.taille) + (longueur * i);
                    if (position >= debutLigne && position < finLigne)
                        return false;
                }
                return true;
            }
     
    // Methode qui permet de virer les indices qui sont dans la zone en concervant les autres
     
            public short[] OptimisationQuadTree(DynamicIndexBuffer buf, int longueurIndice, int longueurTerrain)
            {
                short[] indices = new short[longueurIndice];
                buf.GetData<short>(indices);
     
                List<short> nouveauIndices = new List<short>();
     
                for(int i = 0; i < indices.Count(); i++)
                {
                    if(Desactive(indices[i], longueurTerrain))
                        nouveauIndices.Add(indices[i]);
                }
     
                return nouveauIndices.ToArray();
            }
    Ma question ets la suivante : Comment se fais t'il que ça lague autant et suis-je sur le bon chemin?

    Merci par avance
    Images attachées Images attachées  

  4. #4
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    J'ai essayé d'optimiser en gardant en mémoire mon tableau de int de mes index lors de l'initialisation.

    Je gagne un peut de performance mais je passe de 10 --> 17 fps

    On dirais que le chargement de mon indexbuffer est super lent...

    voici la méthode optimisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
            public int[] OptimisationQuadTree(int[] indices, int longueurTerrain)
            {
                List<int> nouveauxindices = new List<int>();
     
                for(int i = 0; i < indices.Count(); i++)
                {
                    if(Desactive(indices[i], longueurTerrain))
                        nouveauxindices.Add(indices[i]);
                }
     
                return nouveauxindices.ToArray();
            }
    et l'appel lors de l'affichage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
                int[] data = q.OptimisationQuadTree(this.terrainIndices, longueur);
     
                IBTerrain.SetData(data, 0, data.Count());

  5. #5
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    J'ai optimisé encore une fois et sur ma minicarte j'obtient 200fps... par contre sur une carte de 256 le fps descend énormément...

  6. #6
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    Bon... J'ai pas mal avancé mais je continue à bloquer

    Maintenant, je préload mes Quadtree au lieu de les recharger à chaque affichage, je perd ainsi quasiment aucun performance.

    Je souhaite donc stocker les indices de chaque Quad le seul problème c'ets que je m'arrache les cheveux à essayer de comprendre comment faire.

    Mes index vont de long en large du terrain comme un zigzag. Je part de la fin (sur une carte de 256, je part au 256ème vertex) pour revenir au debut puis remonter et aller vers la fin etc..

    J'essaye de stoker les index dans un tableau mais je n'y arrive pas...

    Voici mon code actuelle mais ça ne fonctionne pas :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
            public int[] creerIndices(int[] indices, int tailleTotale)
            {               
                List<int> nouveauxindices = new List<int>();
     
                int position = 0;
     
                foreach (int indice in indices)
                {
                    if (
                        ((indice % tailleTotale) >= zone.Min.X && (indice % tailleTotale) <= zone.Max.X) &&
                        ((indice / tailleTotale) >= zone.Min.Z)
                        )
                        nouveauxindices.Add(indice);
                }
     
                return nouveauxindices.ToArray();
            }

    Il y a très peu de code mais croyez moi j'ai du refaire la méthode au moins une bonne trentaine de fois, si ce n'est pas plus...

    voici la classe complete sinon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
     
    namespace HekaEngine
    {
     
        public struct triangle
        {
            public int a;
            public int b;
            public int c;
        };
     
        public class Quad
        {
            #region "Champs"
            public BoundingBox zone;
            public Quad HautGauche = null;
            public Quad HautDroit = null;
            public Quad BasGauche = null;
            public Quad BasDroit = null;
            public int[] indices;
     
            private BasicEffect shader = new BasicEffect(Moteur.GraphicsDevice, null);
            private VertexPositionColor[] points = new VertexPositionColor[8];
            private short[] inds = {
                            0, 1, 0, 2, 1, 3, 2, 3,
                            4, 5, 4, 6, 5, 7, 6, 7,
                            0, 4, 1, 5, 2, 6, 3, 7
                            };
            private int taille;
            #endregion
     
            public Quad(int tailleTerrain)
            {
                // On vérifie que l'affinage est encore bon
                if (tailleTerrain >= Terrain.precisionQuad)
                {
                    taille = tailleTerrain;
                    tailleTerrain /= 2;
                    HautGauche = new Quad(tailleTerrain);
                    HautDroit = new Quad(tailleTerrain);
                    BasGauche = new Quad(tailleTerrain);
                    BasDroit = new Quad(tailleTerrain);
                }
            }
     
            public void CreerQuad(BoundingBox boite, int[] i, int tailleTotale)
            {
                zone = boite;
     
                // Création des indices
                indices = creerIndices(i, tailleTotale);
     
                Vector3 debut = Vector3.Zero;
                Vector3 fin = Vector3.Zero;
     
                // Q1
                debut = zone.Min;
                fin = zone.Max;
                fin.X = fin.X - taille / 2.0f;
                fin.Z = fin.Z - taille / 2.0f;
                HautGauche.zone = new BoundingBox(debut, fin);
     
                // Q2
                debut = zone.Min;
                fin = zone.Max;
                debut.X = fin.X - taille / 2.0f;
                fin.Z = fin.Z - taille / 2.0f;
                HautDroit.zone = new BoundingBox(debut, fin);
     
                // Q3
                debut = zone.Min;
                fin = zone.Max;
                debut.Z = fin.Z - taille / 2.0f;
                fin.X = fin.X - taille / 2.0f;
                BasGauche.zone = new BoundingBox(debut, fin);
     
                // Q4
                debut = zone.Min;
                fin = zone.Max;
                debut.X = fin.X - taille / 2.0f;
                debut.Z = fin.Z - taille / 2.0f;
                BasDroit.zone = new BoundingBox(debut, fin);
     
                if (HautGauche.HautGauche != null)
                {
                    HautGauche.CreerQuad(HautGauche.zone, i, tailleTotale);
                    HautDroit.CreerQuad(HautDroit.zone, i, tailleTotale);
                    BasGauche.CreerQuad(BasGauche.zone, i, tailleTotale);
                    BasDroit.CreerQuad(BasDroit.zone, i, tailleTotale);
                }
            }
     
            #region "Affichage des boites"
            public void Afficher()
            {
                Affichage();
                if (HautGauche != null)
                {
                    HautGauche.Afficher();
                    HautDroit.Afficher();
                    BasGauche.Afficher();
                    BasDroit.Afficher();
                }
            }
     
            private void Affichage()
            {
                Vector3[] corners = zone.GetCorners();
     
                points[0] = new VertexPositionColor(corners[1], Color.Green);
                points[1] = new VertexPositionColor(corners[0], Color.Green);
                points[2] = new VertexPositionColor(corners[2], Color.Green);
                points[3] = new VertexPositionColor(corners[3], Color.Green);
                points[4] = new VertexPositionColor(corners[5], Color.Green);
                points[5] = new VertexPositionColor(corners[4], Color.Green);
                points[6] = new VertexPositionColor(corners[6], Color.Green);
                points[7] = new VertexPositionColor(corners[7], Color.Green);
     
                Moteur.GraphicsDevice.VertexDeclaration = new VertexDeclaration(Moteur.GraphicsDevice, VertexPositionColor.VertexElements);
     
                shader.World = Matrix.Identity;
                shader.View = Moteur.Service.ObtenirService<Camera>().View;
                shader.Projection = Moteur.Service.ObtenirService<Camera>().Projection;
                shader.DiffuseColor = zone.Min;
                shader.DiffuseColor = Color.Gold.ToVector3();
     
     
                shader.Begin(SaveStateMode.SaveState);
                for (int pass = 0; pass < shader.CurrentTechnique.Passes.Count; pass++)
                {
                    shader.CurrentTechnique.Passes[pass].Begin();
                    Moteur.GraphicsDevice.DrawUserIndexedPrimitives<VertexPositionColor>(PrimitiveType.LineList, points, 0, 8, inds, 0, 12);
                    shader.CurrentTechnique.Passes[pass].End();
                }
                shader.End();
            }
            #endregion
     
     
     
            public int[] creerIndices(int[] indices, int tailleTotale)
            {               
                List<int> nouveauxindices = new List<int>();
     
                int position = 0;
     
                foreach (int indice in indices)
                {
                    if (
                        ((indice % tailleTotale) >= zone.Min.X && (indice % tailleTotale) <= zone.Max.X) &&
                        ((indice / tailleTotale) >= zone.Min.Z)
                        )
                        nouveauxindices.Add(indice);
                }
     
                return nouveauxindices.ToArray();
            }
        }
    }

  7. #7
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    Je continue ce monologue en disant que j'ai réussis à m'en sortir mais qu'il me reste encore 2-3 points à corriger

  8. #8
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    Bon bah ça y est, je m'en sort. J'arrive même à définir ce qui dois ou ne dois pas être affiché !

    Maintenant il me reste plus qu'a regarder comment savoir quel est la zone de la caméra et adapter mon système pour une zone et non un point (oui j'ai fais des tests avec un petit modèle que je déplaçais )

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 21
    Points : 17
    Points
    17
    Par défaut
    Bonjour,

    Le post date mais pourrais-tu indiquer comment tu as fait pour déterminer si ton objet était visible ou non?

    J'essaie de le faire avec des boundingbox et des boundingFrustum mais je n'arrive à aucun résultat

    Cordialement

  10. #10
    Membre habitué Avatar de poussinphp
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    428
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 428
    Points : 176
    Points
    176
    Par défaut
    Bonjour,

    Pour y arriver, tu as besoin de récuperer le frustum de ta camera active. Ensuite, tu joue avec les intersects entre tes quads et ton frustum. La valeur de chaque intersect te dis si ton élements est visible ou pas.

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    21
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 21
    Points : 17
    Points
    17
    Par défaut
    Merci c'est ce que j'avait fait sauf que j'ai bloqué a cause d'une inversion de matrice.
    Ça marche plutôt bien, maintenant je doit faire un système de lumière mais c'est une autre histoire :s

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. optimisation d'une requete de recherche
    Par moog dans le forum PostgreSQL
    Réponses: 2
    Dernier message: 06/04/2005, 16h58
  2. [DB2] Optimisation d'une requête
    Par ahoyeau dans le forum DB2
    Réponses: 7
    Dernier message: 11/03/2005, 17h54
  3. Optimisation d'une recherche et mise à jour
    Par gandf dans le forum C++Builder
    Réponses: 4
    Dernier message: 07/01/2005, 18h38
  4. Réponses: 17
    Dernier message: 03/12/2004, 11h17
  5. [Debutant] Optimisation d'une boucle
    Par Javatator dans le forum Langage
    Réponses: 3
    Dernier message: 25/10/2004, 18h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo