Anaglyphes
Publié : jeu. 04/mars/2010 11:56
Bonjour,
Dans ce code, j'ai essayé de mettre en pratique un truc qui me trottait dans la tête depuis quelques mois. Mais comme je me suis rapidement trouvé bloqué, je poste le code au cas où vous auriez des idées.
En résumé: il s'agit d'afficher une scène 3D en anaglyphes, c'est-à-dire en "vrai" 3D visibles avec ses lunettes marrantes dotées d'un verre rouge et d'un verre bleu. (Dobro saura de quoi je parle, il a pas mal pratiqué la chose).
Pour bien faire les choses, il faudrait:
- Avoir deux caméras légèrement espacées;
- Récupérer l'image vue par chacune d'entre elle;
- Appliquer un filtre bleu sur l'une de ces images, et rouge sur l'autre;
- Afficher à l'écran ces images l'une par-dessus l'autre de façon semi-transparente;
Mais ça, je n'ai pas réussi à le faire. J'avais deux caméras équipée d'un filtre de couleur (un "plain" transparent rouge ou bleu positionné juste devant la caméra), et je voulais faire un "grabSprite" sur chacune d'elle, puis un "displayTranslucentSprite" pour afficher les deux images l'une sur l'autre. Hélas, le "GrabSprite" me renvoie des images vides (toutes noires, quoi).
Deuxième approche, moins satisfaisante: je dédouble toutes les entités, et je colle à un morceau un "material" bleu transparent et à l'autre un "material" rouge transparent. Puis j'affiche les deux avec un léger décalage droite/gauche en fonction de sa distance avec la caméra.
Je pense que ça marche (pas pu vérifier: je n'ai pas encore remis la main sur mes lunettes "la créature du lagon noir", distribuées quand le film était passé à "La Dernière Séance"
), mais ce n'est pas beau car:
- Les objets affichés sont forcément transparents;
- Le nb de polygones affichés est doublé.
Bref: je laisse tomber pour l'instant. Je vous lègue l'exemple suivant (que l'on pourrait intituler "Les nougats dans l'espace"), en espérant que les petits génies du coin auront des idées pour l'améliorer. Ce serait sympa, un jeu PB en "vraie" 3D...
[EDIT] Ah oui: vous pouvez ajuster le rendu en fonction de la taille de votre écran ou de la couleur de vos lunettes grâce aux trois constantes en début de code:
#SEPARATION : écart entre l'image rouge et l'image bleue (x Distance)
#LEFTEYECOLOR : couleur pour l'image de gauche
#RIGHTEYECOLOR : couleur pour l'image de droite
Dans ce code, j'ai essayé de mettre en pratique un truc qui me trottait dans la tête depuis quelques mois. Mais comme je me suis rapidement trouvé bloqué, je poste le code au cas où vous auriez des idées.
En résumé: il s'agit d'afficher une scène 3D en anaglyphes, c'est-à-dire en "vrai" 3D visibles avec ses lunettes marrantes dotées d'un verre rouge et d'un verre bleu. (Dobro saura de quoi je parle, il a pas mal pratiqué la chose).
Pour bien faire les choses, il faudrait:
- Avoir deux caméras légèrement espacées;
- Récupérer l'image vue par chacune d'entre elle;
- Appliquer un filtre bleu sur l'une de ces images, et rouge sur l'autre;
- Afficher à l'écran ces images l'une par-dessus l'autre de façon semi-transparente;
Mais ça, je n'ai pas réussi à le faire. J'avais deux caméras équipée d'un filtre de couleur (un "plain" transparent rouge ou bleu positionné juste devant la caméra), et je voulais faire un "grabSprite" sur chacune d'elle, puis un "displayTranslucentSprite" pour afficher les deux images l'une sur l'autre. Hélas, le "GrabSprite" me renvoie des images vides (toutes noires, quoi).

Deuxième approche, moins satisfaisante: je dédouble toutes les entités, et je colle à un morceau un "material" bleu transparent et à l'autre un "material" rouge transparent. Puis j'affiche les deux avec un léger décalage droite/gauche en fonction de sa distance avec la caméra.
Je pense que ça marche (pas pu vérifier: je n'ai pas encore remis la main sur mes lunettes "la créature du lagon noir", distribuées quand le film était passé à "La Dernière Séance"

- Les objets affichés sont forcément transparents;
- Le nb de polygones affichés est doublé.
Bref: je laisse tomber pour l'instant. Je vous lègue l'exemple suivant (que l'on pourrait intituler "Les nougats dans l'espace"), en espérant que les petits génies du coin auront des idées pour l'améliorer. Ce serait sympa, un jeu PB en "vraie" 3D...
[EDIT] Ah oui: vous pouvez ajuster le rendu en fonction de la taille de votre écran ou de la couleur de vos lunettes grâce aux trois constantes en début de code:
#SEPARATION : écart entre l'image rouge et l'image bleue (x Distance)
#LEFTEYECOLOR : couleur pour l'image de gauche
#RIGHTEYECOLOR : couleur pour l'image de droite
Code : Tout sélectionner
; Author: Kelebrindae
; Date: march,04, 2010
; PB version: v4.41
; OS: Windows XP
;- Initialisation
If InitEngine3D() = 0
MessageRequester( "Error" , "Can't initialize 3D, check if engine3D.dll is available" , 0 )
End
ElseIf InitSprite() = 0 Or InitKeyboard() = 0
MessageRequester( "Error" , "Can't find DirectX 7.0 or above" , 0 )
End
EndIf
Resultat = MessageRequester("Anaglyph","Full Screen ?",#PB_MessageRequester_YesNo)
If Resultat = 6
FullScreen.b=#True
OpenScreen(800,600,32,"Anaglyph")
Else
FullScreen=#False
OpenWindow(0,0, 0, 800 , 600 ,"Anaglyph",#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0, 800 , 600,0,0,0)
EndIf
EnableExplicit
; Constants
#CAMERA=0
#CAMERADIST=200
#NBOBJ = 5
#SEPARATION = 0.01
#LEFTEYECOLOR = $FFFF00
#RIGHTEYECOLOR = $0000FF
;- Data structures and definitions
; Mesh creation
Structure vertex_struct
px.f
py.f
pz.f
nx.f
ny.f
nz.f
Couleur.i
U.f
V.f
EndStructure
Structure triangle_struct
f1.w
f2.w
f3.w
EndStructure
; Objects
Structure obj_struct
nummesh.i
numentity1.i
numentity2.i
x.f
y.f
z.f
xd.f
yd.f
zd.f
xspin.f
yspin.f
zspin.f
EndStructure
Global Dim obj.obj_struct(#NBOBJ)
; Camera position and distance from objects
Global xcam.f,ycam.f,zcam.f,cameraAngle.f,dist.f
Global i.i
;- --- Macros ---
Macro DISTANCE(x1,y1,z1,x2,y2,z2)
Sqr( ((x1)-(x2))*((x1)-(x2)) + ((y1)-(y2))*((y1)-(y2)) + ((z1)-(z2))*((z1)-(z2)) )
EndMacro
;- --- Procedures ---
Procedure.i CreateCube(sizeX.f,sizeY.f,sizeZ.f,Uorigin.f=0,Vorigin.f=0,Uscale.f=1,Vscale.f=1,color.i=$FFFFFF)
Protected nbVert.w , nbTri.w ; Number of vertices and faces
Protected x.f,y.f,z.f ; vertex position
Protected nx.f,ny.f,nz.f ; vertex normals
Protected u.f,v.f ; vertex UV coords (texture mapping)
Protected *PtrV.vertex_struct,*vertexBuffer.i ; vertices buffer in memory
Protected *PtrF.triangle_struct,*triangleBuffer.i ; Faces buffer in memory
Protected newmesh.i ; Procedure Result
Protected i.i,v1.i,v2.i,v3.i
; Restore meshdatas
Restore cube
; Read number of vertices and triangles
Read.w nbVert
Read.w nbTri
; Allocate the needed memory for vertices
*vertexBuffer = AllocateMemory(SizeOf(vertex_struct)*nbVert)
*PtrV = *vertexBuffer
; Read and store vertices position, normals, uv coords
For i = 1 To nbVert
Read.f x
Read.f y
Read.f z
Read.f nx
Read.f ny
Read.f nz
Read.f u
Read.f v
*PtrV\px = x * sizex
*PtrV\py = y * sizey
*PtrV\pz = z * sizez
*PtrV\nx = nx
*PtrV\ny = ny
*PtrV\nz = nz
*PtrV\couleur = Color
*PtrV\u = uorigin + (u * uscale)
*PtrV\v = vorigin + (v * vscale)
*PtrV + SizeOf(vertex_struct)
Next i
; Allocate the needed memory for faces
*triangleBuffer=AllocateMemory(SizeOf(triangle_struct)*nbTri)
*PtrF=*triangleBuffer
;Read and store faces infos
For i=1 To nbTri
Read.w v1
Read.w v2
Read.w v3
*PtrF\f1=v1
*PtrF\f2=v2
*PtrF\f3=v3
*PtrF + SizeOf(triangle_struct)
Next i
; Create mesh from stored infos
newmesh = CreateMesh(#PB_Any,nx)
If IsMesh(newmesh)
SetMeshData(newmesh,#PB_Mesh_Vertex | #PB_Mesh_Normal | #PB_Mesh_UVCoordinate | #PB_Mesh_Color,*vertexBuffer,nbVert)
SetMeshData(newmesh,#PB_Mesh_Face,*triangleBuffer,nbTri)
; and don't forget to free memory
FreeMemory(*vertexBuffer)
FreeMemory(*triangleBuffer)
ProcedureReturn newmesh
Else
; even if "createMesh" has failed
FreeMemory(*vertexBuffer)
FreeMemory(*triangleBuffer)
ProcedureReturn -1
EndIf
EndProcedure
;- --- Main ---
;- Materials
Add3DArchive(".",#PB_3DArchive_FileSystem)
; Base texture
CreateImage(0,32,32)
StartDrawing(ImageOutput(0))
Box(0, 0, ImageWidth(0), ImageHeight(0), $FFFFFF)
For i=1 To 5
Circle(Random(ImageWidth(0)),Random(ImageHeight(0)),Random(ImageHeight(0)/6),$DDDDDD)
Next i
StopDrawing()
SaveImage(0,"temp.bmp")
FreeImage(0)
LoadTexture(0,"temp.bmp")
DeleteFile("temp.bmp")
; For left eye
CreateMaterial(1,TextureID(0))
MaterialAmbientColor(1, #LEFTEYECOLOR)
MaterialBlendingMode(1, #PB_Material_Add)
; For right eye
CreateMaterial(2,TextureID(0))
MaterialAmbientColor(2, #RIGHTEYECOLOR)
MaterialBlendingMode(2, #PB_Material_Add)
;- Entities
;Create and locate the objects
For i=0 To #NBOBJ-1
obj(i)\nummesh = createCube(15+Random(10),15+Random(10),15+Random(10))
obj(i)\numentity1 = CreateEntity(#PB_Any,MeshID(obj(i)\nummesh),MaterialID(1))
obj(i)\numentity2 = CreateEntity(#PB_Any,MeshID(obj(i)\nummesh),MaterialID(2))
; Initial position
obj(i)\x=Random(60)-30
obj(i)\y=Random(60)-30
obj(i)\z=Random(100)-50
; Initial movement
obj(i)\xd=(Random(10)-5 ) / 10.0
obj(i)\yd=(Random(10)-5 ) / 10.0
obj(i)\zd=(Random(10)-5 ) / 10.0
; Spin
obj(i)\xspin=Random(20)/10
obj(i)\yspin=Random(20)/10
obj(i)\zspin=Random(20)/10
Next i
;- Camera
CreateCamera(#Camera, 0, 0 , 100 , 100)
xcam=0:ycam=0:zcam=-#CAMERADIST
;- Light
AmbientColor($666666)
CreateLight(0,$EEEEEE,200,300,0)
;- Main loop
Repeat
If fullscreen = 0
While WindowEvent() : Wend
EndIf
ExamineKeyboard()
; cameraAngle+0.01
; If cameraAngle > #PI
; cameraAngle = -#PI
; EndIf
; xcam = #CAMERADIST * Cos(cameraAngle)
; zcam = #CAMERADIST * Sin(cameraAngle)
CameraLocate(#CAMERA,xcam,ycam,zcam)
CameraLookAt(#CAMERA,0,0,0)
; Move objects
For i=0 To #NBOBJ-1
obj(i)\x+obj(i)\xd
obj(i)\y+obj(i)\yd
obj(i)\z+obj(i)\zd
If obj(i)\x < #CAMERADIST/-2 Or obj(i)\x > #CAMERADIST/2
obj(i)\xd=-obj(i)\xd
EndIf
If obj(i)\y < #CAMERADIST/-2 Or obj(i)\y > #CAMERADIST/2
obj(i)\yd=-obj(i)\yd
EndIf
If obj(i)\z < #CAMERADIST/-2 Or obj(i)\z > #CAMERADIST/2
obj(i)\zd=-obj(i)\zd
EndIf
;set object To new calculated position
dist = DISTANCE(xcam,ycam,zcam,obj(i)\x,obj(i)\y,obj(i)\z) - #CAMERADIST
EntityLocate(obj(i)\numentity2, obj(i)\x - dist*#SEPARATION,obj(i)\y,obj(i)\z)
EntityLocate(obj(i)\numentity1, obj(i)\x + dist*#SEPARATION,obj(i)\y,obj(i)\z)
;make object spin every direction
RotateEntity(obj(i)\numentity1, obj(i)\xspin, obj(i)\yspin, obj(i)\zspin,#PB_Relative )
RotateEntity(obj(i)\numentity2, obj(i)\xspin, obj(i)\yspin, obj(i)\zspin,#PB_Relative )
Next i
; Render
RenderWorld()
FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
End
;- Datas
DataSection
cube:
; Nb sommets / Nb faces
Data.w 24,12
; Vertices: pos / normals / uv
cubeVert:
Data.f -0.5,0.5,-0.5
Data.f 0,1,0
Data.f 0,0
Data.f 0.5,0.5,-0.5
Data.f 0,1,0
Data.f 0,1
Data.f 0.5,0.5,0.5
Data.f 0,1,0
Data.f 1,1
Data.f -0.5,0.5,0.5
Data.f 0,1,0
Data.f 1,0
Data.f -0.5,-0.5,0.5
Data.f 0,-1,0
Data.f 0,0
Data.f 0.5,-0.5,0.5
Data.f 0,-1,0
Data.f 0,1
Data.f 0.5,-0.5,-0.5
Data.f 0,-1,0
Data.f 1,1
Data.f -0.5,-0.5,-0.5
Data.f 0,-1,0
Data.f 1,0
Data.f -0.5,0.5,0.5
Data.f 0,0,1
Data.f 0,0
Data.f 0.5,0.5,0.5
Data.f 0,0,1
Data.f 0,1
Data.f 0.5,-0.5,0.5
Data.f 0,0,1
Data.f 1,1
Data.f -0.5,-0.5,0.5
Data.f 0,0,1
Data.f 1,0
Data.f 0.5,0.5,-0.5
Data.f 0,0,-1
Data.f 0,0
Data.f -0.5,0.5,-0.5
Data.f 0,0,-1
Data.f 0,1
Data.f -0.5,-0.5,-0.5
Data.f 0,0,-1
Data.f 1,1
Data.f 0.5,-0.5,-0.5
Data.f 0,0,-1
Data.f 1,0
Data.f -0.5,0.5,-0.5
Data.f -1,0,0
Data.f 0,0
Data.f -0.5,0.5,0.5
Data.f -1,0,0
Data.f 0,1
Data.f -0.5,-0.5,0.5
Data.f -1,0,0
Data.f 1,1
Data.f -0.5,-0.5,-0.5
Data.f -1,0,0
Data.f 1,0
Data.f 0.5,0.5,0.5
Data.f 1,0,0
Data.f 0,0
Data.f 0.5,0.5,-0.5
Data.f 1,0,0
Data.f 0,1
Data.f 0.5,-0.5,-0.5
Data.f 1,0,0
Data.f 1,1
Data.f 0.5,-0.5,0.5
Data.f 1,0,0
Data.f 1,0
; Faces
cubeTri:
Data.w 2,1,0
Data.w 0,3,2
Data.w 6,5,4
Data.w 4,7,6
Data.w 10,9,8
Data.w 8,11,10
Data.w 14,13,12
Data.w 12,15,14
Data.w 18,17,16
Data.w 16,19,18
Data.w 22,21,20
Data.w 20,23,22
EndDataSection