Aujourd’hui je vais partager avec vous l’un des bouts de code (assez simple) et surtout la méthode que j’ai utilisé pour améliorer les performances de mon code. Il y a pas mal de texte mais c'edst pour placer le contexte et expliquer la démarche.

Ma problématique était la suivante: au début je n’affichai qu’une couche de sol pour mes premiers tests mais pour que le jeu soit intéressante (et ajouter la possibilité de creuser et miner) il me faut plusieurs couches de sols. J’ai donc pensé à 8 couches (inspiré de timber and stone). Mais une fois fait mon jeu s’est mis à ramer. L’explication simple est que je suis passé de 9 (9 fragments) *32*32 (la taille d’un fragment) cubes à afficher (je compte pas les arbres) à 8*9*32*32 cubes à afficher et là mes performances sont catastrophiques.

J’avais plusieurs solutions à ma disposition:

  • utiliser les shaders (il paraît que c’est le top mais je suis toujours à l’étape compréhension  et je bloque un peu dessus)
  • utiliser des algo de faces avant arrière ou autres comme on en trouve (faut juste que je les comprenne)
  • n’afficher que les cubes visibles (en déterminant si un cube est entouré ou pas)
  • une autre méthode?

J’ai pas mal réfléchi en cherchant une solution très simple et élégante et je me suis concentré sur ce qui est dans mon champ de vision et j’ai tout ramené en 2D.

IMG_2460

Comme on le vois dans le petit schéma ci-contre, j’ai un cône/trinagle de vision et je dois déterminer les cubes qui sont à l'intérieur.

Déterminer si un point est à l'intérieur d'un triangle m'a paru trop compliqué (vous vous rappelez il faut que ce soit une optimisation docn simple), j'ai donc eut l'idée du cercle : tous les cubes étant dans le cercle sont visibles.

Au niveau algorithme c'est très facile à déterminer: on calcule le point C. On connait la distance d = 24 (un demi fragment  plus un fragment = 48 le tout divisé par deux.)

Ensuite il suffit au moment de dessiner un cube de savoir si la distance entre son centre (qui est sa position) et le point C est inférieur à la distance. Facile non?

Bon les plus malins auront remarqué que le cercle ne prendra pas en compte les cubes à l'extrème : on peut laisser tomber ou légèrement augmenter le diamètre du cercle.

 

-(float)calculDeDistanceEntre:(NS3DPoint)unPoint et:(NS3DPoint)unAutrePoint
{
//Les coordonnées sont dans un espace cartésien donc on a un triangle rectangle
float a = unPoint.x - unAutrePoint.x;
float b = unPoint.z - unAutrePoint.z;
return sqrtf( (a*a) + (b*b) );
}

 Le NS3DPoint ci-dessus est une structure créée par moi pour représenter un point 3D. Elle suit les mêmes règles que le NSPoint standard.

//La mi-distance est à la moitié d'un fragment et demi ce qui représente 12 =((32+16)*0.5)/2
//le 0.5 représente la taille d'un cube.
float decal =12.0f;
float x = xpos -sin( heading * piover180 ) * decal;
float z = zpos - cos( heading * piover180 ) * decal;

Voilà très peu de code au final et des performances qui ont largement dépassé ce que j'espérai m'évitant d'avoir à gérer d'autres traitements (pour l'instant du moins). 

J'espère que vous aurez réussi à lire jusqu'au bout et que vous avez trouvé cela intéressant.