The Ambassadors Painting and the 3D skull illusion

Everything related to 3D programming
applePi
Addict
Addict
Posts: 1404
Joined: Sun Jun 25, 2006 7:28 pm

The Ambassadors Painting and the 3D skull illusion

Post by applePi »

i have posted before about the Holbein's 'Ambassadors' Painting http://www.purebasic.fr/english/viewtop ... 12&t=50120
and i remember netmaestro note that the painting was made to be hung in a stairwell, where people climbing the steps with the painting just to their left would be startled by a perfect 3D skull staring at them
yesterday while looking at the short video in http://www.nationalgallery.org.uk/paint ... mbassadors
the professor describes that when the skull seen from a point to the right of the picture, the distortion of the skull is corrected.
Image
look also http://www.google.com/culturalinstitute ... rt-project

when i look at the picture in the LCD monitor from the right corner i can't see its coorected form, because the screen pixels does not propogate the light correctly to the sides, may be a classic old monitor with a glass screen will be better.
so why not copying the picture to a purebasic program and then rotate and move the camera until we get the view of the corrected skull !!
below is a two versions , the first are copying the picture pixels to a Mesh and it provides this corrected skull image
Image

use the following image (779 × 768 pixels) and convert it as BMP picture and not jpg
http://upload.wikimedia.org/wikipedia/c ... roject.jpg

or use this ready to use bmp compressed with winrar
http://www.2shared.com/file/v4hgRink/Ambassadors.html
if you have used pixels other than 779 × 768 then you will not get the introductory camera view
the second version are using a textured plane, but i see that the first version provides better view for the corrected skull

I have adjusted the camera so to see the corrected skull , use the arrow keys and the mouse to Move and to rotate around the picture in the 3D space, and keys A/Z to move the camera UP/Down
first version:

Code: Select all

Declare ImageMesh()
#CameraSpeed = 0.1
Enumeration
   #Ambassadors
   #camera
   #win
 EndEnumeration
 
Quit.b = #False
  

ExamineDesktops()
If OpenWindow(#win, 0, 0, DesktopWidth(0), DesktopHeight(0), "use arrow keys and mouse to rotate/move the camera ... A/Z for up and down ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
;Initialize environment
InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()
OpenWindowedScreen(WindowID(#win), 0, 0, DesktopWidth(0), DesktopHeight(0)-5, 0, 0, 0)

SetFrameRate(60)

Add3DArchive(".", #PB_3DArchive_FileSystem)
Add3DArchive(#PB_Compiler_Home + "Examples/3D/Data/Textures", #PB_3DArchive_FileSystem)

CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))

CreateCamera(#camera, 0, 0, 100, 100)
MoveCamera(#camera, 4.1826572418 ,  -2.0903768539,  8.6420898438)

CameraLookAt(#camera, 0, 2, 0)

RotateCamera(#camera, -15, 0, 0)
EndIf

;SkyDome("clouds.jpg", 100) ;for blue color background

    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    CreateMesh(#Ambassadors, #PB_Mesh_PointList, #True)
    
    SetMeshMaterial(1, MaterialID(0))
    
ImageMesh()  ; call the Image mesh construction

 
 CreateEntity(#Ambassadors, MeshID(#Ambassadors), MaterialID(0))
 ScaleEntity(#Ambassadors,0.01,0.01,0.01)
 RotateEntity(#Ambassadors, -180, -60, 0 )
 MoveEntity(#Ambassadors,1,3.0,2)
 ;SaveMesh(1, "Ambassadors.mesh") 
  
 ;Main loop
 incr.f=0.7
Repeat
  Event = WindowEvent()
  If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 1
        MouseY = -MouseDeltaY() * #CameraSpeed * 1
      EndIf
  ShowCursor_(0)
    
; use arrow keys to rotate and move in/out
  ExamineKeyboard()
      
        If KeyboardPushed(#PB_Key_Left)
          KeyX.f = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX.f = #CameraSpeed
        Else
          KeyX.f = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY.f = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY.f = #CameraSpeed
        Else
          KeyY.f = 0
        EndIf
        
        If KeyboardReleased(#PB_Key_C)
          xx.f = CameraX(#camera)
          yy.f = CameraY(#camera)
          zz.f = CameraZ(#camera)
          dx.f = CameraDirectionX(#camera)
          dy.f = CameraDirectionY(#camera)
          dz.f = CameraDirectionZ(#camera)

          Debug StrF(xx)+"   "+StrF(yy)+"   "+StrF(zz)
          Debug StrF(dx)+"   "+StrF(dy)+"    "+StrF(dz)
        EndIf
        

  y.f+incr
  ;If y>80 Or y<-10:incr=-1*incr:EndIf ; just not elaborated rotation
  ;RotateEntity(#Ambassadors, -180, y, 0) 
  RotateCamera(#camera, MouseY, MouseX, 0, #PB_Relative)
      MoveCamera  (#camera, KeyX, 0, KeyY)
   RenderWorld()
   FlipBuffers()
    
  ExamineKeyboard()
  If KeyboardPushed(#PB_Key_Z)
       MoveCamera  (#camera, KeyX, -0.01, KeyY)
     ElseIf KeyboardPushed(#PB_Key_A)
       MoveCamera  (#camera, KeyX, 0.01, KeyY)
    EndIf
  If KeyboardPushed(#PB_Key_Escape)
      Quit = #True
   EndIf
       
 Until Quit = #True Or Event = #PB_Event_CloseWindow
 
 Procedure ImageMesh()
Define image_id.i

;the reading pixel data are from Rashad code here
;http://forums.purebasic.com/english/viewtopic.php?f=13&t=48789
; load image
image_id = LoadImage( #PB_Any, "Ambassadors.bmp" )
Dim image_pixel_data.b( ImageWidth(image_id), ImageHeight(image_id) )

StartDrawing( ImageOutput( image_id ) )
For y = 0 To ImageHeight(image_id) - 1
  For x = 0 To ImageWidth(image_id) - 1
    If Point( x, y )<> 16777215
    MeshVertexPosition(x, y, 0)
    MeshVertexColor(Point( x, y ))
    EndIf
    
    Next x
Next y
StopDrawing()
FreeImage(image_id)
FinishMesh(#True ) 

EndProcedure
textured plane version

Code: Select all

#CameraSpeed = 0.1
Enumeration
   
   #texture
    #material
   #plane
   
   #camera
   #win
 EndEnumeration

Quit.b = #False
  

ExamineDesktops()
If OpenWindow(#win, 0, 0, DesktopWidth(0), DesktopHeight(0), "use arrow keys and mouse to rotate/move the camera ... A/Z for up and down ", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  
;Initialize environment
InitEngine3D()
InitSprite()
InitKeyboard()
InitMouse()
OpenWindowedScreen(WindowID(#win), 0, 0, DesktopWidth(0), DesktopHeight(0)-5, 0, 0, 0)

SetFrameRate(60)

Add3DArchive("Data/", #PB_3DArchive_FileSystem)
Add3DArchive(".", #PB_3DArchive_FileSystem)

CreateMaterial(#material, LoadTexture(#texture, "Ambassadors.bmp"))
MaterialCullingMode(#material, #PB_Material_NoCulling)
CreatePlane(#plane, 10*209.5/207, 10, 1, 1, 1, 1)
CreateEntity (#plane, MeshID(#plane), MaterialID(#material))
RotateEntity(#plane,90,0,180)
CreateLight(0,RGB(255,255,255),-100,40,30)
AmbientColor(RGB(100,100,100))

CreateCamera(#camera, 0, 0, 400, 400)
;MoveCamera(#camera, 0, 4, 9)
MoveCamera(#camera, 5.745074749 , -0.7322137356 , 1.8539280891)
CameraLookAt(#camera, 0, -2.5, 0)

;RotateCamera(#camera,0, 0, 10)
EndIf

SkyDome("clouds.jpg", 100) ;for blue color background

;- Mesh Stars
    CreateMaterial(0, LoadTexture(0, "White.jpg"))
    DisableMaterialLighting(0, #True)
    CreateMesh(1, #PB_Mesh_PointList, #True)
    
    SetMeshMaterial(1, MaterialID(0))
Procedure test()
Define image_id.i

; load image
image_id = LoadImage( #PB_Any, "Ambassadors.bmp" )
Dim image_pixel_data.b( ImageWidth(image_id), ImageHeight(image_id) )

StartDrawing( ImageOutput( image_id ) )
For y = 0 To ImageHeight(image_id) - 1
  For x = 0 To ImageWidth(image_id) - 1
    If Point( x, y )<> 16777215
    MeshVertexPosition(x, y, 0)
    ;MeshVertexColor(Point( x, y ))
    MeshVertexColor(Point( x, y ))
    EndIf
    
    Next x
Next y
StopDrawing()
FreeImage(image_id)
FinishMesh(#True ) 
CreateEntity(1, MeshID(1), MaterialID(0),0,-8,0)
Global node = CreateNode(#PB_Any)
AttachNodeObject(node, EntityID(1))
      
EndProcedure
    

 CreateMesh(2, #PB_Mesh_PointList, #True)
 
 CreateEntity(2, MeshID(1), MaterialID(0))
  
 
Repeat
  Event = WindowEvent()
  If ExamineMouse()
        MouseX = -MouseDeltaX() * #CameraSpeed * 1
        MouseY = -MouseDeltaY() * #CameraSpeed * 1
      EndIf
  ShowCursor_(0)
    
; use arrow keys to rotate and move in/out
  ExamineKeyboard()
      
        If KeyboardPushed(#PB_Key_Left)
          KeyX.f = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Right)
          KeyX.f = #CameraSpeed
        Else
          KeyX.f = 0
        EndIf
        
        If KeyboardPushed(#PB_Key_Up)
          KeyY.f = -#CameraSpeed
        ElseIf KeyboardPushed(#PB_Key_Down)
          KeyY.f = #CameraSpeed
        Else
          KeyY.f = 0
        EndIf
 
  If KeyboardPushed(#PB_Key_Z)
       MoveCamera  (#camera, KeyX, -0.2, KeyY)
     ElseIf KeyboardPushed(#PB_Key_A)
       MoveCamera  (#camera, KeyX, -(-0.2), KeyY)
  EndIf
     
If KeyboardReleased(#PB_Key_C)
          xx.f = CameraX(#camera)
          yy.f = CameraY(#camera)
          zz.f = CameraZ(#camera)
          dx.f = CameraDirectionX(#camera)
          dy.f = CameraDirectionY(#camera)
          dz.f = CameraDirectionZ(#camera)

          Debug StrF(xx)+"   "+StrF(yy)+"   "+StrF(zz)
          Debug StrF(dx)+"   "+StrF(dy)+"    "+StrF(dz)
        EndIf
             
  RotateCamera(#camera, MouseY, MouseX, 0, #PB_Relative)
  MoveCamera  (#camera, KeyX, 0, KeyY)
  
  RenderWorld()
   FlipBuffers()

  ExamineKeyboard()
   If KeyboardPushed(#PB_Key_Escape)
      Quit = #True
   EndIf
       
Until Quit = #True Or Event = #PB_Event_CloseWindow