Graphique de scène comme conteneur d'objets?

8

Le graphe de scène contient des nœuds de jeu représentant des objets de jeu. À première vue, il peut sembler pratique d'utiliser Scene Graph comme conteneur physique pour les objets du jeu, au lieu de std :: vector <> par exemple.

Ma question est, est-il pratique d'utiliser le graphe de scène pour contenir les objets du jeu , ou doit-il être utilisé uniquement pour définir les liens entre les objets et les nœuds de la scène, tout en conservant les objets stockés dans un conteneur séparé, comme std :: vector <>?

Bunkai.Satori
la source
Est-ce que quelqu'un a une idée? J'ai l'intention d'utiliser à la fois le graphique de scène pour organiser les acteurs / nœuds de jeu, puis le vecteur pour effectuer divers tri qui devraient être plus rapides que le tri d'un arbre SceneGraph à plusieurs voies.
Bunkai.Satori
@ All: J'ai une autre question: SceneGraph contient-il toute la carte, ou doit-il contenir uniquement une partie de la carte, disons sa zone visible? Évidemment, le graphique de la scène serait alors continuellement mis à jour, alors que le joueur se déplace sur la carte.
Bunkai.Satori

Réponses:

5

Le choix du type de gestion de scène à utiliser dépend fortement du type de logique que vous essayez d'exécuter. Considérez les différents consommateurs de votre scène:

Consommateur de rendu

Le moteur de rendu veut probablement simplement savoir ce qui est actuellement visible par l'utilisateur à un moment donné. Il veut une hiérarchie de volume de délimitation pour une élimination rapide ( article wiki BVH) afin de pouvoir comprendre qu'une chaise à l'intérieur d'un bateau n'a pas besoin d'être dessinée car les limites du bateau sont en dehors du tronc de vue. Cela pourrait être intégré dans un octree .

Il pourrait également vouloir avoir une idée que la chaise est sur le dos à l'intérieur du bateau, et que le bateau roule de haut en bas sur certaines vagues quand il apparaît enfin. De cette façon, pour trouver les coordonnées mondiales finales des sommets de la chaise, il peut concaténer les transformations de chaise et de bateau et en finir (cela rend également votre travail de programmeur plus facile).

Encore une autre façon de voir ce problème est que le moteur de rendu exécute probablement une bonne carte et, en fin de compte, veut juste un tas de triangles triés de manière à minimiser la texture, le shader, le matériau, l'éclairage et les changements d'état de transformation. Ce dernier vous aidera probablement plus qu'un BVH, en termes de performances.

Game Logic Consumer

La logique du jeu veut probablement juste une liste plate de choses qui peuvent se parler par un système de messagerie, donc un std :: vector est probablement bien.

Le jeu pourrait également vouloir un moyen de garder une trace de qui est le plus proche de quoi, donc une sorte d'information [du plus proche voisin] [3] pourrait être utile dans ce cas. Cela peut également être fourni par un BVH, mais avoir à monter et descendre le graphique peut être ennuyeux.

Le jeu voudra peut-être même simplement savoir que quand il bouge A, l'élément B de A devrait aussi bouger ... auquel cas nous revenons à une sorte de hiérarchie de transformation.

Consommateur de physique

Votre physique de jeu peut vouloir avoir une [représentation spéciale] [4] d'espaces intérieurs pour une détection très rapide des collisions. Alternativement, il pourrait utiliser une sorte d'octree ou de [hachage spatial] [5] pour trouver efficacement les choses qui pourraient entrer en collision.

Aucune des structures de données physiques ci-dessus ne ressemble vraiment à un "graphique de scène" au sens de Java3D.

Consommateur audio

Un moteur audio veut juste de la géométrie, peut-être un ensemble potentiellement visible (audible), ou une sorte de hiérarchie de volume englobante pour calculer l'atténuation sonore et la propagation. Encore une fois, ce n'est pas vraiment un type de graphique de scène normal, bien qu'il puisse s'agir d'un graphique de géométrie dans votre scène.

En fin de compte ... ... cela dépend vraiment des besoins exacts de votre application. Je suggère d'utiliser une liste plate pour commencer et de voir où se posent vos problèmes. Vous pourriez même essayer une liste plate avec une hiérarchie de transformation, car c'est peut-être la seule sorte de scénario utile pour des raisons autres que l'efficacité.

Bonne chance!

ChrisE
la source
@ChrisE: +1 pour une excellente question. À mon avis, c'est la meilleure réponse ici, permettez-moi donc de marquer celle-ci comme la réponse acceptée . Si j'ai bien compris, vous avez prouvé que Scene Graph n'est pas toujours la solution ultime. Surtout dans Game Logic, voyez-vous un graphique de scène comme la bonne façon de mettre à jour la transformation (échelle, traduction) des objets associés? Exemple, une chaise est sur le bateau, donc les coordonnées de la chaise sont mises à jour lorsque le bateau se déplace? Alternativement, voyez-vous une meilleure solution pour la mise à jour des coordonnées relatives?
Bunkai.Satori
@ChrisE: En plus de ce qui précède, dans le cas où le graphique de scène est utilisé, peut-il être lui-même utilisé comme seul support d'objets pour la scène, ou recommanderiez-vous d'avoir un autre conteneur (disons std :: vector <>) en plus de Scene Graphique?
Bunkai.Satori
2
J'étais en train de suggérer cela. J'essaierais de garder une hiérarchie de transformation (ici, un arbre n-aire où les nœuds ont un parent et plusieurs enfants, et aucun enfant n'est partagé entre les nœuds) avec chaque nœud contenant une référence à l'objet de jeu. Les objets du jeu sont conservés dans un tableau plat séparé (par exemple, std :: vector).
ChrisE
Pendant la mise à jour, vous pouvez parcourir la liste des plats et exécuter la logique du jeu, et chaque fois qu'un mouvement relatif se produit (par exemple, la chaise est poussée vers l'avant sur le bateau), vous utilisez la hiérarchie de transformation pour trouver la transformation finale du local au monde en marchant placez les parents de votre objet et enchaînez leurs transformations. Cela utilise la hiérarchie de transformation pour ce qu'il est le mieux (simplifiant le mouvement relatif), et vous permet toujours de garder une liste pratique d'objets autour.
ChrisE
Une autre amélioration consiste à conserver dans chaque objet un drapeau sale et une transformation de tout ce qui se trouve au-dessus dans la hiérarchie de transformation. La transformation parent-monde mise en cache (cette transformation que je viens de mentionner) signifie que pour toutes les mises à jour de position d'objet, vous ne devez effectuer qu'une seule multiplication de matrice (la transformation relative en parent avec la transformation parent-monde). Chaque fois que vous mettez à jour la transformation relative, vous mettez également à jour votre indicateur sale.
ChrisE
3

Il y a une bonne raison de ne pas utiliser le graphique de scène comme conteneur pour les objets de jeu, et c'est l'instanciation. Si vous souhaitez réutiliser certaines ressources, il est beaucoup plus logique de se référer plusieurs fois à la ressource de votre graphique de scène que d'avoir plusieurs copies réelles.

Jari Komppa
la source
@Jari: +1 pour une bonne réponse. Si je comprends bien, l'approche générale est d'avoir un conteneur séparé de maillages pouvant être rendus. Le graphique de scène fait normalement référence au conteneur de maillages pouvant être rendus, pour prendre des informations sur la forme de l'objet. En plus de cela, chaque nœud de graphe de scène contient des informations de transformation. Jari, ayant une telle conception, je voudrais savoir s'il est toujours recommandé d'avoir un conteneur std :: vector <> séparé pour les nœuds de jeu, par exemple dans le but d'un tri plus rapide, ou pour d'autres raisons ..
Bunkai.Satori
2
Cela dépend - il peut être utile d'avoir en fait plusieurs listes linéaires de nœuds pour un traitement plus rapide de l'IA, de la physique, peu importe. Mais j'irais là-bas après avoir vu s'il y avait un problème autrement.
Jari Komppa
Donc, pour conclure, il devrait être acceptable que le début n'ait qu'un seul SceneGraph, qui contiendrait tous les objets de la scène. Pouvez-vous indiquer s'il vous plaît si les caméras, les lumières et les déclencheurs devraient également figurer dans le graphique de la scène?
Bunkai.Satori
Tout ce qui est affecté par la hiérarchie de transformation doit être dans le graphique de la scène, mais je ne donnerais toujours pas la propriété au graphique de la scène, mais je les stockerais ailleurs pour un traitement plus facile (animation, physique, etc.).
Jari Komppa
J'ai compris Jari. Merci. Je commencerai par une version plus petite et ajouterai un autre conteneur pour un traitement plus facile plus tard si nécessaire.
Bunkai.Satori
2

Séparer votre modèle d'objet et votre modèle de vue (votre scénario) est généralement une bonne idée.

Voir cet article sur le sujet.

Cela permettra notamment l'utilisation de pools d'objets. Ce qui pourrait être essentiel pour une gestion efficace de la mémoire.

Cloueur
la source
+1 pour une bonne contribution. J'ai parcouru l'article. Il discute des modèles de programmation, et si j'ai bien compris, le modèle d'objet conserverait la liste des objets de la scène organisée dans une sorte de conteneur std: vector <>, tandis que ViewModel contiendrait les mêmes objets organisés dans le graphique de la scène? Cependant, seuls les objets actuellement affichés seraient contenus dans le graphique de scène?
Bunkai.Satori
Et qu'en est-il des caméras, des déclencheurs, des lumières? feraient-ils également partie du graphique de la scène?
Bunkai.Satori
@ Bunkai.Satori Eh bien, vous pourriez avoir potentiellement dans le scénario des éléments qui ne sont pas affichés à l'écran. Vous créez votre scénario, puis vous pouvez exécuter un algorithme d'élimination sur le scénario avant de rendre les nœuds visibles. Les lumières et les déclencheurs des caméras peuvent exister à la fois dans le modèle et dans le modèle de vue.
Nailer
Merci pour votre réponse. Comme vous avez mentionné l' abattage , comment cela se fait-il dans la pratique? la scène entière est-elle incluse dans le graphique de la scène, ou y a-t-il seulement la partie visible? Si la scène entière se trouve dans le graphe de scène, le graphe de scène entier est-il parcouru par image pour envoyer uniquement la zone visible dans OpenGL / DirectX API? Je doute que la scène entière soit envoyée à l'API par image, car la partie visible est généralement à moins de 5% de la scène complète. Alternativement, le graphique de scène est-il organisé d'une manière ou d'une autre, pour récupérer rapidement les zones les plus proches sans travelrsal complet par image?
Bunkai.Satori
Mettez toute votre scène dans le scénario. Équilibrez le graphique en fonction de certains critères (par exemple, vous pouvez en faire un arbre oc). Parcourez l'arborescence et déterminez quels nœuds sont "Visibles", "Partiellement visibles" et "Invisibles" selon que les zones de délimitation sont dans votre vue tronconique. Vous pouvez créer un "graphique de visibilité" super léger qui se compose essentiellement de références aux nœuds SG et d'un indicateur. Après l'abattage du tronc, vous pouvez à nouveau traverser l'arbre pour effectuer l'abattage par occlusion. Répétez l'élimination de chaque image ou de chaque image où la caméra ou la scène a été marquée comme "sale".
Nailer