image en perspective

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

image en perspective

Message 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
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Message 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 :) )
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message par Golfy »

Pour le moment, tu reste le seul à avoir répondu :lol:
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
ATHOW
Messages : 226
Inscription : mer. 29/déc./2004 16:54

Message 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) 
Anonyme

Message par Anonyme »

Salut , fait une recherche sur SuperSprite3D , c'est exactement ce que tu cherches. c'est opensource :P

@++
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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.)
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Anonyme

Message 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++
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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:
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Anonyme

Message 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().

@++
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message 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
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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 !
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Golfy
Messages : 423
Inscription : mer. 25/août/2004 15:14
Localisation : Grenoble
Contact :

Message 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:
Purebasic 5.30 full sous Windows XP (x86) et Win7 (64 bits), Linux Debian. Orientation réseaux, domotique
http://golfy.olympe.in/Teo-Tea/
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Message 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.
Répondre