Liste de sommets normales ou indexées? [D3D] - Programmation
Marsh Posté le 24-11-2001 à 17:15:29
Citation : |
po compris....
Citation : |
pour ça oui, en fait, au chargement du modèle: (ou par ton importateur de modèles)
1) tu matiens pour chaque vertex quel sont les facettes qui l'utilise comme un de ses sommets.
implémentation:
a) tu charges les vertex avec leur liste de facettes
associées vide
b) tu charges les facettes, 3 indices a,b,c de vertexs
pour chaque vertex a,b,c tu ajoutes l'indice de la facette
dans la liste de facette associées.
2) une fois que tu as la liste des facettes pour chaque vertex, tu calcules le vecteur normal de chaque facette. (normalisé de le vecteur) (peut être fait au b) )
3) tu associes un vecteur normal pour l'éclairage de gouraud à chaque vertex, vecteur qui est la somme normalisée de chaque vecteur de normal des facettes associées...
alors, là attention... il faut gérer un angle limite. à savoir que par exemple si tu prends 2 facettes perpendiculaires, un cube, ben ça va pas être terrible, donc moi j'ai fait:
1) la première facette est utilisée comme vecteur normal de référence. (le vecteur normal du vertex est intialisé à cette normale)
2) pour les autres facettes (autres vecteur normaux):
si l'angle formé entre la normale de référence est dans l'angle limite (mettons 30° un bon angle dans la pratique) on l'ajoute.
si l'angle est supérieur, on crée une copie du vertex si elle n'existe pas (1 seule copie), la facette ast ajoutée à la liste et on modifie la facette pour qu'elle utilise ce vertex.
comme on balaye tous les vertexs (même les nouveaux créés comme ça), ça marche.
par exemple imaginons la config suivante:
200 points
pour le point 8:
1ère facette de la liste, numéro 64: prise comme facette de base
2ème , 65 : dans l'angle limite avec la 1ère
3 , 70 :non
4 , 75 : non
5 , 80:non
comportement de l'algo, pour le point 8:
facette 1: (64)
elle est utilisé comme "base", la normale du vertex est initialisée avec.
2: (65), elle est dans l'angle limite, on ajoute
3: elle l'est po, on copie le vertex (si y'a po déjà une copie), la copie va se retrouver > 200, mettons 210...
le sommet incriminé de de la facette est mis à 210
le facette 3, 70 est ajoutée à la liste des facettes de 210.
4: idem, mais le vertex copié existe, on ajoute la facette à la liste de 210, et on modifie le sommet 75
5: idem.
maintenant on arrive sur 210, on a:
facette 1: 70
2: 75
3: 80
à la facette 1 (70): prise comme base
facette 2 (75) : dans l'angle limite on ajoute
facette 3 (80) : elle l'est po !!!! on copie le vertex => vers 211 par exemple et la facette 80 est mise en 1ière facette dans la liste du nouveau vertex...
par effet de cascade, on crée ainsi des vertex quand on a affaire à une facette "hors-angle".
pour un vertex si on a des facettes "hors-angle", elle sont réssignées à une recopie, et cette recopie une fois qu'on va passer dessus, peut générer de nouveau un recopie avec
les facettes qui ne sont toujours pas dans l'angle (avec la normale de la facette qui a été prise comme référence)
-----
sinon c'est le principe de l'ombrage de gouraud....
on associe à chaque vertex une normale qui une normale "moyenne" de toutes les facettes utilisant le vertex.
[edtdd]--Message édité par bjone--[/edtdd]
Marsh Posté le 24-11-2001 à 17:23:19
pour ton premier problème, en DirectX 8, avec une carte T&L, l'implémentation est comme ça:
un vertex buffer qui un tableau de vertexs comme ça:
{
float x,y,z; // la position spaciale
float nx,ny,nz; // le vecteur normal du vertex (gouraud rulez)
... d'autres trucs (float u,v: coordonnées de texture)
}
et des indexs buffers, qui sont des tableau d' unsigned int (32bits) ou short (16bits), qui indiquent les sommets à utiliser lors du trançage....
pi tu les utilises comme ça:
transforme_et_éclaire_bordel(monchti_vertex_buffer,YA_UNE COORDONNEE_ET_UNE_NORMALE);
trace_moi_ça_et_vite(monchti_index_buffer,CEST_DES_TRIANGLES);
[edtdd]--Message édité par bjone--[/edtdd]
Marsh Posté le 24-11-2001 à 17:44:50
pour l'algo qui génére les normales de chaque vertex, je crois que l'implémentation suivant est meilleure:
En fait non, maintenant que je viens de vérifier que le code de la première solution marche très bien
pour chaque vertex:
{
float x,y,z; // pos
float nx,ny,nz; // vexteur normal final
float tnx,tny,tnz; // temporaire
int vsuivant; // vertex recopié suivant (même position
// spaciale
}
1) chargement des vertexs:
->x,y,z du fichier
->nx,ny,nz, tnx,tny,tnz = 0
-> vsuivant = -1
2) chargement des facettes
-> calcul du vecteur normal
si le vecteur normal est inconsistant on ignore la facette
(ce que j'appelle un vecteur normal inconsistant serait une facette qui utilise 2 points qui ont la même position => ligne)
-> on crée une facette dans la liste
-> pour chaque vertex a,b,c
si nx,ny,nz == 0, alors (première facette assignée au vertex)
nx,ny,ny, tnx, tny, tnz = vecteur normal facette
si nx,ny,nz <> 0, alors (y'a déjà des facettes qui "utilisent" le point)
(******)
teste angle (produit scalaire) entre nx,ny,nz et notre normale de facette si angle < à notre angle limite (30°)
=> ajouter normale à tnx,tny,tnz
sinon (va ptet falloir faire un autre vertex), est ce que vsuivant <> -1 (y'a un vertex copié suivant)
dans ce cas, on refait (*****), le test de l'angle sur le vertex suivant
(on va parcourir comme ça tout les vertexs qui sont des copies)
si vsuivant == -1 (pas de vertex copié), bin fo le copier
on copie => indice dans vsuivant...
nx,ny,nz,tnx,tny,tnz du nouveau vertex = vecteur normal de la facette...
(vsuivant du nouveau vertex = -1)
et le sommet incriminé de la facette est mis à l'indice du nouveau vertex.
on gros, ça doit marcher....
je vais aller corriger mon code...
a oui à la fin le bon vecteur normal par vertex est tnx,tny,tnz normalisé.
[edtdd]--Message édité par bjone--[/edtdd]
Marsh Posté le 24-11-2001 à 18:43:38
(pour répondre à toutes tes questions)
excuse, pour ta première question, c'est vaux-t-il mieux faire du DrawPrimitive sans IndexBuffer, que du DrawIndexedPrimitive avec IndexBuffer ?
bin je dirais, que par IndexBuffer le moteur géomtrique doit avaler l'index buffer, ça prends de la bande-passante, alors que sans indexbuffer, tu économises de la bande passante, MAIS il se peut que tu doives recopier plusieurs fois le même vertex puisque tu ne peux pas revenir à un ancien vertex. et du coup tu regénéres de la bande-passante et du temps avec + de vertexs à transformer. donc là fo bencher, et/ou tester au cas par cas.
d'un autre coté, sans indexbuffer, la carte est obligé de transformer les vertexs comme ils arrivent, alors qu'avec un index buffer, tu peux revenir sur des points déjà transformés et bénéficier du cache à vertexs.
moi, pour l'instant je fais de l'indexbuffer 16 bits.
et n'oublies pas que l'on peut gagner pas mal en perfs en faisant des rafales de strips ou de fans....
mais il faut que la rafale soit suffisamment longue (en triangles/vertexs) pour rentabiliser l'augmentation des appels des DrawPrimitive. (et réorganiser les vertexs si tu passes par un IndexBuffer)
ça te va comme réponses (je sais po je suis cho)
[edtdd]--Message édité par bjone--[/edtdd]
Marsh Posté le 24-11-2001 à 18:55:32
juste pour dire qu'il faut eviter les index buffer 32bits (du moins pour le moment), me semble que ca aide po les perfs (si tant est que la carte supporte, ce qui est deja pas sur)
edit : t sur que les fan c conseillé ? je suis pas convaincu que ce soit le top (pis de toute facon, c plutot rare comme utilisation, je trouve...)
[edtdd]--Message édité par chrisbk--[/edtdd]
Marsh Posté le 24-11-2001 à 18:57:50
pis por les fan (cf edit ?)
Bon, bref, je vous laisse, je retourne a mes plug in 3ds ( je veuuux paaas . Dieu que c relou quand meme....)
Marsh Posté le 24-11-2001 à 19:04:11
bin les fans, d'un point de vue dépendances mémoire, ça se vo avec le strip (1 vertex=>1 triangle, puis 2 "pentes" à recalculer à chaque fois pour les 2).....
pi j'ai po vu de recommendations de la part de grosoft/nvidia/ati....
disons que moi, pour l'instant j'avale des .ASC (début de début de moteur), et je génére un max de strips, puis un max de fans, et enfin le reste en triangles indépendants..... donc priorité aux strips..
par contre il faudra que je benche les strip & les fans sans passer par des IndexBuffer.
j'ai les CDs de 3DS Max 4 ce we (enfin j'ai po l'adsl )
[edtdd]--Message édité par bjone--[/edtdd]
Marsh Posté le 24-11-2001 à 20:46:38
Ben c pas le pied...
je viesn enfin de finir de decortiquer un sample du sdk (1500 lignes avec un taux de commentaire assez bas, le tout codé exactement comme je n'aime pas, super ) et donc pour tout refaire a ma sauce ca va etre la joie .
Enfin g du doliprane .....
(pour le coup je crois que j'aurais meilleur tps de faire mon editeur mais bon, melangeons pas tout)
Marsh Posté le 24-11-2001 à 21:24:33
dis-moi, le sdk il est sur les cd de base de 3ds ?
ou fo se le trouver ailleurs ?
Marsh Posté le 24-11-2001 à 21:56:16
je l'ai eu avec, mais bon, ca depend du CD (je sais que pour le 3 je l'ai eu a part)
Marsh Posté le 25-11-2001 à 00:50:32
arf zute alors, normalement on va m'amener que 2 cds....
c'est ptet pour ça, j'ai cru comprendre que discreet faisait payer le sdk de 3dsmax & gmax. (dommage & normal)
Marsh Posté le 25-11-2001 à 02:08:20
chrisbk a écrit a écrit : juste pour dire qu'il faut eviter les index buffer 32bits (du moins pour le moment), me semble que ca aide po les perfs (si tant est que la carte supporte, ce qui est deja pas sur) |
Pour savoir si la carte supporte il y a un champ dans
le D3DCAPS8.
A+
LEGREG
Marsh Posté le 23-11-2001 à 22:23:22
Dans mon programme C++, je charge des fichiers .ASE pour les afficher dans mon moteur 3D en cours de réalisation.
Je me suis posé une question, pour le moment je crée une liste de sommets grâce aux sommets indexés du fichier .ASE. Serait-il plus judicieux de les garder en indexé? Quelle version est la plus rapide à afficher?
Dernier point, comment spécifie-t-on les normales d'un sommet indexé sachant qu'il peut appartenir à plusieurs faces qui n'ont pas les mêmes directions?