Objectif

Créer un jeu qui mélange Minecraft, Kube, Galaxy55 et notre créativité.

Le monde est un tore qui sera affiché sous une forme sphérique.

Technologies

Le jeu est codé en C et utilise une bibliothèque graphique (libHang) qui s'occupe du rendu 3D, des entrées (clavier, souris, etc.), des threads, etc.

Les TESTS

Booti's booting...

Ok, gros problème de lenteur au niveau de l'élaboration du rendu des chunks, va falloir corriger ça...

I>upd_map 1430587014292
[...]
O<upd_map 1430587014856

Edit: Blabla timestamp...

Booti's booting...

Problème de lenteur corrigé, on attaque la physique :)

Booti's booting...

Excellent ! =)

Le plus pif des pifs

:O
Pif, tu réactualises combien de fois la page par jour ? :calim:

Booti's booting...

En fait je viens d'arriver, juste pour regarder. '-'

Le plus pif des pifs

Problème de lenteur extrême de génération des chunks sous Windows, d'origine inconnue, à voir...

Booti's booting...

Bon, visiblement c'était dû à un problème de préemption à la libération d'un mutex (aucun changement de tâche n'était effectué après lhLockMutex, ce qui fait que le thread graphique avait quasiment en permanence la main sur le verrou graphique). Un petit changement de l'implémentation des mutex dans le driver Windows de libHang, et ça a l'air corrigé. o/

Booti's booting...

La petite histoire, pour ceux que ça intéresse...

Dans libHang, les éléments à afficher sont regroupés en classes d'objets (non affichables), qui contiennent des objets (affichables), qui peuvent contenir des clones d'objet (affichables). Ces différentes divisions sont définies au niveau graphique, et servent à optimiser le rendu : ça ira infiniment plus vite d'afficher 30976 cubes (=actuellement, une map avec seulement de l'eau à sa surface) sous forme de 30976 clones d'1 seul objet, provenant d'1 seule classe, que d'afficher 1 objet par 30976 classes différentes.
La limite à ça étant que chaque niveau réduit les modifications que l'on peut effectuer sur des éléments affichés : la classe d'objets est la plus paramétrable (on peut faire absolument tout avec), les objets le sont un peu moins, mais conservent une certaine marge de liberté, en revanche pour clones d'objets, la seule différence qu'ils peuvent avoir avec l'objet parent est leur position et leur angle de rotation.
(À terme, existera une autre division, mais à part : les groupes d'objets, qui pourront contenir des objets et clones d'objets hétéroclites, mais sans aucun impact sur les performances, car ils permettent seulement de regrouper plusieurs objets de façon à former une seule entité : si on bouge ou on pivote un groupe d'objet, alors tous les objets à l'intérieur en subiront les effets)
Mais je digresse. Pour en revenir au sujet, pour stocker (entre autres) les clones d'objets, libHang utilise des listes chaînées. Lors du rendu graphique, ces listes sont parcourues pour générer les données à envoyer à la carte graphique. Cependant, sans Mutex, un autre thread peut par exemple supprimer un élément pendant qu'il est en train d'être lu par le thread de rendu. Ce qui fait que ce thread essaiera de lire dans le vide, et donc crashera, tout simplement. Pour éviter ça, on utilise un Mutex, qui dispose de 2 fonctions intéressantes : Lock et Unlock. Un thread qui veut utiliser une ressource partagée doit la verrouiller avec lhMutexLock. Cette fonction met en pause le thread courant si le mutex a déjà été verrouillé par un autre (qu'on va appeler maître), le verrou étant maintenu jusqu'à un appel par le thread "maître" de lhUnlockMutex. À ce moment, un des autres threads en attente obtient le verrou, devient le thread maître et peut continuer son exécution, etc.
Le problème avec Windows, c'est qu'il existe 4564156 implémentations différentes de mutex. Celle que j'utilisais avant, Critical Section, est très efficace, mais elle présente un inconvénient majeur : elle n'effectue pas d'appel à l'ordonnanceur juste après avoir libéré le mutex (ordonnanceur = système est chargé de switcher d'un thread à un autre). Ce qui fait que ma fonction lhDraw, qui verrouille plus de 60 fois par seconde le Mutex graphique, le libérait et récupérait en boucle, en laissant seulement rarement un autre thread le récupérer. Or, le chargement de chunks nécessite en permanence l'ajout et la suppression de clones d'objet, qui ne peuvent se faire qu'après l'acquisition du verrou graphique. C'était ce qui causait le lag monstrueux pouvant atteindre plus de 10 secondes chez sodimel.
J'ai donc changé d'implémentation, en en utilisant une moins avancée (j'ai dû rajouter quelques lignes de code pour la rendre récursive), mais qui présente l'avantage d'appeler systématiquement l'ordonnanceur après chaque déverrouillage, et donc d'éviter à tous les threads de se faire pomper l'oxygène par lhDraw.

Pavey Caesar

Booti's booting...

Maintenant, focus sur physics.c :D

Booti's booting...

Regarde, avec 256*16*16 cubes par chunk, en supposant qu'un cube = 32 octets (ce qui doit être le max, je pense...), ça nous fait 2 Mo par chunk, tel que c'est actuellement.

Tel que tu veux faire, ça nécessite l'utilisation de listes chaînées, et donc ça rajoute au moins 24 octets de plus par cube, pour environ la moitié des cubes stockés par comme c'est actuellement.

Second problème des listes chaînées : tel que c'est actuellement, j'ai juste besoin de faire chunk->cubes[x][y][z] pour récupérer un cube. Maintenant, avec une liste chaînée dans une seule dimension, il faut parcourir toute la liste avant de tomber sur le bon. Dans 2 dimensions, il faut parcourir toute une liste de listes avant de tomber sur la bonne, puis toute la sous-liste associée pour trouver le bon cube, etc.

- Guillaume

Le plus pif des pifs

Vous devez être inscrit pour répondre à ce sujet.