Moteur 3D améliorer

Discussion forum for the French Hollywood community

Moteur 3D améliorer

Postby ArtBlink » Sat Mar 12, 2011 3:42 pm

Voici le code source amélioré pour afficher des objets en 3D
Code: Select all
; ##############################
; # TUTORIEL 3D AVEC HOLLYWOOD #
; ##############################
; Ouverture d'écran avec choix
; Mode = "ask" : Permet de choisir entre mode fenêtre et mode plein écran
@SCREEN {Mode = "ask", Width = 640, Height = 480,Depth=16}
SetFontStyle(#EDGE, #RED, 1)
HidePointer()
CreateBrush(1,330,100)
SelectBrush(1)
TextOut(#CENTER,0,"LA GUERRE DES ETOILES")
   TextOut(#CENTER,10,"A Hollywood")
   TextOut(0,20,"Touche fléché pour la rotation de l'objet")
   TextOut(0,30,"touche a = Zoom Arrière")
   TextOut(0,40,"touche z = Zoom Avant")
   TextOut(0,50,"touche e = Antialiasing")
   TextOut(0,60,"touche r = Retirer l'Antialiasing")
   TextOut(0,70,"touche t = 3D Surface pleine")
   TextOut(0,80,"touche y = 3D filaire")
   TextOut(0,90,"ctrl + c = QUITTER")
EndSelect
SetFontStyle(#NONE)
; Variables globales : elles sont utilisées pour se déplacer dans les tableaux
; Se sont les curseurs qui vont se modifier en fonction de la touche direction appuyée
ROTX=0
ROTY=0
ROTZ=16
CZ=1
; On initialise et réserve des emplacements mémoire pour les tableaux
; Y'en a beaucoup, car on précalcule beaucoup afin de gagner du temps CPU
; Plus il y aura de précalculation, plus votre moteur sera rapide.
; Si les triangles formant votre objet sont tous identiques, il est même
; possible de précalculer l'effet de lumière ou même mieux, la texturisation
; Se moteur n'est pas le meilleur, il est normalement très facile à optimiser
; Celui qui arrive à précalculer l'effet de lumière augmentera de beaucoup
; la vitesse de se moteur. Regardons ces tableaux de plus près:
   Dim coord[288] ; Coordonnées des X,Y,Z de l'objet soit 96*3
   Dim CO[64] ; Découpage de la rotation en 64 positions (cosX)
   Dim SI[64] ; Découpage de la rotation en 64 positions (SinX)
   Dim P1[510] ; Point à relié, un triangle a 3 points, donc 3*170
; Tableau d'optimisation du calcule du curseur :
; Afin d'éviter les calcules inutiles dans les boucles de PRG, on mets dans 3 tableaux
; les valeurs du curseur pour X,Y et Z
   Dim GP1[170] ; valeurs possible pour le point 1 des triangles
   Dim GP2[170] ; valeurs possible pour le point 2 des triangles
   Dim GP3[170] ; valeurs possible pour le point 3 des triangles
; Tableau des vecteurs de chaques triangles. 3 point en X,Y soit 6 lignes
   Dim TRIE[6]
; Tableau qui va servir au trie, les valeurs de se tableau seront utilisé comme index
; dans les tableaux Tri..[]
   Dim ZM[96] ; Tableau de la valeur moyenne en Z
; Tableaux des coordonnées réels qui vont être utilisé pour Polygone()
; donc enregistré par la suite en TRIE.
   Dim XE[96] ; Tableau coordonnées en X
   Dim YE[96] ; Tableau coordonnées en Y
   Dim ZE[96] ; Tableau coordonnées en Z
   ; Pourquoi ici?! sinon les tableau deviendrait ENORME, car ZM change de valeur tous le temps
   ; Tableau utilisé pour trié l'ordre d'affichage des triangles
   Dim TriX1[170] ; Tableau de trie en X du point 1 de chaque triangle
   Dim TriX2[170] ; Tableau de trie en X du point 2 de chaque triangle
   Dim TriX3[170] ; Tableau de trie en X du point 3 de chaque triangle

   Dim TriY1[170] ; Tableau de trie en Y du point 1 de chaque triangle
   Dim TriY2[170] ; Tableau de trie en Y du point 2 de chaque triangle
   Dim TriY3[170] ; Tableau de trie en Y du point 3 de chaque triangle
   
   Dim TriZ1[170] ; Tableau de trie en Z du point 1 de chaque triangle
   Dim TriZ2[170] ; Tableau de trie en Z du point 2 de chaque triangle
   Dim TriZ3[170] ; Tableau de trie en Z du point 3 de chaque triangle
; VALEURS des coordonnées de l'objet:
; Sa se présente ainsi:
; Coord={
; X1,Y1,Z1,
; X2,Y2,Z2,
; ...
; }
   coord={
   -0.013836,-0.009224,-0.039999,
   0.076100,0.046121,-0.536000,
   0.076100,-0.046121,-0.536000,
   -0.013836,-0.202934,-0.039999,
   -0.034591,-0.009224,-0.039999,
   -0.034591,-0.202934,-0.039999,
   0.055346,-0.046121,-0.536000,
   0.055346,0.046121,-0.536000,
   -0.013836,-0.202934,0.039999,
   0.076100,-0.046121,0.536001,
   0.076100,0.046121,0.536001,
   -0.013836,-0.009224,0.039999,
   0.055346,0.046121,0.536001,
   0.055346,-0.046121,0.536001,
   -0.034591,-0.202934,0.039999,
   -0.034591,-0.009224,0.039999,
   0.041509,-0.341298,0.007999,
   0.041509,-0.249055,0.007999,
   0.152200,-0.249055,0.007999,
   0.172955,-0.313625,0.007999,
   0.041509,-0.249055,0.000000,
   0.041509,-0.341298,0.000000,
   0.172955,-0.313625,0.000000,
   0.152200,-0.249055,0.000000,
   0.172955,-0.202934,0.000000,
   0.172955,-0.202934,0.007999,
   0.172955,-0.027673,0.000000,
   0.172955,-0.027673,0.007999,
   0.193710,-0.027673,0.000000,
   0.193710,-0.027673,0.007999,
   0.193710,-0.285952,0.000000,
   0.193710,-0.285952,0.007999,
   -0.048427,0.451989,0.039999,
   -0.013836,0.451989,0.016000,
   0.013836,0.341298,0.023999,
   -0.048427,0.341298,0.072000,
   0.013836,0.073794,0.023999,
   -0.048427,0.073794,0.072000,
   -0.013836,0.451989,-0.008000,
   0.013836,0.341298,-0.016000,
   0.013836,0.073794,-0.016000,
   -0.048427,0.451989,-0.039999,
   -0.048427,0.341298,-0.056000,
   -0.048427,0.073794,-0.056000,
   -0.048427,0.590353,0.000000,
   -0.069182,0.451989,0.023999,
   -0.083018,0.341298,0.039999,
   -0.083018,0.276728,0.023999,
   -0.083018,0.276728,-0.016000,
   -0.083018,0.341298,-0.024000,
   -0.069182,0.451989,-0.016000,
   -0.048427,0.599577,0.000000,
   -0.083018,0.073794,-0.016000,
   -0.083018,0.073794,0.023999,
   -0.117609,0.083018,0.112000,
   -0.166037,0.083018,0.056000,
   -0.186791,0.083018,0.007999,
   -0.186791,0.083018,-0.008000,
   -0.166037,0.083018,-0.056000,
   -0.117609,0.083018,-0.112000,
   0.013836,0.083018,-0.056000,
   0.055346,0.083018,-0.008000,
   0.055346,0.083018,0.007999,
   0.013836,0.083018,0.056000,
   0.013836,-0.341298,0.056000,
   -0.076100,-0.341298,0.088000,
   -0.117609,-0.267504,0.112000,
   0.055346,-0.341298,0.007999,
   0.055346,-0.341298,-0.008000,
   0.013836,-0.341298,-0.056000,
   -0.117609,-0.267504,-0.112000,
   -0.076100,-0.341298,-0.088000,
   -0.186791,-0.166037,0.007999,
   -0.186791,-0.166037,-0.008000,
   -0.166037,-0.193710,-0.056000,
   -0.166037,-0.193710,0.056000,
   0.055346,0.184485,0.488000,
   0.124528,0.184485,0.488000,
   0.124528,0.184485,0.552001,
   0.055346,0.184485,0.696001,
   0.000000,0.184485,0.552001,
   0.145282,-0.101467,0.552001,
   0.145282,-0.101467,0.488000,
   0.055346,-0.101467,0.488000,
   -0.034591,-0.101467,0.552001,
   0.055346,-0.101467,0.696001,
   0.000000,0.184485,-0.552000,
   0.055346,0.184485,-0.696000,
   0.124528,0.184485,-0.552000,
   0.124528,0.184485,-0.488000,
   0.055346,0.184485,-0.488000,
   0.055346,-0.119915,-0.696000,
   -0.034591,-0.119915,-0.552000,
   0.055346,-0.119915,-0.488000,
   0.145282,-0.119915,-0.488000,
   0.145282,-0.119915,-0.552000
   }
For I=0 To 287
   coord[I]=coord[I]*100
Next

; Les points a relier pour former les triangles
; Sa se présente ainsi:
; P1={
; point 1 du triangle 1,point 2 du triangle 1, point 3 du triangle 1,
; point 1 du triangle 2,point 2 du triangle 2, point 3 du triangle 2,
; ...
; }
; Ces valeurs sont en fait des valeurs de curseur qui vont permettre d'aller chercher
; les valeurs X,Y et Z dans le tableau Coord(). Il y a 170 triangles dans cet objet
; 1 triangle à 3 côtés donc P1 à 170*3=510 valeurs car 510 côtés
P1={
   0,1,2,
   0,2,3,
   4,5,6,
   4,6,7,
   7,1,0,
   7,0,4,
   2,1,7,
   2,7,6,
   3,2,6,
   3,6,5,
   0,3,5,
   0,5,4,
   8,9,10,
   8,10,11,
   12,13,14,
   12,14,15,
   15,11,10,
   15,10,12,
   13,12,10,
   13,10,9,
   14,13,9,
   14,9,8,
   15,14,8,
   15,8,11,
   16,17,18,
   16,18,19,
   20,21,22,
   20,22,23,
   23,18,17,
   23,17,20,
   24,25,18,
   24,18,23,
   26,27,25,
   26,25,24,
   28,29,27,
   28,27,26,
   30,31,29,
   30,29,28,
   22,19,31,
   22,31,30,
   21,16,19,
   21,19,22,
   20,17,16,
   20,16,21,
   18,25,31,
   18,31,19,
   22,30,24,
   22,24,23,
   24,30,28,
   24,28,26,
   31,25,27,
   31,27,29,
   32,33,34,
   32,34,35,
   35,34,36,
   35,36,37,
   33,38,39,
   33,39,34,
   34,39,40,
   34,40,36,
   38,41,42,
   38,42,39,
   39,42,43,
   39,43,40,
   44,44,45,
   44,45,46,
   44,46,47,
   44,47,48,
   44,48,49,
   44,49,50,
   44,50,44,
   44,44,51,
   44,51,51,
   51,51,38,
   51,38,33,
   51,44,41,
   51,41,38,
   41,44,50,
   50,49,42,
   50,42,41,
   49,48,52,
   49,52,43,
   49,43,42,
   48,47,53,
   48,53,52,
   46,35,37,
   46,37,53,
   46,53,47,
   46,45,32,
   46,32,35,
   32,45,44,
   44,51,33,
   44,33,32,
   36,40,43,
   36,43,52,
   36,52,53,
   36,53,37,
   36,37,37,
   54,55,56,
   54,56,57,
   54,57,58,
   54,58,59,
   54,59,60,
   54,60,61,
   54,61,62,
   54,62,63,
   64,65,66,
   64,66,54,
   64,54,63,
   63,62,67,
   63,67,64,
   62,61,68,
   62,68,67,
   61,60,69,
   61,69,68,
   59,70,71,
   59,71,69,
   59,69,60,
   56,72,73,
   56,73,57,
   57,73,74,
   57,74,58,
   58,74,70,
   58,70,59,
   54,66,75,
   54,75,55,
   55,75,72,
   55,72,56,
   69,71,65,
   69,65,64,
   69,64,67,
   69,67,68,
   75,66,65,
   75,65,71,
   75,71,70,
   75,70,74,
   75,74,73,
   75,73,72,
   76,77,78,
   76,78,79,
   76,79,80,
   81,82,83,
   81,83,84,
   81,84,85,
   78,85,79,
   77,81,78,
   76,82,77,
   80,83,76,
   79,84,80,
   85,84,79,
   84,83,80,
   83,82,76,
   82,81,77,
   81,85,78,
   86,87,88,
   86,88,89,
   86,89,90,
   91,92,93,
   91,93,94,
   91,94,95,
   87,91,88,
   88,95,89,
   89,94,90,
   90,93,86,
   86,92,87,
   87,92,91,
   86,93,92,
   90,94,93,
   89,95,94,
   88,91,95,
}
; On commence le travail de précalculation pôur gagner du temps CPU
; Se qui est précalculer sera enregistré dans des tableaux
; Il suffira donc de mettre en lien ses valeurs dans les tableaux
; avec notre moteur 3D
; On précalcule les valeurs Cosinus et Sinus utilisé pour les différentes rotation
; Et hop, on gagne 12*96 fois ses calcules par images
For Local I=0 To 63
   CO[I]=Cos(I*0.1)
   SI[I]=Sin(I*0.1)
Next
; On précalucle les pointeurs, argh!, on gagne 6x96 calcules/images pour les CPT et 13*169 calcules/images pour les GP
For Local I=0 To 169
   Local Cpt1=I*3
   GP1[I]=P1[Cpt1]
   GP2[I]=P1[Cpt1+1]
   GP3[I]=P1[Cpt1+2]
Next
; Tableau contenant 21 couleurs, mettez n'importe quel dégradé de couleur
Dim Couleur[11]
Couleur[0]=$FFFFFF
Couleur[1]=$EEEEEE
Couleur[2]=$DDDDDD
Couleur[3]=$CCCCCC
Couleur[4]=$BBBBBB
Couleur[5]=$AAAAAA
Couleur[6]=$999999
Couleur[7]=$888888
Couleur[8]=$777777
Couleur[9]=$666666
Couleur[10]=$555555
; Première fonction Controle() ou on test certaines touches du clavier
; Chaques touches testé quand elle est pressé renvoie à une fonction définie
Function Controle()
   
   If IsKeyDown("Left")=True Then ROTY=ROTY+1
   If IsKeyDown("Right")=True Then ROTY=ROTY-1
   If IsKeyDown("Up")=True Then ROTX=ROTX+1
   If IsKeyDown("Down")=True Then ROTX=ROTX+1
   If IsKeyDown("*")=True Then ROTZ=ROTZ-1   
   If IsKeyDown("$")=True Then ROTZ=ROTZ+1
   If IsKeyDown("a")=True Then CZ=CZ-1
   If IsKeyDown("z")=True Then CZ=CZ+1

   If ROTX<0 Then ROTX=63
   If ROTX>63 Then ROTX=0
   If ROTY<0 Then ROTY=63
   If ROTY>63 Then ROTY=0
   If ROTZ<0 Then ROTZ=63
   If ROTZ>63 Then ROTZ=0

   If CZ<1 Then CZ=1
   If CZ>10 Then CZ=10

   ; La touche "e" mets en route l'antialiasing d'hollywood
   If IsKeyDown("e")=True Then SetFormStyle(#ANTIALIAS)
   ; La touche "r" enlève l'antialiasing d'hollywood
   If IsKeyDown("r")=True Then SetFormStyle(#NORMAL)
   ; La touche "t" mets en route le remplissage des polygon()
   If IsKeyDown("t")=True Then SetFillStyle(#FILLCOLOR)
   ; La touche "e" enlève le remplissage des Polygon()
   If IsKeyDown("y")=True Then SetFillStyle(#FILLNONE) 
EndFunction

; La fonction principale
Function PRG()
   ; On démarre un chronomètre pour le calcule des FPS
   StartTimer(1)
   ; On lance la fonction controle pour contrôler l'objet
   Controle()
   ; Basculement entre les 2 écrans (doublebuffer)
   Flip
   ; Effacement de l'écran
   Cls
   ; Affichage du texte des indications
   DisplayBrush(1,0,0)
   ; Première Boucle PRG() pour le calcule des 96 points de l'objet
   For Local I=0 To 95 ; 96 points
      ; calcules de trigo...      
         Local Cpt1=I*3
         Local Cpt2=Cpt1+1
         Local Cpt3=Cpt2+1   
      ; Enfin, les valeurs final à utiliser pour le traçage des triangles
      ; On les stocks dans un tableau, et oui, on est obligé pour pouvoir
      ; trier les triangles afin d'afficher en premier les triangles les
      ; plus éloigné suivant l'axe Z
      XE[I]=CZ*((coord[cpt1]*CO[ROTY]+(-coord[cpt2]*SI[ROTX]+coord[cpt3]*CO[ROTX])*SI[ROTY])*CO[ROTZ]+(coord[cpt2]*CO[ROTX]+coord[cpt3]*SI[ROTX])*SI[ROTZ])
      YE[I]=CZ*(-(coord[cpt1]*CO[ROTY]+(-coord[cpt2]*SI[ROTX]+coord[cpt3]*CO[ROTX])*SI[ROTY])*SI[ROTZ]+(coord[cpt2]*CO[ROTX]+coord[cpt3]*SI[ROTX])*CO[ROTZ])
      ZE[I]=CZ*(-coord[cpt1]*SI[ROTY]+(-coord[cpt2]*SI[ROTX]+coord[cpt3]*CO[ROTX])*CO[ROTY])
   Next
   ; Deuxième boucle OBLIGATOIRE : Préparation des tableaux pour le trie
   For Local I=0 To 169 ; 170 triangles
      ; on calcule les Zmoyens qui sont la valeur moyenne en Z de chaque triangle
      ZM[I]=ZE[GP1[I]]+ZE[GP2[I]]+ZE[GP3[I]]
      ; On utilise la valeur de ZM comme index des tableaux Tri..[]
      ; "comme index"  ???? comment cela peut marcher  Certains valeurs de Z vont exister en double et d'autres vont pas exister dans le tableau
      ;  vaudrait mieux multiplier Z par (disons) 100 et stocker l'index du triangle comme partie décimale
      ZM[I]=ZM[I] + I/1000;

      TriX1[ZM[I]]=XE[GP1[I]]
      TriY1[ZM[I]]=YE[GP1[I]]
      TriZ1[ZM[I]]=ZE[GP1[I]]
      
      TriX2[ZM[I]]=XE[GP2[I]]
      TriY2[ZM[I]]=YE[GP2[I]]
      TriZ2[ZM[I]]=ZE[GP2[I]]

      TriX3[ZM[I]]=XE[GP3[I]]
      TriY3[ZM[I]]=YE[GP3[I]]
      TriZ3[ZM[I]]=ZE[GP3[I]]
   Next
   ; On demande à Hollywood de trier le Tableau ZM[] de la valeur la plus petite à la plus grande
   Sort(ZM, Function(a,b) Return (a>b)EndFunction)   
    ;Troisième boucle de traçage
   For Local I=0 To 169 ; 170 triangles
      ; Comme on a trier le tableau ZM de façon croissante,
      ; On utilisera les valeur en X et Y du plus éloigné selon l'axe Z au plus proche ;-)
      
      ; Calcule de trigo... décidement.
      Local ABx=(TriX2[ZM[I]]-TriX1[ZM[I]])
      Local ABy=(TriY2[ZM[I]]-TriY1[ZM[I]])   
      Local ACx=(TriX3[ZM[I]]-TriX1[ZM[I]])
      Local ACy=(TriY3[ZM[I]]-TriY1[ZM[I]])
      ; On calcule la normal de chaque triangle (sur un plan en 2D)
      ; Si la normal est supérieur à 0, alors, on affiche pas le triangle (et encore de l'optimisation)
      
      If (ABx*ACy)-(ACx*ABy)<0
         Local ABz=(TriZ2[ZM[I]]-TriZ1[ZM[I]])
         Local ACz=(TriZ3[ZM[I]]-TriZ1[ZM[I]])
         ; Calcule des normales en X pour l'effet de lumière (sur un plan en 3D)
         Local Nx=(ABy*ACy)-(ABz*ACy)
         ; Calcule des normales en Y pour l'effet de lumière (sur un plan en 3D)
         Local Ny=(ABz*ACx)-(ABx*ACz)
         ; Calcule des normales en Z pour l'effet de lumière (sur un plan en 3D)
         Local Nz=(ABx*ACy)-(ABy*ACx)
         Local D1=Sqrt(Nx^2+Ny^2+Nz^2)
         
         If D1<0
            Local D1=10
            Local Nx=10
         EndIf
         Local Nx=Nx/D1 ; On divise NX par D1 (valeur entre -1 et 1)
         Local Nx=Nx*10 ; on multiplie NX par 10 (valeur entre -10 et 10
         Local Nx=Int(Nx) ; On arrondie la valeur de NX, car l'adresse 7,12 n'existe pas
         If NX<0 Then NX=NX*-1
         Local Xmouse=MouseX()
         Local Ymouse=MouseY()
         ; Ensuite, Comme Nx va être compris entre -10 et 10, on utilise Nx comme valeur
         ; du pointeur pour choisir la couleur du triangle
         ; il doit y avoir une erreur qque part car dans le vaisseau les rectangles composés de 2 triangles (donc orientés pareil) devraient être de la même couleur
         Polygon(Xmouse,Ymouse,{TriX1[ZM[I]],TriY1[ZM[I]],TriX2[ZM[I]],TriY2[ZM[I]],TriX3[ZM[I]],TriY3[ZM[I]]},3,Couleur[Nx])
      EndIf
      
   Next
   ; On efface les tableaux
   ; Car XM est la valeur de l'index de ses tableaux, on efface ses 6 tableaux
   ; afin d'éviter qu'ils ne prennent une taille trop énorme
   

   ; On récupère le temps du chrono   
   Local Temps=GetTimer(1)
   ; On affiche la vitesse en FPS
   TextOut(0,100,Round((1/Temps)*1000))
   TextOut(30,100,"Images par seconde")
   ; On remet le chronomètre à zéro
   ResetTimer(1)
   
EndFunction
; Activation de la technique d'animation double buffer
BeginDoubleBuffer
; Interval pour la fonction PRG de 50FPS ne pas mettre 1, le programme est plus lent... Je sais pas pourquoi
SetInterval(1,PRG,20)
; boucle Infini
Repeat   
WaitEvent()
Forever
; Fin, amusez vous à l'optimiser maintenant que vous avez les explications ;-)
ArtBlink
 
Posts: 426
Joined: Mon Nov 01, 2010 11:37 am
Location: Albert - France

Re: Moteur 3D améliorer

Postby Tarzin » Tue Mar 15, 2011 8:28 pm

Tu progresses en la matière!
167 ips mais sur PC! :D
Power User! :-)
A500/1Mo + 2nd floppy drive
A600/2Mo chip+2Mo Fast/Rom3.1/CF+WB3.1 + Wifi
---
WinUAE 2.x / OS 3.9 BB2 / Amikit 1.x
Amikit "Official" French Translator
http://amifrance.hw.tc
User avatar
Tarzin
 
Posts: 67
Joined: Mon Feb 15, 2010 12:46 pm
Location: Coudekerque-Branche / FRANCE

Re: Moteur 3D améliorer

Postby ArtBlink » Tue Mar 15, 2011 10:35 pm

Sur PC, hollywood est très sympa pour la 3D, mais comme tu as vu sur le forum, Andreas nous dis que la gestion des brush et commande de traçage ne sont pas optimisé, donc il est dommage que se soit si lent...
ArtBlink
 
Posts: 426
Joined: Mon Nov 01, 2010 11:37 am
Location: Albert - France


Return to French forum

Who is online

Users browsing this forum: No registered users and 1 guest

cron