Moteur 3D améliorer

Discussion forum for the French Hollywood community
Post Reply
ArtBlink
Posts: 484
Joined: Mon Nov 01, 2010 10:37 am
Location: Albert - France
Contact:

Moteur 3D améliorer

Post by ArtBlink »

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 ;-)
User avatar
Tarzin
Posts: 112
Joined: Mon Feb 15, 2010 11:46 am
Location: Dunkerque / FRANCE
Contact:

Re: Moteur 3D améliorer

Post by Tarzin »

Tu progresses en la matière!
167 ips mais sur PC! :D
A500 / A600 / A1200 / SAM440
WinUAE OS3.9 (AmiKit) / OS4.1FE (FlowerPot)
---
https://twitter.com/TarzinCDK
ArtBlink
Posts: 484
Joined: Mon Nov 01, 2010 10:37 am
Location: Albert - France
Contact:

Re: Moteur 3D améliorer

Post by ArtBlink »

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...
Post Reply