The Ambassadors Painting and the 3D skull illusion
Posted: Sun Dec 01, 2013 9:24 am
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.

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

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:
textured plane version
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.

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

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 )
EndProcedureCode: 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