Page 1 sur 2

Taille des Sprites 3D

Publié : dim. 09/déc./2007 11:00
par Thyphoon
Bonjour,

ça fait déjà un bout de temps que je manipule les sprites 3D mais il me reste des questions sans reponse.

les Sprites 3D doivent t'il vraiment toujours être carré ? doit t'elle toujours être des dimensions suivante ? 16x16, 32x32, 64x64,128x128,256x256,512x512 ?
Peux t'on faire des sprite de 300x300 ?

Si on veut afficher avec un sprite 3D une image qui fait 300x100 comment fait-on ? est ce que ce n'est pas idiot de faire un sprite3D de 300x300 dans le quel je colle mon sprite de 300x100 ?

j'ai l'impression que les cartes graphiques recente supporte n'importe quel taille de sprite (même si pas carré). Est ce que c'est coup de chance ou bien on peut le faire ? parcontre si le sprite n'est pas carré avec la fonction rotatesprite3D alors l'image est toute deformé !

merci d'avance si vous m'apportez des eclaircissements !!

:P

Re: Taille des Sprites 3D

Publié : dim. 09/déc./2007 11:22
par beauregard
Thyphoon a écrit :j'ai l'impression que les cartes graphiques recente supporte n'importe quel taille de sprite (même si pas carré). Est ce que c'est coup de chance ou bien on peut le faire ? parcontre si le sprite n'est pas carré avec la fonction rotatesprite3D alors l'image est toute deformé !
l'intérêt d'un sprite3D, réside dans le fait d'être manipulé( transparence, zoom, rotation), donc je te confirme qu'il est tout à fait logique de respecter les tailles préconisés.

Peurbasique est à l'origine un programme de test de sprite3D, qui est devenu par la force des choses un jeu.
exemple de rotation avec #pic d'une taille de 16*16:
http://www.purebasic.fr/french/viewtopi ... 30&start=0

Code : Tout sélectionner

 ; Affichage clone elice si existe.
 ForEach elice()
 zutB+1
   elice()\x=elice()\x+elice()\sensx ; fait avancer les elices
   elice()\Y=elice()\Y+elice()\sensy
     
   ; +24= position par rapport à l'elice ; +40 diamètre de la rotation de pic. 

  If elice()\sr=0
   RotateSprite3D(#pic3D, -tourne, 0)
   DisplaySprite3D ( #pic3D , elice()\x+24+40*Sin(tourne*0.0174532925), elice()\Y+24+40*Cos(tourne*0.0174532925),255)
   RotateSprite3D(#pic3D, -tourne2, 0)
   DisplaySprite3D ( #pic3D , elice()\x+24+40*Sin(tourne2*0.0174532925), elice()\Y+24+40*Cos(tourne2*0.0174532925),255)
  EndIf
  If elice()\sr=1
   RotateSprite3D(#pic3D, -tournf, 0)
   DisplaySprite3D ( #pic3D , elice()\x+24+40*Sin(tournf*0.0174532925), elice()\Y+24+40*Cos(tournf*0.0174532925),255)
   RotateSprite3D(#pic3D, -tournf2, 0)
   DisplaySprite3D ( #pic3D , elice()\x+24+40*Sin(tournf2*0.0174532925), elice()\Y+24+40*Cos(tournf2*0.0174532925),255)
  EndIf
     
   DisplaySprite3D ( elice()\id , elice()\x, elice()\Y, 255) 
rotation des sprites #pic3D, qui de plus tournent autour du clone sprite elice( voir Procedure Fclonee() ; elice 64*64 ).

Publié : dim. 09/déc./2007 11:50
par comtois
tout dépend de la diffusion que tu souhaites donner à ton jeu, si tu veux qu'il tourne sur un max de config, tu devrais respecter la règle, sinon effectivement sur les cartes récentes il n'y a pas de soucis ,tu peux donner des tailles rectangulaires et non multiples de 2.

Publié : dim. 09/déc./2007 11:56
par Thyphoon
@Beauregard:merci pour l'exemple. j'avais déjà testé ton jeu. C'es très sympa (l'idée comme la réalisation)
@comtois: merci comtois. C'est un peu ce que je pensais.
Mais que préconises-tu pour manipuler en sprite 3D une image part exemple de 300x100 ? sachant qu'on a besoin de la fonction rotatesprite3D ?

Merci d'avance

Publié : dim. 09/déc./2007 12:18
par Backup
pas obligé d'etre Carre !!
mais il doit etre un multiple de 16

on peut tres bien faire un sprite 512x128 ou 32x512... :)
300x100 comment fait-on ?
ben tu créé un sprite le plus approchant !! multiple de 16

soit 320x128

Publié : dim. 09/déc./2007 12:21
par Thyphoon
Dobro a écrit :pas obligé d'etre Carre !!
mais il doit etre un multiple de 16

on peut tres bien faire un sprite 512x128 ou 32x512... :)
très interessant ça. j'étais perssuadé d'avoir lu dans la doc que ça devait être carré lolllll :lol: En tout cas c'est une bonne nouvelle je vais testé voir si ça marche avec rotatesprite3D si le sprite est pas carré !! :o)

Publié : dim. 09/déc./2007 12:23
par djes
Il faut vraiment respecter les dimensions imposées. J'ai dû à de multiples reprises revoir mes programmes à cause d'incompatibilités sur certaines cartes (même récentes!). Les effets sont désastreux, qui vont de la corruption de l'affichage, à la disparition de la transparence, ou au non affichage pur et simple.

Ce n'est PAS une limitation de Purebasic, mais une contrainte DirectX liée aux cartes graphiques.

Dans ton cas, pour un sprite de 300x100, si tu dois faire une rotation, il te faut prendre 512x512 (attention au centre de rotation, si tu dois le bouger, utilise la lib supersprite de CPL Bator).

Si tu ne dois pas faire de rotation et que tu as un peu de courage, tu peux faire un sprite de 256x256 + un de 128x128, ou 3 de 128x128.

Publié : dim. 09/déc./2007 12:28
par Backup
ce programme te montre que c'est possible !! :D
CreateSprite(0,128,64,#PB_Sprite_Texture)

Code : Tout sélectionner

Structure vertex
    sx.f
    sy.f
    sz.f
    rhw.f
    Color.l
    specular.l
    tu.f
    tv.f
EndStructure

Structure PB_Sprite3D
    Texture.l         
    Vertice.vertex[4]
    width.w
    height.w
EndStructure

Structure PB_Sprite3DEX
    No.l
    AA.f:AB.f:AC.f:AD.f
    DA.f:DB.f:DC.f:dd.f
    Pivot_x.f
    Pivot_y.f
EndStructure





Procedure Distance(x1,y1,x2,y2)
    Protected Result.f
    Result = Sqr(  Pow(x1-x2,2) + Pow(y1-y2,2) + Pow(z1-z2,2) )
    ProcedureReturn Result
EndProcedure


Procedure.f ReturnAngle(x1.f,y1.f,x2.f,y2.f)
    a.f = x1-x2
    b.f = y1-y2
    c.f = -Sqr(a*a+b*b)
    angle.f = ACos(a/c)*180/#PI
    If y1 < y2 : angle=360-angle : EndIf
    ProcedureReturn Abs(angle - 360)
EndProcedure


Procedure Sprite3DModifyPivot(*SpriteID.PB_Sprite3DEX,x.f,Y.f)
    Protected *VertexSprite.PB_Sprite3D = IsSprite3D(*SpriteID\No)
    
    *SpriteID\AA = ReturnAngle(*VertexSprite\Vertice[0]\sx,*VertexSprite\Vertice[0]\sy,x,Y)
    *SpriteID\AB = ReturnAngle(*VertexSprite\Vertice[1]\sx,*VertexSprite\Vertice[1]\sy,x,Y)
    *SpriteID\AC = ReturnAngle(*VertexSprite\Vertice[2]\sx,*VertexSprite\Vertice[2]\sy,x,Y)
    *SpriteID\AD = ReturnAngle(*VertexSprite\Vertice[3]\sx,*VertexSprite\Vertice[3]\sy,x,Y)
    
    *SpriteID\DA = Distance(*VertexSprite\Vertice[0]\sx,*VertexSprite\Vertice[0]\sy,x,Y)
    *SpriteID\DB = Distance(*VertexSprite\Vertice[1]\sx,*VertexSprite\Vertice[1]\sy,x,Y)
    *SpriteID\DC = Distance(*VertexSprite\Vertice[2]\sx,*VertexSprite\Vertice[2]\sy,x,Y)
    *SpriteID\dd = Distance(*VertexSprite\Vertice[3]\sx,*VertexSprite\Vertice[3]\sy,x,Y)
    
    *SpriteID\Pivot_x=x
    *SpriteID\Pivot_y=Y
EndProcedure

Procedure CreateSprite3DEX(Sprite3D)
    Protected *VertexSprite.PB_Sprite3D = IsSprite3D(Sprite3D)
    Protected *VertexSpriteEX.PB_Sprite3DEX = AllocateMemory(SizeOf(PB_Sprite3DEX))
    
    *VertexSpriteEX\No = Sprite3D
    
    
    
    SizeW.f = *VertexSprite\width/2
    SizeH.f = *VertexSprite\height/2
    
    
    *VertexSpriteEX\AA = ReturnAngle(*VertexSprite\Vertice[0]\sx,*VertexSprite\Vertice[0]\sy,SizeW,SizeH)
    *VertexSpriteEX\AB = ReturnAngle(*VertexSprite\Vertice[1]\sx,*VertexSprite\Vertice[1]\sy,SizeW,SizeH)
    *VertexSpriteEX\AC = ReturnAngle(*VertexSprite\Vertice[2]\sx,*VertexSprite\Vertice[2]\sy,SizeW,SizeH)
    *VertexSpriteEX\AD = ReturnAngle(*VertexSprite\Vertice[3]\sx,*VertexSprite\Vertice[3]\sy,SizeW,SizeH)
    
    *VertexSpriteEX\DA = Distance(*VertexSprite\Vertice[0]\sx,*VertexSprite\Vertice[0]\sy,SizeW,SizeH)
    *VertexSpriteEX\DB = Distance(*VertexSprite\Vertice[1]\sx,*VertexSprite\Vertice[1]\sy,SizeW,SizeH)
    *VertexSpriteEX\DC = Distance(*VertexSprite\Vertice[2]\sx,*VertexSprite\Vertice[2]\sy,SizeW,SizeH)
    *VertexSpriteEX\dd = Distance(*VertexSprite\Vertice[3]\sx,*VertexSprite\Vertice[3]\sy,SizeW,SizeH)
    
    ProcedureReturn *VertexSpriteEX
EndProcedure


Procedure RotateSprite3DEX(*SpriteID.PB_Sprite3DEX,angle.f)
    Protected *VertexSprite.PB_Sprite3D = IsSprite3D(*SpriteID\No)
    Protected SizeW2.l,SizeH2.l
    If angle = 0 Or angle = 180
        *SpriteID\Pivot_x = *VertexSprite\width/2
        *SpriteID\Pivot_y = *VertexSprite\height/2
    Else
        *SpriteID\Pivot_x = *VertexSprite\height/2
        *SpriteID\Pivot_y = *VertexSprite\width/2
    EndIf
    *VertexSprite\Vertice[0]\sx = *SpriteID\Pivot_x  - *SpriteID\DA  * Cos((angle+*SpriteID\AA)*#PI/180)
    *VertexSprite\Vertice[0]\sy = *SpriteID\Pivot_y  - *SpriteID\DA  * Sin((angle+*SpriteID\AA)*#PI/180)
    
    *VertexSprite\Vertice[1]\sx = *SpriteID\Pivot_x  - *SpriteID\DB  * Cos((angle+*SpriteID\AB)*#PI/180)
    *VertexSprite\Vertice[1]\sy = *SpriteID\Pivot_y  - *SpriteID\DB  * Sin((angle+*SpriteID\AB)*#PI/180)
    ; ;                                         
    *VertexSprite\Vertice[3]\sx = *SpriteID\Pivot_x  - *SpriteID\dd  * Cos((angle+*SpriteID\AD)*#PI/180)
    *VertexSprite\Vertice[3]\sy = *SpriteID\Pivot_y  - *SpriteID\dd  * Sin((angle+*SpriteID\AD)*#PI/180)
    
    *VertexSprite\Vertice[2]\sx = *SpriteID\Pivot_x  - *SpriteID\DC  * Cos((angle+*SpriteID\AC)*#PI/180)     
    *VertexSprite\Vertice[2]\sy = *SpriteID\Pivot_y  - *SpriteID\DC  * Sin((angle+*SpriteID\AC)*#PI/180)
    
EndProcedure



InitSprite() : InitSprite3D() : InitKeyboard()
If OpenWindow(0, 0, 0, 800, 600, "Un écran dans une fenêtre...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    If OpenWindowedScreen(WindowID(0), 0, 0, 800, 600, 0, 0, 0)
    Else
        MessageRequester("Erreur", "Impossible d'ouvrir un écran dans la fenêtre!", 0)
        End
    EndIf
EndIf

;{ A
CreateSprite(0,128,64,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(0))
Box(0,0,64,64,RGB(255,0,0))
Box(64,0,64,64,RGB(255,255,0))
Box(0,0,10,10, $FF0000)
StopDrawing()
CreateSprite3D(0,0)
a = CreateSprite3DEX(0)
;}
;{ B
CreateSprite(1,128,64,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(1))
Box(0,0,64,64,RGB(255,0,0))
Box(64,0,64,64,RGB(255,255,0))
Box(0,54,10,10, $FF0000)
StopDrawing()
CreateSprite3D(1,1)
b = CreateSprite3DEX(1)
;}
;{ C
CreateSprite(2,128,64,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(2))
Box(0,0,64,64,RGB(255,0,0))
Box(64,0,64,64,RGB(255,255,0))
Box(118,54,10,10, $FF0000)
StopDrawing()
CreateSprite3D(2,2)
c = CreateSprite3DEX(2)
;}
;{ D
CreateSprite(3,128,64,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(3))
Box(0,0,64,64,RGB(255,0,0))
Box(64,0,64,64,RGB(255,255,0))
Box(118,0,10,10, $FF0000)
StopDrawing()
CreateSprite3D(3,3)
d = CreateSprite3DEX(3)
;}
e = CreateSprite3DEX(0)
f = CreateSprite3DEX(0)



Sprite3DModifyPivot(e,0,32)
Sprite3DModifyPivot(f,64,0)


Repeat
    Event=WindowEvent()
    r.f = 90 + 45 * Cos(ElapsedMilliseconds()/500)
    ExamineKeyboard()
    ClearScreen(0)
    Start3D()
    RotateSprite3DEX(a,0)
    DisplaySprite3D(0,100,100)
    
    RotateSprite3DEX(b,90)
    DisplaySprite3D(1,300,100)
    
    RotateSprite3DEX(c,180)
    DisplaySprite3D(2,100,300)
    
    RotateSprite3DEX(d,270)
    DisplaySprite3D(3,300,300)
    
    RotateSprite3DEX(e,r)
    DisplaySprite3D(0,500,200)
    
    
    RotateSprite3DEX(f,-r)
    DisplaySprite3D(0,500,400)
    Stop3D()
    
    StartDrawing(ScreenOutput())
    DrawText(100,100,"0 DEG")
    DrawText(300,100,"90 DEG")
    DrawText(100,300,"180 DEG")
    DrawText(300,300,"270 DEG")
    Circle(500,232,4,RGB(0,0,255))
    Circle(564,400,4,RGB(0,0,255))
    Box(100,100,10,10, $00FF00)
    Box(300,100,10,10, $00FF00)
    Box(100,300,10,10, $00FF00)
    Box(300,300,10,10, $00FF00)
    StopDrawing()
    FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape) Or event=#PB_Event_CloseWindow

Publié : dim. 09/déc./2007 13:02
par Thyphoon
Dobro a écrit :pas obligé d'etre Carre !!
mais il doit etre un multiple de 16

on peut tres bien faire un sprite 512x128 ou 32x512... :)
300x100 comment fait-on ?
ben tu créé un sprite le plus approchant !! multiple de 16

soit 320x128
Apres test, si on veut utiliser les fonctions3D native pour faire tourner un sprite 3D il faut impérativement que le sprite soit carré sinon il sera deformé :(
Mais je te merci des fonctions que tu as mis. Sais-tu si elles sont multiplatforme ? j'ai pas l'impression qu'il y ai d'API utiliser...

Publié : dim. 09/déc./2007 13:10
par Backup
Thyphoon a écrit : Sais-tu si elles sont multiplatforme ? j'ai pas l'impression qu'il y ai d'API utiliser...
en principe aucun problèmes puisqu'aucun Api est employé ..

le seul problem c'est que je ne sais plus qui est l'auteur du Code .... :?

peut etre bien le Soldat inconnu .... :)

ou cpl Bator ? , ou Chris ? ou Oliv ? ou Denis ? ou Dri? ou Comtois ? :lol:

Publié : dim. 09/déc./2007 13:40
par beauregard
djes a écrit :Dans ton cas, pour un sprite de 300x100, si tu dois faire une rotation, il te faut prendre 512x512
c'est ce que je pense aussi.

Publié : dim. 09/déc./2007 14:50
par Thyphoon
Dobro a écrit :
Thyphoon a écrit : Sais-tu si elles sont multiplatforme ? j'ai pas l'impression qu'il y ai d'API utiliser...
en principe aucun problèmes puisqu'aucun Api est employé ..

le seul problem c'est que je ne sais plus qui est l'auteur du Code .... :?

peut etre bien le Soldat inconnu .... :)

ou cpl Bator ? , ou Chris ? ou Oliv ? ou Denis ? ou Dri? ou Comtois ? :lol:
heu et comment tu fais lorsque tu veux changer la taille et faire tourner en même temps avec ton code ? car il n'y a que la fonction rotation et apparement ce n'est pas compatible avec la fonction transform de purebasic !? :P

Publié : dim. 09/déc./2007 16:23
par Thyphoon
Bon je vous remerci tous, car tout est beaucoup plus claire pour moi maintenant. Et au final je vais utiliser des sprites3D carré car c'est la seul façon d'utiliser RotateSprite3D et zoomSprite3D sans que ça deforme l'image.
Le code de Dobro est tres interessant mais il manque quelques fonctions pour ête pleinnement efficace :oP
En tout cas un grand merci a tous, de m'avoir donner un peu de votre dimanche. :D

Publié : lun. 10/déc./2007 13:27
par beauregard
Thyphoon a écrit :En tout cas un grand merci a tous, de m'avoir donner un peu de votre dimanche. :D
Au plaisir ! :D

Publié : lun. 10/déc./2007 20:17
par Anonyme
C'est bibi l'auteur du code, a la base c'est un snippet pour progi1984 si je me rapelle bien.
Ce n'est PAS une limitation de Purebasic, mais une contrainte DirectX liée aux cartes graphiques.
C'est le même problème avec OpenGL , cela vient bien du matériel et non pas d'une api , a prioris se serais un problème de stockage interne , certaine carte impose une taille n² , comme la mienne par exemple , un sprite 32x128 ne marche pas. la solution consiste donc a créer un buffer d'une taille n²
d'appliquer l'image dans ce buffer, puis d'afficher ce buffer. si ton sprite fait donc 32x128 , il fera en réalité 128x128 , il faudra donc joué avec les UV pour ne pas avoir de déformation.