Page 1 sur 1

image en perspective

Publié : mar. 11/sept./2007 13:08
par Golfy
Bonjour,

je voudrais pouvoir transformer une image 2D en image en perspective (un peu comme une page ouverte).
J'ai bidouillé le code suivant (avec des sprites 3D) mais j'ai 2 problèmes :
1) le sprite 3D étant géré comme 2 triangles, la mise en perspective n'est pas bonne... (ça marchait avec l'image de l'exemple initial mais j'ai dû... trop bidouiller :oops: )
2) dans le code suivant, je n'arrive même pas à avoir une image (on dirait que j'ai une zone mémoire quelquonque).

Quelqu'un peut-il m'aider ? dois-je essayer de plaquer mon image sur un véritable objet 3D ?
je ne maitrise pas du tout la 3D :oops: :oops: :oops:
Merci d'avance !

Code : Tout sélectionner

;
; ------------------------------------------------------------
;
;   PureBasic - Sprite example file
;
;    (c) 2002 - Fantaisie Software
;
; ------------------------------------------------------------
;
#image = 0
#img_ori = 1
#spri = 2
Resultat = GetClipboardImage(#Img_ori)
If Resultat = 0
	Fichier$ = OpenFileRequester("Choisissez une image à mettre en perpective", "", "Images |*.jpg;*.bmp;*.png", 0)
	If fichier$ =""
		End
	EndIf
EndIf


UseJPEGImageDecoder() 
UsePNGImageDecoder() 

If InitSprite() = 0 Or InitKeyboard() = 0
  MessageRequester("Error", "Can't open DirectX 7 Or later", 0)
  End
EndIf

If InitSprite3D() = 0
  MessageRequester("Error", "Direct3D system can't be initialized correctly", 0)
  End
EndIf

;
; Now, open a 16 bits (65000 colours) screen
;

Xscreen = 1024
Yscreen = 768
If OpenScreen(Xscreen, Yscreen, 32, "Sprite")

  ; Load our 16 bit sprite (which is a 24 bit picture in fact, as BMP doesn't support 16 bit format)
  ; 
  FlipBuffers()

  ClearScreen(RGB(cr,cv,cb))
  StartDrawing(ScreenOutput())
;  If resultat = 0
 	LoadImage(#img_ori, Fichier$)
 	DrawImage(#img_ori,0,0)
;  Else
;  	DrawImage(#img_ori,0,0,Xscreen,Yscreen)
;  EndIf
	Circle(Xscreen/2, Yscreen/2, 100, RGB(255,0,0))
	DrawText(10,50,Fichier$,RGB(0,255,0),RGB(0,0,0))
  StopDrawing()
  FlipBuffers()
  Delay(2000)
  Re = GrabSprite(#spri,0,0,Xscreen, Xscreen,#PB_Sprite_Texture)
  
 	; LoadSprite(#image, Fichier$, #PB_Sprite_Texture)
  	
  CreateSprite3D(#image, #spri)
  Sprite3DQuality(1)
 	res = InitMouse()
 	cr = 255
 	cv = 255
 	cb = 255
 	side = 0		; 0: Gauche, 1: droite
 	brelease = 0
  Repeat   
    ; Inverse the buffers (the back become the front (visible)... And we can do the rendering on the back)
    FlipBuffers()
    
    ClearScreen(RGB(cr,cv,cb))
    
    ; Draw our sprite
    ;
    If Start3D()
			; Traitement des paramètres SOURIS
			ExamineMouse()
			x = MouseX()
			y = MouseY()
			ymiddle = yscreen/2
			dy = Abs(ymiddle-y)
			;
			If MouseButton(2) And brelease = 0
				side = ~side
				brelease = 1
			EndIf
			If MouseButton(2) = 0
				brelease = 0
			EndIf
			
			If MouseButton(1) And brelease = 0
			EndIf	
			
			; Traitement des paramètres CLAVIER
	    ExamineKeyboard()
			If KeyboardInkey() = " "
				If cr = 0
					cr = 255
					cv = 255
					cb = 255
				Else
					cr = 0
					cv = 0
					cb = 0
				EndIf
			EndIf
			
			; Préparation du dessin
			If side = 0
				TransformSprite3D(#image,0,0,x,ymiddle-dy,x,ymiddle+dy,0,Yscreen)
			Else
				TransformSprite3D(#image,x,ymiddle-dy,Xscreen,0,Xscreen, Yscreen,x,ymiddle+dy)
			EndIf
      DisplaySprite3D(#image, 0, 0)
      ;RotateSprite3D(1, x, 0)
      ;DisplaySprite3D  (1, 0, 100, x/2)
      ;DisplaySprite3D  (1, x*2, 100, x)
      ;DisplaySprite3D  (1, 0, 100, x/2)
      ;DisplaySprite3D  (1, x*2, 200+x, x)
      
      Stop3D()
    EndIf   
  Until KeyboardPushed(#PB_Key_Escape)
  
Else
  MessageRequester("Error", "Can't open a 640*480 - 16 bit screen !", 0)
EndIf

End

Publié : mar. 11/sept./2007 13:15
par ATHOW
J'ai un premier élément de réponse : les images utilisées pour les sprite3D doivent être des textures de 8*8, 16*16, 32*32, 64*64 ou 256*256... mais 1024*1024 peut-être trop important (d'après la doc).
J'ai pas PureBasic au boulot, je regarderai ce soir plus en détail (même si les autres acharnés du forum répondront sûrement avant moi :) )

Publié : mar. 11/sept./2007 23:07
par Golfy
Pour le moment, tu reste le seul à avoir répondu :lol:

Publié : mer. 12/sept./2007 6:13
par ATHOW
Oui, étonnant :D
J'ai pas eu beaucoup le temps de regarder ton code, mais j'ai vu que ma première piste n'était pas bonne.

Mais ici, filperj a fait un effet qui resemble, je crois à ce que tu veux faire : http://www.purebasic.fr/french/viewtopi ... prite3d%2A

C'est un peu complexe, mais tu pourras peut-être en tirer quelque chose le temps que je me repenche dessus !
Je l'ai mis -vite fait- en 4.xx ci dessous :

Code : Tout sélectionner


#pipi=2*#PI

Procedure.f wraptour(tr.f)
  tr-Int(tr)
  If tr<0
    ProcedureReturn tr+1
  Else
    ProcedureReturn tr
  EndIf
EndProcedure

Procedure.f anglentour(x.f,y.f)
  dist.f=Sqr(x*x+y*y)
  If ASin(-x/dist)<0
    ProcedureReturn wraptour(-ACos(y/dist)/#pipi)
  Else
    ProcedureReturn wraptour(ACos(y/dist)/#pipi)
  EndIf
EndProcedure


Procedure.l bobface(x1,y1,x2,y2,x3,y3,x4,y4)
  Xa=x1: Ya=y1: xb=x2: yb=y2: xc=x4: yc=y4
  For t=1 To 2
    If wraptour(anglentour(xc-Xa,yc-Ya)-anglentour(xb-Xa,yb-Ya))>0.5
      renvoi | 2
    Else
      renvoi | 1
    EndIf
    Xa=x2: Ya=y2: xb=x3: yb=y3
  Next
  ProcedureReturn renvoi
EndProcedure



scx=GetSystemMetrics_(#SM_CXSCREEN)
scy=GetSystemMetrics_(#SM_CYSCREEN)



;vous pouvez remplacer ça par un LoadImage
imid=CreateImage(0,scx,scy)
BitBlt_(StartDrawing(ImageOutput(0)),0,0,scx,scy,GetDC_(GetDesktopWindow_()),0,0,#SRCCOPY)
StopDrawing()

hwin=OpenWindow(0,0,0,scx,scy,"",#PB_Window_BorderLess)
StartDrawing(WindowOutput(0))
DrawImage(imid,0,0)
StopDrawing()

If scx<>400 Or scy<>300
  ResizeImage(0,400,300)
EndIf

InitSprite() : InitSprite3D()
OpenWindowedScreen(hwin,0,0,scx,scy,0,0,0)

For x=0 To 49 : For y=0 To 36
    imid=GrabImage(0,1,x<<3,y<<3,8,8)
    numsprite=x+y*50
    CreateSprite(numsprite,8,8,#PB_Sprite_Texture)
    StartDrawing(SpriteOutput(numsprite))
    DrawImage(imid,0,0)
    StopDrawing()
    CreateSprite3D(numsprite,numsprite)
    ;CopySprite(numsprite,numsprite+10001)
    If WindowEvent()=#WM_KEYUP
      HideWindow(0,1) : End
    EndIf
Next:Next

FreeImage(0) : FreeImage(1)

For numsprite=10000 To 10000+49+36*50
  CreateSprite(numsprite,8,8,#PB_Sprite_Texture)
  UseBuffer(numsprite)
  For x=0 To 7
    ClipSprite(numsprite-10000,x,0,1,8)
    DisplaySprite(numsprite-10000,7-x,0)
  Next
  If WindowEvent()=#WM_KEYUP
    HideWindow(0,1) : End
  EndIf
  CreateSprite3D(numsprite,numsprite)
Next

;FreeSprite(17500)
UseBuffer(-1)


Structure noeud
  x.f : y.f
EndStructure



Dim grille.noeud(50,37)
For x=0 To 50 : For y=0 To 37
    grille(x,y)\x=(scx*x)/25
    grille(x,y)\y=(scy*y)/18.5
Next:Next

souris.noeud
visee.noeud
vitesse.f=0.02
basepondero.f=Sqr(Pow(scx,2)+Pow(scy,2))*20
InitMouse()
SetFrameRate(0)

Repeat
  
  
  pondero=basepondero*vitesse+1
  souris\x=MouseX() : souris\y=MouseY()
  
  For x=0 To 50 : For y=0 To 37
      
      poids.f=Sqr(Pow(souris\x-(scx*x)/50,2)+Pow(souris\y-(scy*y)/37,2))/pondero
      xv.f=(scx*x)/50 : yv.f=(scy*y)/37
      visee\x=(xv*poids+souris\x*(1-poids))*(1-poids)+xv*poids
      visee\y=(yv*poids+souris\y*(1-poids))*(1-poids)+yv*poids
      
      ;Décommentez pour un effet "froissé" (pas très au point)
      
      ;    Repeat
      ;      If visee\x<0
      ;        visee\x=-visee\x
      ;       ElseIf visee\x>scx
      ;        visee\x/scx
      ;        visee\x=(visee\x-Int(visee\x))*scx
      ;       Else
      ;        Break
      ;      EndIf
      ;    ForEver
      ;    Repeat
      ;      If visee\y<0
      ;        visee\y=-visee\y
      ;       ElseIf visee\y>scy
      ;        visee\y/scy
      ;        visee\y=(visee\y-Int(visee\y))*scy
      ;       Else
      ;        Break
      ;      EndIf
      ;    ForEver
      
      grille(x,y)\x+((visee\x-grille(x,y)\x)*vitesse)
      grille(x,y)\y+((visee\y-grille(x,y)\y)*vitesse)
      
  Next:Next
  
  Start3D() : For x=0 To 49 : For y=0 To 36
      
      numsprite=x+y*50
      c1.noeud
      c2.noeud
      c3.noeud
      c4.noeud
      CopyMemory(@grille(x,y),@c1,SizeOf(noeud))
      CopyMemory(@grille(x+1,y),@c2,SizeOf(noeud))
      CopyMemory(@grille(x+1,y+1),@c3,SizeOf(noeud))
      CopyMemory(@grille(x,y+1),@c4,SizeOf(noeud));:CallDebugger
      visibilite=bobface(c1\x,c1\y,c2\x,c2\y,c3\x,c3\y,c4\x,c4\y)
      If visibilite & 1
        TransformSprite3D(numsprite,c1\x,c1\y,c2\x,c2\y,c3\x,c3\y,c4\x,c4\y)
        DisplaySprite3D(numsprite,0,0,128)
      EndIf
      If visibilite & 2
        numsprite+10000
        TransformSprite3D(numsprite,c2\x,c2\y,c1\x,c1\y,c4\x,c4\y,c3\x,c3\y)
        DisplaySprite3D(numsprite,0,0,128)
      EndIf
      
  Next:Next:Stop3D()
  
  ExamineMouse()
  vitesse+(MouseWheel()*0.001)
  If vitesse<=0 : vitesse=0.001 :EndIf
  FlipBuffers() : ClearScreen(RGB(127,127,127))
Until WindowEvent()=#WM_KEYUP
ReleaseMouse(1)
HideWindow(0,1) 

Publié : mer. 12/sept./2007 7:02
par Anonyme
Salut , fait une recherche sur SuperSprite3D , c'est exactement ce que tu cherches. c'est opensource :P

@++

Publié : mer. 12/sept./2007 13:27
par Golfy
Merci Cpl.Bator !!!
c'est exactement ce que je cherche
:)

Cependant, l'image doit impérativement avoir la même largeur que la hauteur.
Ai-je un moyen de travailler (en mémoire) sur une image à moi (un fond noir de 1024x1024 par exemple) et d'y intégrer l'image à charger (par exemple 1024x768) pour ensuite seulement la transformer en SuperSprite3D ?

Désolé pour les questions stupides mais l'histoire de passer une image en sprite puis en sprite3D m'embrouille un peu...
(dois-je utiliser les mêmes pointeurs ? comment puis copier l'image dans le sprite ? etc.)

Publié : mer. 12/sept./2007 18:39
par Anonyme
c'est très simple :

Dans un premier temps tu initialises SuperSprite3D :

Code : Tout sélectionner

InitSuperSprite3D()
Ensuite tu définis el point de fuite qui est le centre de ton écran , pour le connaitre, tu divises la résolution par deux :

(1024/2)*(768/2) = 512*384

Code : Tout sélectionner

SetPerspective(512,384)
Ensuite du charge ton sprite normalement :

Code : Tout sélectionner

LoadSprite(0,"MonSprite.xxx",#PB_Sprite_Texture) 
CreateSprite3D(0,0)
L'id du sprite doit avoir le même id que celui du sprite3D
Sprite = 0
Sprite3D = 0
cela peut être 1,2,10,12,etc... on s'en fout, c'est juste qu'il doivent avoir un id identique.

ensuite tu créer ton supersprite3D :

Code : Tout sélectionner

MonSprite = CreateSuperSprite3D(0,512,512)
le 1° argument est le numéro du sprite chargé plus haut , les autres c'est la taille, tu es libre de mettre ce que tu veut.

ensuite tu l'affiches :

Code : Tout sélectionner

Start3D()
 SetSuperSpritePosition(MonSprite,0,0,0) ; Position XYZ
 RotateSuperSprite3D(MonSprite,0,0,0) ; Rotation XYZ
 DisplaySuperSprite3D(MonSprite) ; Affichage
Stop3D()

N'oublie pas de mettre un zoom a environ 500 / 1000 , si tu ne voit rien , tourne le de 180° sur l'axe des Y.

voila, A++

Publié : mer. 12/sept./2007 22:47
par Golfy
En fait, mon problème est désormais ici :

Code : Tout sélectionner

; création d'une image pour charger le fichier image dans la zone en 1024x1024
CreateImage(1,1024,1024)
LoadImage(0, Fichier$)
StartDrawing(ImageOutput(1))
DrawImage(ImageID(0),0,0,1024,1024)
StopDrawing()
; Voir le résultat du traitement de l'image
Delay(1000)
; Capture de l'image pour en faire un sprite
Resultat = GrabSprite(0,0,0,1024,1024,#PB_Sprite_Texture) 

;LoadSprite(0,"Media\SS3D.jpg",#PB_Sprite_Texture) ; Les sprites 3D crées doivent avoir obligatoirement des id identiques
CreateSprite3D(0,0)


MonSprite = CreateSuperSprite3D(0,1024,1024) ; Notre SuperSprite3D sera MonSprite
Je n'arrive pas à charger une image de taille quelquonque et à la redimensionner dans un format 1024x1024 :x :oops:

Au mieux, j'arrive à 'clipper' un image avec

Code : Tout sélectionner

LoadSprite(1,Fichier$,#PB_Sprite_Texture)
ClipSprite(1,0,0,1024,1024)
DisplaySprite(1,0,0)
CreateSprite3D(0,1)
:roll:

Publié : jeu. 13/sept./2007 8:29
par Anonyme
essaye avec :

Code : Tout sélectionner

Resultat = GrabSprite(0,0,0,1024,1024,#PB_Sprite_Texture) 
CreateSprite3D(Resultat,Resultat) 
MonSprite = CreateSuperSprite3D(Resultat,1024,1024) 
tu risque quand même d'avoir un soucis, Grabsprite capture l'écran, je ne sais pas se qui ce passe "hors-limite écran" si ca déconne, essaye d'ajouté la fct° usebuffer().

@++

Publié : jeu. 13/sept./2007 10:36
par Backup
Golfy a écrit : Je n'arrive pas à charger une image de taille quelquonque et à la redimensionner dans un format 1024x1024 :x :oops:

Code : Tout sélectionner

ResizeImage(#Image, Largeur, Hauteur [, Mode]) 
?????? 8O

Publié : jeu. 13/sept./2007 16:46
par Golfy
Tout n'est pas encore très clair mais... j'ai un programme utilisable :
1) choisissez une image quelquonque dans le sélecteur de fichier
2) bougez la souris et la molette de souris (merci Cpl.Bator pour ton superbe travail)
3) déplacez avec les flèches du clavier et pivotez avec + et - du pavé numérique
4) Mettez dans le presse-papier (clipboard) avec la touche [Impr. écran]
5) collez dans Powerpoint, Word, PSP, etc...

Code : Tout sélectionner

IncludeFile "Include\Supersprite3D.pbi"

Fichier$=OpenFileRequester("Ouvrir une image","","",0)
InitSprite() :InitSprite3D() : InitSuperSprite3D() : InitKeyboard() : InitMouse()


OpenScreen(1024,768,32,"")

UseJPEGImageDecoder()

; création d'une image pour charger le fichier image dans la zone en 1024x1024
LoadImage(0, Fichier$)

; Création d'un sprite
CreateSprite(0,512,512,#PB_Sprite_Texture)
StartDrawing(SpriteOutput(0))
DrawImage(ImageID(0),0,0,512,512)
StopDrawing()

CreateSprite3D(0,0)


MonSprite = CreateSuperSprite3D(0,512,512) ; Notre SuperSprite3D sera MonSprite


SetPerspective(512,384) ; Defini le point de fuite


Repeat
 ClearScreen(RGB(255,255,255)) : ExamineKeyboard() : ExamineMouse()

ax.f - (MouseDeltaY()/10)
ay.f + (MouseDeltaX()/10)
Zoom - MouseWheel()*100

; Les flèches permettent de déplacer le sprite (haut/bas/gauche/droite)
If KeyboardReleased(#PB_Key_Left)
	Xoffset = Xoffset -10
EndIf
If KeyboardReleased(#PB_Key_Right)
	Xoffset = Xoffset +10
EndIf
If KeyboardReleased(#PB_Key_Up)
	Yoffset = Yoffset -10
EndIf
If KeyboardReleased(#PB_Key_Down)
	Yoffset = Yoffset +10
EndIf
; Les touches - et + du pavé numérique permettent sa rotation
If KeyboardReleased(#PB_Key_Add)
	RZoffset = RZoffset -2
EndIf
If KeyboardReleased(#PB_Key_Subtract)
	RZoffset = RZoffset +2
EndIf


Start3D()
 SetSuperSpritePosition(MonSprite,0+Xoffset,0+Yoffset,600+Zoom)
 RotateSuperSprite3D(MonSprite,ax,ay,0+RZoffset)
 DisplaySuperSprite3D(MonSprite)
Stop3D()


 FlipBuffers(1)
Until KeyboardPushed(#PB_Key_Escape) Or KeyboardPushed(#PB_Key_Space)

; J'ai pas réussi à sauvegarder l'image mais la touche [Impr écran] fonctionne !
; sinon, la touche [Espace] sera utilisé pour générer une image sur le disque
If KeyboardPushed(#PB_Key_Space)
	Chemin$ = GetPathPart(Fichier$)
	Nom$ = GetFilePart(Fichier$)
	extention$ = GetExtensionPart(Fichier$)
	Image$=Chemin$ + Nom$ + "_3D" + extension$
	SetClipboardImage(0)
EndIf
Merci encore à Cpl.Bator pour sa patience !
Merci aussi à Dobro !

Publié : jeu. 13/sept./2007 16:47
par Golfy
Dobro a écrit :
Golfy a écrit : Je n'arrive pas à charger une image de taille quelquonque et à la redimensionner dans un format 1024x1024 :x :oops:

Code : Tout sélectionner

ResizeImage(#Image, Largeur, Hauteur [, Mode]) 
?????? 8O
Apparemment, une limite est : 512x512 :roll:

Publié : jeu. 13/sept./2007 23:31
par djes
Golfy a écrit :
Dobro a écrit :
Golfy a écrit : Je n'arrive pas à charger une image de taille quelquonque et à la redimensionner dans un format 1024x1024 :x :oops:

Code : Tout sélectionner

ResizeImage(#Image, Largeur, Hauteur [, Mode]) 
?????? 8O
Apparemment, une limite est : 512x512 :roll:
C'est une limitation de directx, qui correspond à la taille de l'affichage.