CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

faces, primitives, octree avec DirectX

saleGauss
saleGauss
Niveau 9
04 octobre 2007 à 19:32:14

Bonjour tout le monde !

Voila, je voudrais solliciter votre aide pour un probleme qui me pose probleme depuis très (trop) longtemps.
Je code un petit moteur 3D en c++ avec directX 9.0c.

Cela fait au moins 4 mois que j´essaye de finir l´algo d´un octree mais je n´y parviens pas.

En fait, ce n´est absolument pas l´algo qui est en cause : mon arbre est crée normallement, en decoupant recursivement en 8 chaque box lorsque cela est necessaire (critere en nombre de triangle dedans).

J´arrive aussi à explorer mon arbre pour dessiner (je ne dessine que les box de "dernière génération" -> celles qui n´ont pas de fils, et uniquement celle qui sont visibles)

Le seul truc où je m´arrache les cheveux c´est savoir comment gérer mes triangles.
Je m´explique : au depart j´ai un mesh qui represente ma map.
C´est un type LPD3DXMESH.

J´ai aussi bien sur des
D3DMATERIAL9* MeshMaterials;
LPDIRECT3DTEXTURE9* MeshTextures;
DWORD NumMaterials;
pour mon mesh de base (map entière, je le repete)

Inicialement je le charge avec la methode D3DXLoadMeshFromX().

Bon, maintenant, quand je decoupe mon monde, il faut bien que je recupere les triangles de ce mesh, et que je mette chaques triangles de mon mesh dans la bonne box.
Alors les mettre dans les bonnes box, c´est pas le probleme.
Le probleme c´est je stocke dans quoi ?

Bon avant de chercher comment je les gere par box, je me suis dis que commencer par garder un tableau de tous les triangles de map pourrait me servir pour ensuite les "repartir" dans les bonnes box.
Donc avant de decouper mon monde, je garde uun tableau de tous mes triangles :

LPDIRECT3DVERTEXBUFFER9 Vb;

MyEngine.MapOfScene->Mesh->GetVertexBuffer(&Vb);

CUSTOMVERTEX* _vb;
Vb->Lock(0, 0, (void**)&_vb, D3DLOCK_READONLY);

int max = MyEngine.MapOfScene->Mesh->GetNumVertices();
for(int y=1; y < max; y++)
{

/* save in the engine array */

if (MyEngine.allVertex_size + 1 < allVertex_capacite)
{

MyEngine.allVertex[MyEngine.allVertex_size + 1] = new CUSTOMVERTEX;

MyEngine.allVertex[MyEngine.allVertex_size + 1]->x = _vb[ y ].x;
MyEngine.allVertex[MyEngine.allVertex_size + 1]->y = _vb[ y ].y;
MyEngine.allVertex[MyEngine.allVertex_size + 1]->z = _vb[ y ].z;
MyEngine.allVertex[MyEngine.allVertex_size + 1]->color = _vb[ y ].color;
MyEngine.allVertex[MyEngine.allVertex_size + 1]->tu = _vb[ y ].tu;
MyEngine.allVertex[MyEngine.allVertex_size + 1]->tv = _vb[ y ].tv;

MyEngine.allVertex_size +=1;

}

(j´espere que le copier coller de code passera asser bien).
Donc mon tableau global c´est bien sur allvertex (qui appartient à l´instance MyEngine mais c´est pas important).

Comme vous le voyez je recupere le vertex buffer (de type LPDIRECT3DVERTEXBUFFER9) de mon mesh et je recupere (enfin j´espere) toutes les vertices grace à un CUSTOMVERTEX*.

CUSTOMVERTEX est une struct que j´ai créé ainsi :
struct CUSTOMVERTEX
{

float x, y, z;
DWORD color;
float tu, tv; // Texture coordinates

};

Et bien sur pour que "tout corresponde" entre mes représentations et celles de DirectX, j´ai du faire un :

  1. define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

pour dire quelles étaient les infos qui m´interessaient sur chaque vertex.

Vous remarquerez que je gere ces infos dans le meme ordre (composante xyz, PUIS couleur, PUIS coordonnées de mapping).
La doc directX précise que c´est essentiel.

----------------------------------------------

Question 1:/ En théorie, à ce stade, le tableau allVertex[]
------------
devarit bien contenir toutes mes vertices, non ?
Quand je debugue je trouve des valeurs qui me sembles normales pour quelques vertices au pif de ce tableau.
Par exemple, quelques valeurs que j´ai choisis au pif :

tu : -1; 0; ...
color : (1.062.723.723) ; (3.174.273.719)
x : (-0,987868); (-1,05000); (-1,12235); (-1,20000)
y : -0.800000

Les valeurs des couleurs me semblent très elevées mais je n´ai aucun "repere".
Sachant que la couleur est de type DWORD, qu´en pensez vous ?

--------------------------------------------------
-------

2/ Et donc là, j´en viens à quand je decoupe mon monde.
Je le gere relativement de la meme manière : un tableau de vertices pour chaque "noeud" ou "box" de mon octree (j´appelle ca une box moi).
Et pour remplir bah je fais des tests conditionnels pour savoir quelles vertex doit aller ds quelle box.
(bon au passage je me base pas sur la liste totale, mais sur la box "du dessus" car une box F fille d´une box mere M ne peut contenir qu´une partie de M au plus, donc autant regarder et faire mes tests conditionnels sur le liste de la box M)

Bon,bref, je remplis des tableaux pour chaque box de la meme manière.

A ce stade, j´ai donc des tableau remplis de vertices (de type CUSTOMVERTEX).

Meme si c´est pas extra comme methode de stockage, d´apres vous, j´ai bien stocké mes vertices là ? Je veux dire c´est convenable meme si il y a surrement mieux comme représentation (un vector serait surrement plus approprié mais c´est pas le probleme), non ?

------------
Question 3 (là où je veux en venir) :
Quand je vais vouloir dessiner (plus tard), il faudra que je dispose d´un vertexbuffer et non d´au pauvre tableau de CUSTOMVERTEX que DirectX ne saura pas afficher.

Donc je dois créer un VertexBuffer à partir de mon tableau de vertices :
A l´heure actuelle je procede ainsi :
Je construit un vertexBuffer à partir du tableau de vertices que j´ai deja ainsi :

HRESULT hr =
MyEngine.Device->CreateVertexBuffer(vertexOfOctree
_size * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_SYSTEMMEM, &vertexBufferOfOctree, NULL) ;

VOID* VB;
int VB_size = 0;

vertexBufferOfOctree->Lock(0, sizeof(vertexOfOctree), (void**)&VB, 0); // On va utiliser VB pour remplir vertexBufferOfOctree

// nb : vertexOfOctree c´est ce qu´on a obtenu grace aux fonctions qui crées l´arbre. C´est un tableau de vertices.

memcpy(VB, vertexOfOctree, vertexOfOctree_size * sizeof(CUSTOMVERTEX)); // On copie nos vertex dans VB, et donc dans vertexBufferOfOctree

vertexBufferOfOctree->Unlock();

Je précise que VertexBufferOfOctree est de type LPDIRECT3DVERTEXBUFFER9.

Est-ce que d´apres vous j´ai donc bien créé un vertex buffer à partir du tableau de vertices que j´avais (
vertexOfOctree).

Etes vous d´accord avec ma methode créer un vertex buffer à partir d´un tableau de vertex (de type CUSTOMVERTEX) ?

----------------------------------
Question 4:/

Et donc maintenant que j´ai des vertexbuffer pour chaque box (en fait uniquement pour chaque bos "de dernière génération qar je ne risque d´afficher QUE elles), je peux tenter d´afficher ce que lon voit.
Immaginons que je dois dessiner les box 1, 4 et 9.
(J´ai exploré recursivement mon arbre comme il faut pour determiner ca et j´ai bien sur vérifié que ces box sont visibles avec un tel obervateur).

Et bien pour une box, j´affiche son vertexBuffer ainsi (3etapes):

MyEngine.Device->SetStreamSource(0, vertexBufferOfOctree, 0, sizeof(CUSTOMVERTEX));

MyEngine.Device->SetFVF(D3DFVF_CUSTOMVERTEX);

MyEngine.Device->DrawPrimitive(D3DPT_TRIANGLESTR
IP, 0,vertexOfOctree_size -2);

Alors là, les questions importantes :

bon, j´ai trouvé que pour dessiner des triangles strip la valeur (nbvertex - 2) marche bien comme valeur de primitives à dessiner, mais me demander pas trop pourquoi.

J´ai essayé de dessiner avec la primitive ligne (et donc avec autant de primitives à dessiner que de vertices) mais ca ne arche pas et declanche une xception que je ne comprend pas.

Enfin bref, pour l´instant j´ai tenté le triangleStrip.
Pourquoi ?
Car c´est le seul truc qui me donne quelque chose à l´écran.

Le pb me direz vous ?
C´est que sur la map que je tente de charger, avec tout ce que je vous ai decris plus haut, et bien je ne vois "qu´un plan" de la map : une coupe à un y donné si vous voulez.
Enfin, je simplifie un peu, en fait je vois quelques deformations aussi mais globalement on dirait une "coupe" qu´on voit.

Je ne comprend vraiment pas pourquoi.

Donc les 2 questions ultimes :
-Pourquoi ne puisje pas dessiner la primitive que je veux ? (trianglefan, strip, ligne..) comme primitive de base ?
Quelle sont les bonnes valeur à mettre dans le parametre "nombre de primitives à dessiner". (c´est bien sur une fonction du nombre de vertices)

-Pourquoi avec la methode actuelle le prog tourne mais avec une map deformée et en "coupe" dans un plan ?

    1. ##########################################

Epilogue :

je m´excuse pour la longueur du post mais je n´arrive vraimment à rien depuis très longtemps et je sais qu´il y a des personnes très douées sur ce forum qui ne seront pas impréssionnées pas mon code tout pourri et part la longueur de ce post.

Vous aurez bien compris que ce qui me bloque dans l´histoire ce sont des pb des gestion des primitives et des vertexbuffer puisque mon algo d´exploration est hors de cause (j´ai débuggué la création de l´arbre : il se crée normallement).

J´espere sincerement que vous pourrez m´aider.
N´hésitez pas à me poser des questions si vous ne m´avez pas suivi.
merci bcp.

Fvirtman
Fvirtman
Niveau 10
04 octobre 2007 à 20:04:09

Oula ! Quel post !

Je t´avouerai que je ne suis pas bien compétent pour répondre (et oui, a la fac, les boycotteurs de microsoft qui me servaient de prof ne nous ont enseigné QUE OpenGL, et perso, il est vrai que j´aime bien OpenGL, et que, comme j´ai eu la chance d´etre embauché tout de suite apres mes études, je n´ai pas eu vraiment de temps pour moi pour approfondir DirectX, j´avais juste survolé un jour pour essayer...)
-> je leur en veux aux profs : leur boycott ou leur opinion politique n´a, selon moi, pas a handicaper un étudiant qui a envie de voir un peu de tout. Bon, je ne vais pas faire le débat la dessus....

Si j´avais a faire ça avec OpenGL, je pourrai te suggérer quelques résolutions (donc a toi de voir si tu as l´équivalent sous DirectX)
Sous OpenGL, il y a ce qu´on appelle les glList : en fait, quand tu as un mesh, et que, de toute façon, tu le rendras toujours intégralement, tu peux "monter" ce mesh directement dans la carte graphique : ensuite, tu peux le rendre (via une matrice pour le rendre a un autre endroit si tu le souhaite) avec un seul appel : et c´est 100% la carte graphique qui bosse -> efficacité garantie.

Donc si j´étais a ta place, je ferais pareil : un arbre, avec, pour chaque noeud, une glList propre a la boite englobante de ce noeud la. Donc découpage du Mesh selon les boites, triangle par triangle : quand un triangle est dans une boite englobante de feuille, je l´ajoute a la liste dans la feuille, quand il chevauche plusieurs boites, je l´ajoute a la liste de la boite commune (donc le premier parent commun des 2 boites). Ensuite, je charge les listes dans la carte graphique, ce qui me permet de speeder sur l´affichage.

Pour les triangles strip et triangles fan, c´est sur que ça permet d´accélérer encore un petit peu. Apres, dilemne : si un strip ou un fan chevauche 2 boites, qu´est ce que je fais ? Soit je garde le strip/fan entier, et j´y met dans la liste du parent commun, soit je découpe le strip/fan pour en mettre le maximum dans les feuilles.... A voir.

Voila, apres, au niveau implémentation, comme je te disais, je ne connais pas trop encore :(
J´espere ne pas avoir été trop hors sujet...

saleGauss
saleGauss
Niveau 9
04 octobre 2007 à 20:55:30

"Oula ! Quel post ! "

-> En effet, domage que je ne l´ai pas rédigé quelques jours avant, il m´aurait surrement valu le prix du post le plus long :D

Tout d´abord merci d´avoir pris le temps de me lire Fvirtman, c´est très sympa.

Pour ce que tu me dis concernant les glList, je vais essayer de me renseigner concernant un equivalent directX.
Le truc qui m´énerve c´est que pour l´instant j´ai l´impression que directX me permet essentiellement 2 choses :
-dessiner à partir de primitives et donc à partir de vertexBuffer.
-dessiner à partir de mesh chargé (.x) ou meme créés à la volée à partir d´un vertexBuffer.
Je n´ai pas parlé de cette deuxieme optique tout à l´heure car tout le debut serait exactement le meme (jusqu´à la création du vertexBuffer à partir de mon tableau de vertex). La seule différence serait qu´au lieu de dessiner ensuite ma primitive, bah je crée 1FOIS un mesh optimisé à la volée à partir de mon vertexBuffer, et après quand je dessine je dessine avec ce mesh et non plus avec mes primitives, ce qui me faciliterait la vie.
Le souvis c´est que j´aimerais bien quand meme arriver à dessiner avec des primitives, c´est quand meme la base.
Sans compter que créer un mesh "à la volée" à partir de mon vertexBuffer obtenu et bien j´ai essayé mais je n´y arrive pas : le pointeur sur mon mesh sensé etre crée est vide, une routine DirectX doit echouer "silencieusement" lorsque je crée ce msh à partir de mon vertexBuffer.

DOnc aller, tant qu´à rajouter une question : est-il préférable de m´acharner tout de suite à faire fonctionner ce "partitionnement" en sous-mesh ou vaut il mieux que je continuer à afficher mes vertexBuffer avec des primitives ?
Je pense que tant que je n´y parviens pas, je ne pourrais pas commencer à créer de mesh à la volée (qui plus est sont optimisabes -> compliqué).

Si tu le souhaites Fvirtman, je peux t´envoyer des captures d´écran de ce que j´obtiens avec mon programme et de ce que je devrias obtenir (avec le meshViewer de DirectX).
Tu arriveras peut etre à "sentir" l´erreur mieux que moi.

Honnetement j´en peux plus de DirectX, leur doc est trop legere et ne rentre pas asser (jamais?) dans des questions reellement techniques comme celles ci.

Si vous avez des idées, ou des pistes de recherche, je suis toujours là et je continurais à passer regulierement.
Ca m´éneeeeerve de rester bloquer la dessus depuis si longtemps ! :D

Vous savez si il y a des connaisseurs de directX qui passent de temps en temps sur le forum ?
En tout cas je l´espere car mon pb c´est reellement directX : comprendre comment il gere les primitives et les verteBuffer.

C´est trop frustant d´avoir un code asser réfléchi en terme d´algo pour créer et explorer l´octree (enfin évolué pour moi : j´en étais asser content) et de ne pas pouvoir voir un resultat correct à cause de ces questions de bas niveau purement technique sur DirectX.

Encore merci à toi et aux futurs posteurs ;- )

LGV
LGV
Niveau 28
04 octobre 2007 à 22:09:06

"il faut bien que je recupere les triangles de ce mesh, et que je mette chaques triangles de mon mesh dans la bonne box."

ca depend de ce que tu fais; pour un landscape static, pourquoi pas (mais baker des VB par node et selectionner la geometrie a coup d´IB dynamic)
si tu veux faire, il faut en plus calculer tous les plans de coupes pour partionner proprement les meshes.

(bref, pour un landscape static c´est pas forcement super ; un geomipmorphing pour un exterieur, ou un solid BSP + portals pour un interieurs sont autrement plus pratiques)

si c´est pour des objets (qui peuvent eventuellement bouger), alors un loose octree irregulier avec adaptative bounding box est le plus efficace.

pour repondre directement aux questions :

1/ "Sachant que la couleur est de type DWORD, qu´en pensez vous ?"
inspecte la valeur en hexa pour intepreter aisement l´ARGB (ou RGBA, ou ca depend, etc. selon tes vertices)

2/ "il y a surrement mieux comme représentation (un vector serait surrement plus approprié mais c´est pas le probleme), non ?"

en effet, qqch de bcp plus proche du format utilise directement par le GPU ; sinon ton CPU va passer son temps a collecter les vertices...

3/ "Etes vous d´accord avec ma methode créer un vertex buffer à partir d´un tableau de vertex (de type CUSTOMVERTEX) ?"

oui sur le principe, mais la gestion des ressources est mauvaise ; cf. la doc du SDK sur les flags des ressources. Des combinaisons de dynamic, managed, write only, etc. permettent de decrire l´utilsation de la ressource pour une utilisation efficace par le hardware

(apres avoir lu la question 4, je pense en fait que ta methode est fausse : tu colles dans un VB un tableau de vertices qui ne correspond a aucune primitive valide. Il faut un VB qui decrivent ta primites, ou un VB de vertices uniques PLUS un IB qui decrit la primitive. Pas evident sans "visualiser" l´erreur)

4/ "pour dessiner des triangles strip la valeur (nbvertex - 2) marche bien comme valeur de primitives à dessiner, mais me demander pas trop pourquoi."

c´est le cas pour toute triangulation reguliere connexe

"J´ai essayé de dessiner avec la primitive ligne"

geometrie non compatible ? recupere l´erreur DX et utilise la D3D error LUT (passe ton DX en debug si ca crash)

"Pourquoi ne puisje pas dessiner la primitive que je veux ? (trianglefan, strip, ligne..) comme primitive de base ?"

je pense que ton VB est mal construit, et le contenu ne correspond pas au type de primite que tu decris ; cf question 2

saleGauss
saleGauss
Niveau 9
04 octobre 2007 à 23:08:53

merci pour ta réponse LGV.

Je pense que tu as très bien compris d´ou vient le probleme : ce sont effectivement mes vertexbuffer qui sont mal construits mais j´ai du mal à comprendre la bonne méthode.

Je pense aussi que les IB pourraient me permettre de conserver ma géométrie, ou plutot de la décrire comme tu dis.

Mais j´avoue ne jamais avoir réussi à comprendre comment ca marchait concraitement.
Du moins, j´ai aucune idée du comment je dois coder le truc pour qu´il me demolisse pas ma géométrie lorsque je vais recuperer mes vertices et les separer dans des vertexBuffer différents.

C´est le probleme que j´ai toujours eu.

concernant les termes un peu techniques :

"ca depend de ce que tu fais; pour un landscape static, pourquoi pas (mais baker des VB par node et selectionner la geometrie a coup d´IB dynamic)
si tu veux faire, il faut en plus calculer tous les plans de coupes pour partionner proprement les meshes."
-> Je vais essayer de me renseigner la dessus car je ne sais pas ce qu´est un landscape static
-> Selectionner la géométrie à coup d´IB dynamique : je pense que ma solution est LA mais aucune idée de comment coder mon truc pour arriver à ce que je voudrais avoir : un mesh découpé en plusieurs vertexBuffer avec une géométrie respectée.
Si un jour tu as un moment pour m´expliquer ca, ca serait très sympa.

"J´ai essayé de dessiner avec la primitive ligne"

geometrie non compatible ?

oui je suis quasi certain que c´est ca : il n´arrive pas à dessiner avec la primitive demandée acr mon vertexbuffer ne doit pas correspndre.
Mais je n´ai aucune idée de comment faire marcher le truc.

Je vais essayer de repenser et de relire ce que tu as mis demain à tete reposée mais je pense qu´il me manque bcp d´infos sur directX en fait pour arriver à coder mon truc (sans recopier un code d´internet).
Ce sont purement les connaissances Dx qui me manquent cruellement.

Ralala tu as l´air de si bien connaitre directX -> j´aimerais bien un ptit cours :)

ps : un detail : comment à tu appris directX ? En cours cours ? avec la doc ? les 2 peut etre ?
Si tu as des poly de cours de fac, essayes de ma faire un signe si tu peux.

Encore merci, mine de rien ca fait du bien de pas rester seul avec son pb !
Et merci d´avoir lu cet horrible post, zetes les vaillants du forum.

Int
Int
Niveau 4
05 octobre 2007 à 00:51:37

La doc la plus complete sur DX c´est MSDN, pas tres pédagogique mais assez detaillé.

LGV
LGV
Niveau 28
05 octobre 2007 à 01:58:16

qq elements de reponse ; j´essayerai qqch de plus complet si je trouve un peu de temps

"ce sont effectivement mes vertexbuffer qui sont mal construits mais j´ai du mal à comprendre la bonne méthode.

Je pense aussi que les IB pourraient me permettre de conserver ma géométrie, ou plutot de la décrire comme tu dis."

rappel sur les VB/IB et primitives. Considerons un ensemble de vertices v0..vn

on les met dans un VB dans l´ordre naturel

cas 1: VB uniquement, triangle list. on affiche les triangles (vm, vm+1, vm+2) , m augmente de 3 en 3. ca nous donne la geometrie:
(v0, v1, v2), (v3, v4, v5), (v6, v7, v8), etc.

cas 2: VB uniquement, triangle strip. on affiche les triangles (vm, vm+1, vm+2) , m augemente de 1 en 1 (et on inverse un triangle sur 2 pour conserver des normales consistantes). ca nous donne:
(v0, v1, v2), (v2, v1, v3), (v2, v3, v4), (v4, v3, v5), etc.

cas 3 : VB uniquement, triangle fan. on affiche les triangles (v0, vm, vm+1), m augemente de 1 en 1. ca nous donne :
(v0, v1, v2), (v0, v2, v3), (v0, v3, v4), etc.

quand on a uniquement des VB, on est souvent amener a dupliquer des vertices pour creer ses triangles.

maintenant pareil mais avec des IB: l´idee est de stocker chaque vertex qu´un seule foix dans le VB, et decrire la geometrie des triangles a afficher par l´index des vertices. Ca permet de "selectionner", entre autres. Exemple: on prend une grille 4x4 des vertices :

v0 v1 v2 v3
v4 v5 v6 v7
v8 v9 v10 v11
v12 v13 v14 v15

si je veux dessiner le quad 5-6-9-10 , il me suffit de faire un IB de 6 indices : 5-9-10 , 5-10-6 , et rendre le VB/IB en triangle list. Je peux aussi faire un IB de 4 indices : 5-9-6-10 , et rendre le VB/IB en triangle strip.
Il n´y pas de "bonne" facon de faire, toujours bien, dans tous les cas ; ca depend des situations, de ce qu´on fait avec ses vertices, etc.

"je ne sais pas ce qu´est un landscape static"

pas la peine de fouiller, faut juste retenir que de la geometrie "static" (qui ne change pas) doit etre stockee dans un format au plus proche possible de ce qu´utilise le hardware. Genre, tu veux un modele unique dans une scene, tu fous ta geometrie en VB/IB et tu n´y touches plus. Quand t´as bcp de geometrie static, tu prepares les groupes de vertices, et tu "collectes" les indices pour generer les batches a dessiner.

"comment à tu appris directX ?"
SDK pendant qq annees ; par la suite en devenant professionnel j´ai pu affiner certains concepts en cotoyant au quotidien des gens qui sont specialises dans ce domaine. En fait au final il y a assez peu de choses, mais c´est important de bien les comprendre (surtout la gestion des ressources !)

bon courage, c´est pas facile a prendre en main, mais apres c´est un plaisir.

saleGauss
saleGauss
Niveau 9
05 octobre 2007 à 22:01:23

Merci infiniment LGV, ton explication est très claire.

Je me pose maintenant une seule question : moi je charge mon mesh et je vais le decouper en plusieurs VB.
Donc si je veux sonserver ma géométrie il faut que je me base sur le VB que je recupere de mon mesh de base ET sur son IB pour pourvoir décrire sa géométrie (et donc eviter d´estropiller les faces dans mon decoupage).
Haaa ok je pense avoir compris.
Donc en fait quand je fesais mon :

MyEngine.MapOfScene->Mesh->GetVertexBuffer(&Vb);

CUSTOMVERTEX* _vb;
Vb->Lock(0, 0, (void**)&_vb, D3DLOCK_READONLY);

sur le mesh de base (pour recuperer ses vertices dans un VB) il faudrait aussi que je fasse la meme chose sur son IB et que dans ma "distribution" des pixels je me base sur l´IB.

Je suis pas sur que je vais reussir à implémenter le truc facilement mais je commcence (je pense) à comprendre le truc.

L´IB decrit donc ma géométrie et me permet de ne pas la "casser" dans ma répartition.
C´est le truc que je n´avais vraimment pas pigé avant.
Je me demandais comment avec juste mes vertex je pouvais prédire commment était ajencées mes faces, car on est bien d´accord sur le fait que avec v1, v2, v3 et v4 j´ai deja quelques possibilités pour dessiner des faces de manière completement différentes.

Je tente d´implémenter ca ce week-end et je reposterais pour dire comment ca se passe.
En tout cas merci bcp, c´est très sympa les gars.

J´espere arriver à faire tourner le truc convenablement bientot pour vous faire essayer une petite scene de mon très jeune semblant de moteur :D

Bonne soirée !

saleGauss
saleGauss
Niveau 9
13 octobre 2007 à 21:46:12

Bonsoir,

Voila, j´ai continué ces derniers jours mon implémentation et j´ai encore qq problemes (le contraire vous aurait étonné, hein :d)
Bien, donc je me base sur mon mesh de base que je découpe en plusieurs VB/IB.
Je procede ainsi :

je m´interesse à chaque VB[ IB[ i ] ] où i varie jusqu´à Mesh->GetNumFaces() * 3
(VB et IB se réfèrent au mesh de base : ma map initiale)

Je met donc ce vertex " dans le bon sous-vertexBuffer ", c´est à dire dans le noeud de l´octree où il doit etre.

Je fais avancer mon pas (i) de 3 en 3, et chaque fois je regarde en fait où est-ce que je doit mettre ce pack de 3 vertex.
Des que j´ai mis un "pack " de 3 vertex dans un noeud, je vais completer le sous-IB de ce noeud en ajoutant les 3 valeurs qui indiquent la position de ce vertex dans LE NOUVEAU VB.

Je précique que je ne duplique pas mes vertex dans mes VB que je crée à la main.
C´est à dire que si je regarde un vertex que j´ai deja mis dedans, bah je l´ajoute pas dans le VB.
Mais bien sur j´ajoute son index dans l´IB.

------- Exemple de ce que je fais à l´heure actuelle : -------

un exemple : VB de base : v0, v1, v2, v3
IB de base : 0, 1, 2, 1, 2, 3, 2, 3, 0

Supposons que v0, v1 et v2 appartiennent à mon noeud.
Et bien avec ma methode voici mon couple VB/IB que je crée ;
VBnoeud : v0, v1, v2
IBnoeud : 0, 1, 2

ma méthode : 1/ prenons VB[ Ib [0] ] soit VB[ 0 ] soit v0.
2/ Appartient il à ce noeud ? Oui (présupposé)
3/ Est il deja mit dans VBnoeud? Non
4/ Je met v0 dans VBnoeu à la position VBnoeud_size

5/Prenons VB[ IB [1] ] soit VB[ 1] soit v1.
6/ Appartient il à ce noeud? Oui (présupposé)
7/ Est-il deja mit dans VBnoeud? Non
8/ Je met v1 dans VBnoeud à la position VBnoeud_size + 1.

9/ Je prend v2
10/ Appartin il à ce noeud ? Oui (présupposé)
11/ Est-il deja mit dans VBnoeud? Non.
12/ Je met v2 dans VB noeud à la position VBnoeud_size + 2

13/ Je rajoute à IBnoeud 3 valeurs :
VBnoeud_size
VBnoeud_size + 1
et VBboeud_size + 2
Je rajoute donc dans IBnoeud les index de mes vertex par rapport à leur emplacement dans leur nouveau VB.

---------------- Fin de mon ex ---------------------

Le soucis ?
Bah je dessine quoi comme primitive de base ?
Je peux utiliser triangleStrip, Fan, list ...
Mais j´avoue n´avoir aucune idée, et aucune des possibilitées ne me donne ma map d´origine, toujours un truc "tout cassé".

Est-ce que je dois savoir quelle primitive de base est utilisée dans mon mesh de base ?

Quelle primitive correspond à ce que j´ai fais dans ma repartition des vertex ?
Je pense que c´est triangle list car je faisait avancer mon pas de 3 en 3.

Quelqu´un comprend mon pb ?
J´ai bcp de mal à l´expliquer.

Est-ce que LGV ou qq d´autre pourrait tenter de me réexplique le dessin avec VB et IB s´il vous plait ?

Je veux dire, vous avez ma methode de remplissage de VBnoeud et de Ibnoeud dans mon exemple.
Dans ma methode de remplissage : -je ne duplique pas les vertex
-je me decris ma géométrie avec un IB.
- Je décris ma géométrie avec un pas de 3 dans mon IB, c´est à dire que VB[ Ib[0] ]
VB[ Ib [1] ]
VB[ ib [2] ] forment une face

et VB[Ib[3] ]
VB[Ib[4] ]
VB[Ib[5] ] forment une autre face.
J´ai donc un pas de 3 dans mon Ib.

Pensez vous que ma methode corresponde à un type de primitive ? (j´espere !)
Je veux juste dire à ma carte graphique de considérer mes packs de vertices comme je viens de le faire plus haut, en me basant sur l´IB et avec un pas de 3

Voila, j´espere qu´un pro me viendra encore en aide ;- )
Plus serieusement, merci à tous ceux qui liront mon poste, et un merci encore plus grand à celui ou ceux qui auront encore le courage de m´éxpliquer ca, à moi : grand noob de la 3d.
Encore désolé pour la longueur des post d´ailleurs mais j´essaye de bien expliquer ce que j´ai fais et ce que je voudrais faire.

Merci à tous, bonne soirée.

saleGauss
saleGauss
Niveau 9
14 octobre 2007 à 18:50:32

Je fais un petit up et j´en profite pour dire que je viens de faire des screnns de ce que j´attend (avec l´outil MeshViewer de DirectX) et de ce que j´obtiens avec mon moteur.
Si quelqu´un qui connait bien les VB/Ib accepterais que je lui envoie ces screens par mail ca serait sympa.

Au fait, j´ai réflechi à la question de mon précédent post et cela me semble claire maintenant : ce sont bien des triangle list que je rend avec Vb et Ib.
En regardant la methode que j´exposais, vous etes bien d´accord pour dire que ce que j´ai construit (vb et ib) correspond bien à une structure en triangle list, non ?

Voila, j´esssaye d´avancer en testant plein de truc mais j´avoue que la gestion des ressources avec directX est asser ardue, et cela m´énerve un peu car sans une représentation "triangle et vertex" je ne peux rien coder de rigolo : c´est à partir de cette représentation là que je peux faire plein de choses derrière.

J´espere que j´arriverais à comprendre le truc.

nb : Je précise qu´en plus des déformations de géométrie actuelle j´ai en plus quelques triangles qui bougent quand je bouge mon perso dans ma map.
Je pense comprendre que c´est un probleme de transformation qui affecte aussi le reste du monde, et pourtant j´ai pris en compte cela en faisant les transformations inveres sur mon mode après avoir bouger un objet (ici mon perso).
Je ne comprend pas bien ce qui se passe, mais bon, c´est pas l´urgence, je verrais ca après si j´arrive deja à rendre ma map à 90% à l´identique.

Aller, je vous laisse.
Bonne soirée !

Franck.

LGV
LGV
Niveau 28
15 octobre 2007 à 13:56:04

je ne suis pas trop passe sur le forum recemment..

les screenshots aideraient a comprendre les problemes. Tu peux les mettre sur un site public d´image hosting et nous coller les liens ; sinon : qomrlsmb@ephemail.net (valable 4 jours a partir de... maintenant !! )

saleGauss
saleGauss
Niveau 9
17 octobre 2007 à 21:38:38

Yep !
mail envoyé aujourd´hui !
Encore merki de t´etre proposé.

saleGauss
saleGauss
Niveau 9
16 novembre 2007 à 17:17:41

Bonjour à tous !

Voila, j´ai encore quelques soucis avec mon octree, mais c´est en fait toujours avec directX.

Le code qui pose pb est très court, je me permet de le poser directement :
(je précise que ce bout de code est executé au tout debut de la construction de l´octree : c´est le moment ou je recupere toutes mes vertices de mon mesh, que je vais dispatcher après dans mes noeuds) :

int max = MyEngine.MapOfScene->Mesh->GetNumVertices(); // Max pour le VB
int max2 = MyEngine.MapOfScene->Mesh->GetNumFaces() * 3; // Max pour l´IB

for(int y=0; y < max; y++)
{

/* save in the engine array */

if (MyEngine.allVertex_size + 1 < allVertex_capacite)
{
MyEngine.allVertex[MyEngine.allVertex_size] = new CUSTOMVERTEX;

MyEngine.allVertex[MyEngine.allVertex_size]->x
= _vb[ y ].x;

MyEngine.allVertex[MyEngine.allVertex_size]->y
= _vb[ y ].y;

MyEngine.allVertex[MyEngine.allVertex_size]->z
= _vb[ y ].z;

MyEngine.allVertex[MyEngine.allVertex_size]->n
x = _vb[ y ].nx;

MyEngine.allVertex[MyEngine.allVertex_size]->n
y = _vb[ y ].ny;

MyEngine.allVertex[MyEngine.allVertex_size]->n
z = _vb[ y ].nz;

MyEngine.allVertex[MyEngine.allVertex_size]->c
olor = _vb[ y ].color;

MyEngine.allVertex[MyEngine.allVertex_size]->t
u = _vb[ y ].tu;

MyEngine.allVertex[MyEngine.allVertex_size]->t
v = _vb[ y ].tv;

MyEngine.allVertex_size +=1;

}

Je précise que mes vertex sont des FVF définies ainsi :

  1. define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1)

et que MyEngine.allvertex[] est un tableau de CUSTOMVERTEX déclaré à une taille enorme (1million).

customvertex est la structure suivante :

struct CUSTOMVERTEX
{

float x, y, z;
float nx, ny, nz;
DWORD color;
float tu, tv; // Texture coordinates

};

Et dans mon test, je charge une map de 1400 vertex à peu près (je l´ai su grace à l´outil MeshView de Dx) et ce morceau de code va planter, à dans la boucle, à un MOMENT ALEATOIRE.
Je veux dire par là que des fois il va planter à 1200, des fois à 1250, des fois vers 1280 (toujours dans les 1200).

Pourtant je fais bien varier y de (0) à (max-1) où max est la valeur représentant le nombre de vertices sur l´objet (obtenu par la methode directX GetNumVertices() ) .

Je ne comprend vraimment pas.
Il y a de la place dans mon tableau.
J´ai l´impression qu´il me reste de la RAM (j´ai 1Go de RAM).
Et en plus ca peut planter à un moment différent de la boucle (valeur de y-plantage différente à chaque fois, et ligne du plantage différente aussi : ca peut etre sur le ->x, sur le ->ny, sur le ->color ...)

Si quelqu´un aurait une piste ce serait trooop gentil !
(j´ose pas trop embeter encore LGV avec ca...)
Merci

saleGauss
saleGauss
Niveau 9
16 novembre 2007 à 17:20:29

aie, détail important, j´aurais du donenr 4 lignes de plus en fait (elles se trouvent juste avant le morceau que je viens de donner) :

LPDIRECT3DVERTEXBUFFER9 Vb;

MyEngine.MapOfScene->Mesh->GetVertexBuffer(&Vb);

CUSTOMVERTEX* _vb;
Vb->Lock(0, 0, (void**)&_vb, D3DLOCK_READONLY);

LGV
LGV
Niveau 28
16 novembre 2007 à 18:39:28

que dit le debugger, exactement ? que valent les valeurs au runtime quand ca "plante" ?

a noter que le code n´est pas tres intuitif ; utiliser "size" pour remplir ton buffer, ignorer des vertices si ca "rentre pas", etc. C´est aussi conceptuellement tres "moche": un tableau de pointeurs, et copie membre par membre.

Tu dois pouvoir ecrire un truc genre ca, qui sera plus clair pour tout le monde :

int nbVertices = mesh->GetNbVertices();
for (int index = 0; index < nbVertices; ++index)
{
engineVB[index] = meshVB[index];
}

et encore, ca c´est pour garder la "logique" de copie la main; mais au final, tout ce que tu fais, c´est de choper 2 pointeurs: un source (la mesh), un destination ("engine"). Un gros memcpy fera l´affaire. En pseudo code :

enginePtr = engineVB->Lock();
meshPtr = meshVB->Lock();
memcpy(enginePtr, meshPtr, numVertices*sizeof(CUSTOMVERTEX));
engineVB->Unlock();
meshVB->Unlock();

saleGauss
saleGauss
Niveau 9
16 novembre 2007 à 19:23:11

Merci LGV.

Le compilo me met : unhandled exception in Myexe.exe : 0xC0000005 : access violation.
Et le debuggeur pointe sur une ligne de ma boucle, aléatoirement.
Et la valeur de y lors du plantage est aussi aléatoire.

La par exemple, je viens de l´executer, et ca s´est arreté ainsi :

  • y = 1204
  • ligne d´arret : sur le "->ny"
  • valeur inspectée : _vb[y].nx = -1.55840 * 10^38

Il y a toujours un moment où e recupere n´importe quoi comme valeurs (comme si les valeurs n´étaient pas définies).
Pourtant les 1200 premieres valaurs sont toujours cohérentes.

Apres par contre...

Je continue à essayer de chercher.

saleGauss
saleGauss
Niveau 9
18 novembre 2007 à 21:35:03

bon, j´en peu plus.
Je suis à bout...

Je ne sais vraimment plus quoi faire avect cette ù*$$$ù^* d´octree.

J´ai changé mon code comme me l´a conseillé LGV, j´ai fais dans le style :

int nbVertices = mesh->GetNbVertices();
for (int index = 0; index < nbVertices; ++index)
{
engineVB[index] = meshVB[index];
}

car memcpy ne semblait pas fonctionner, je ne sais absolument pas pourquoi.
En clair bah apparemment il recopiait rien.

Enfin bref, bon là c´est plus lisible.
Mais le soucis c´est que :

-dans le meilleur des cas ca me deforme tout !
J´analyse à la vollée les valeurs que "j´extrais" de mon VB et je chope des vertex aux coordonnées improbables (je charge un cube pour bien pister l´évolution)

Le pire c´est qu´en plus ca ne dessine pas qq chose qui devrait ressembler à ces valeurs erronées.
Si à la rigueur c´était logique...
Là j´en perd la boule..

-autre cas : plantage au moment de la repartition des vertex dans les noeuds.
Ca foire sur une boucle où pour un noeud fils, je regarde tous les vertex de sa mere, et je look si je dois mettre ce vertex dans le fils.

-dans le pire des cas toujours mon unhandled exception sur le morceau de code donné.

Je précise que l´issue depend de la "map" chargée.

Le pire c´est que mon code est volumineux et qu´il m´est difficile de le présenter en intégralite (d´autant plus que je fais toujours référence à des objets qui ne font pas directement parti de mon implémentation de l´octree).
J´hésite meme à publier le code sur le net, de toute facon qui me volerait un code aussi pourri ?

Peut-etre que transformer le projet en qq chose de libre peut etre interessant.
Mais en meme temps, ca m´enerve, j´aimerais bien comprendre.

Je me demandais du coup si qq aurait le courage de decortiquer mon code, pour me filer un coup de main remarquable.

Je sais bien que c´est caremment enorme ce que je demande : mon code est touffu, parfois dur à lire, et pire que tout codé par un debutant.
J´ai aussi la grosse manie de ne pas decouper mes fcts, donc du coup j´ai des fonctions de 300 lignes.
(ceci car j´ai parfois du mal à penser l´architecure de ce projet)

Je sais pas si après cette courte description y´a des gens suffisamment vaillants pour accepter d´aider le pauvre noob que je suis.
(le condition de noob est toujours dure à vivre :d)

Bon, en plus j´ai pas grand chose à proposer à celui qui arrivera à traquer le/les bugs.
Si : ma reconnaissance absolue et son nom en tant que personne adorable ayant accepter d´aider le pauvre deprimé que je deviens !

Voila, on sait jamais !
Bonne soirée à tous

sn00bino
sn00bino
Niveau 5
20 novembre 2007 à 12:39:48

"et que MyEngine.allvertex[] est un tableau de CUSTOMVERTEX déclaré à une taille enorme (1million). "

je dois comprendre que dans ta classe tu as :
allvertex[1 000 000]; ?

saleGauss
saleGauss
Niveau 9
20 novembre 2007 à 14:13:05

oui et non.
En fait ce ne sont plus des CUSTOMVERTEX mais des CUSTOMVERTEX*, un pointeur c´est quand meme plus léger :D
Bon, je sais que je pourrais par la suite utiliser un vector, qui me permettra de ne pas l´initialiser ainsi, et de pouvoir modifier sa capacité.

Bon, pour mon octree bah j´ai décidé de faire un break.
Je me suis mis à coder un petit exo tout bete pour m´habituer à manipuler VB et IB : je veux :
-charger un mesh
-recuperer ses VB et IB
-extraire de ces VB/IB les info sur mes vertices, et les mettre dans un tableau

-reconstruire des VB/IB à la main, tout en respectant la géométrie initiale.
-Dessiner en primitives, avec mes VB/IB reconstruits.

Car en fait c´ets exactement ce que je fais pour mon octree mais avec autant de couples VB/IB que j´ai de noeuds dans mon arbre, et du coup sans entrainement sur les VB c´est très dur.

J´ai visé un peu dur pour un debut.
J´ai maintenant compris que la gestion des ressources est primordiale, et que je ne peux pas me permettre de sauter cette étape.
Je sens qu´il me faut juste m´acharner un peu plus pour passer ce cap difficile.

Bientot la puissance de Dx sera à moi ! :D

sn00bino
sn00bino
Niveau 5
20 novembre 2007 à 15:59:44

Doit y avoir pas mal de cours sur les VB/IB j´ en avais un bon mais je m´ en souviens plus. Dsl de ne pouvoir t´ aider.

Sous forums
  • Aide à l'achat Mac
  • Macintosh
  • Création de Jeux
  • Programmation
  • Création de sites web
  • Linux
  • Internet
  • Steam Deck
  • Hardware
La vidéo du moment