old lenses

For quite some time now, i own a Panasonic g1. A so called “system camera” with interchangeable lenses. That opens up completely new ways to spend money since there is now always just another lens that one might need. The price of such lenses is often a multiple of what the camera + kit lens cost.
Luckily there are alternatives, at least for adventurous people. Photography has been around for some time and because of that, there is a huge reservoir of old lenses available that, with the help of adapters, can be screwed onto the modern cameras. You only lose the mostly irrelevant auto-focus ;-) I started with a fast f1.5 50mm lens that is 50 years old. Over time i started taking more photos with this than with the original kit lens.
That increased my appetite. i currently own some lenses that i catched cheaply in the bay. Last week i then went for a Panagor 90mm macro lens. It is still a bargain compared to the modern lenses but being able to shot 1:1 macros i now can make a 20mm object fill the screen. That is a lot of fun!
More images on http://www.orgetik.de/cpg

Yes, i have one and love it. My cute little pocketable linux device. I also like python a lot. Since i program in python i do not like C++ or Java anymore. And i love 3D. Colorfull, programmable and flexible it has to be, exactly like… like OpenGL ES2 Exactly. But does all this fit together?

Of course it does. With the ctypes interface, in principle any system library can be accessed. OpenGL is actually even relatively easy. But where do i get a window to render into from?Xlib is a possibility, but its data structures i did not really want to create ctypes variants for. Fortunately someone else did already. Pyglet is a ctypes based  cross plattform windowing and multimedia library that also containes a wrapper for Xlib. That i used to do a proof of concept port of the  maemo.org SimpleGL example to python.

It is an absolutely minimal port, the EGL/OpenGL i did manualy via ctypes, mapping only whats necessary to get it to run. Pyglet actually contains a script that could be used to create much nicer wrappers from  egl.h und gl2.h. But the beautifying i leave up to you :-P

Here is the port anyway, hope it helps someone.

this is the wrapper from pyglet, i did only do one modification, i directly load libX11.so.6 instead of using using pyglet.lib.load:

xlib wrapper.py

and here is the simple example:

opengltest.py

from ctypes import *
import os
import math
import sys
import time
import xlib_wrapper
egl =  cdll.LoadLibrary( "libEGL.so")
glesv2=  cdll.LoadLibrary( "libGLESv2.so")

#############################################################
#global defs for Opengl
GLuint = c_uint
GLint = c_int
GLenum = c_uint
GLfloat = c_float

GL_TRUE = 1
GL_FALSE = 0
GL_FLOAT = 0x1406

GL_COLOR_BUFFER_BIT = 0x00004000
GL_TRIANGLE_STRIP = 0x0005
GL_TRIANGLE_FAN                   =0x0006

GL_VERTEX_SHADER = 0x8b31
GL_FRAGMENT_SHADER = 0x8b30

GL_COMPILE_STATUS = 0x8b81
GL_INFO_LOG_LENGTH = 0x8b84

##############################################################
#simple shader programs
vertexShaderSrc = c_char_p(
"                                        \
   attribute vec4        position;       \
   varying mediump vec2  pos;            \
   uniform vec4          offset;         \
                                         \
   void main()                           \
   {                                     \
      gl_Position = position + offset;   \
      pos = position.xy;                 \
   }                                     \
")
fragmentShaderSrc = c_char_p(
"                                                      \
   varying mediump vec2    pos;                        \
   uniform mediump float   phase;                      \
                                                       \
   void  main()                                        \
   {                                                   \
      gl_FragColor  =  vec4( 1., 0.9, 0.7, 1.0 ) *     \
        cos( 30.*sqrt(pos.x*pos.x + 1.5*pos.y*pos.y)   \
             + atan(pos.y,pos.x) - phase );            \
   }                                                   \
")
VAType= GLfloat*15
vertexArray = VAType(
   0.0,  0.5,  0.0,
  -0.5,  0.0,  0.0,
   0.0, -0.5,  0.0,
   0.5,  0.0,  0.0
)
updatePos = True
phase = 0.0
norm_x    =  0.0
norm_y    =  0.0
offset_x  =  0.0
offset_y  =  0.0
p1_pos_x  =  0.0
p1_pos_y  =  0.0

##############################################################

def printShaderInfoLog (shader):

   length = GLint()
   glesv2.glGetShaderiv ( shader , GL_INFO_LOG_LENGTH , byref(length) )

   print length.value
   if length.value >0:
      buffer  =  create_string_buffer(length.value)
      glesv2.glGetShaderInfoLog ( shader , length , None , byref(buffer) );
      print "shader info "+str( buffer.value)
      success = GLint();
      glesv2.glGetShaderiv( shader, GL_COMPILE_STATUS, byref(success) )
      if success.value != GL_TRUE :
        print "failed to compile shader"

############################################################

def loadShader ( shader_source, type):
   shader = glesv2.glCreateShader( type );
   glesv2.glShaderSource  ( shader , 1 , byref(shader_source) , None );
   glesv2.glCompileShader ( shader );

   printShaderInfoLog( shader )

   return shader

############################################################

def createOglWindow(name):
  #needs error checking
  display = xlib_wrapper.XOpenDisplay (os.getenv ( "DISPLAY"))
  screen = xlib_wrapper.XDefaultScreen (display)
  root = xlib_wrapper.XDefaultRootWindow (display, screen)
  windowAttributes=xlib_wrapper.XSetWindowAttributes()
  windowAttributes.event_mask = (
               xlib_wrapper.PointerMotionMask
              | xlib_wrapper.KeyPressMask
              | xlib_wrapper.KeyReleaseMask
              | xlib_wrapper.ExposureMask
              | xlib_wrapper.ButtonPressMask
              | xlib_wrapper.ButtonReleaseMask
              )

  window = xlib_wrapper.XCreateWindow(display,root,0,0,800,480,0,
            xlib_wrapper.CopyFromParent,
            xlib_wrapper.InputOutput,
            xlib_wrapper.XDefaultVisual(display,screen),
            xlib_wrapper.CWEventMask,
            byref(windowAttributes) )

  xattr=xlib_wrapper.XSetWindowAttributes()
  xattr.override_redirect=False
  xlib_wrapper.XChangeWindowAttributes(display,window,xlib_wrapper.CWOverrideRedirect,byref(xattr))

  atom=xlib_wrapper.XInternAtom(display,"_NET_WM_STATE_FULLSCREEN",True)
  xlib_wrapper.XChangeProperty(display,window,
            xlib_wrapper.XInternAtom(display,"_NET_WM_STATE",True ),
            xlib_wrapper.XInternAtom(display,"ATOM",False),
            32,
            xlib_wrapper.PropModeReplace,
            cast( pointer((xlib_wrapper.Atom)(atom)), POINTER(c_ubyte)),
            1
            )

  xlib_wrapper.XChangeProperty(display,window,
            xlib_wrapper.XInternAtom(display,"_HILDON_NON_COMPOSITED_WINDOW",True ),
            xlib_wrapper.XInternAtom(display,"INTEGER",False),
            32,
            xlib_wrapper.PropModeReplace,
            cast( pointer(c_ulong(1)), POINTER(c_ubyte)),
            1
            )
  xlib_wrapper.XMapWindow(display, window)
  xlib_wrapper.XStoreName(display,window,name)

  wm_state=xlib_wrapper.XInternAtom(display,"_NET_WM_STATE",False)
  fullscreen=xlib_wrapper.XInternAtom(display,"_NET_WM_STATE_FULLSCREEN",False)

  xev = xlib_wrapper.XEvent()
  xev.type=xlib_wrapper.ClientMessage
  xev.xclient.window=window
  xev.xclient.message_type=wm_state
  xev.xclient.format=32
  xev.xclient.data.l[0]=1
  xev.xclient.data.l[1]=fullscreen
  xlib_wrapper.XSendEvent(display,root,False,xlib_wrapper.SubstructureNotifyMask,byref(xev))

  #now for the egl part
  #needs error checking
  eglDisplay= egl.eglGetDisplay(display)
  egl.eglInitialize(eglDisplay,None,None)
  Attr5=c_ulong*5
  attr=Attr5(
         0x3020,#EGL_BUFFER_SIZE
         16,
         0x3040,#EGL_RENDERABLE_TYPE
         0x0004,#EGL_OPENGL_ES2_BIT
         0x3038 #EGL_NONE
         )
  numConfig=c_ulong()
  ecfg=c_void_p()
  egl.eglChooseConfig(eglDisplay,attr,byref(ecfg),1,byref(numConfig))
  eglSurface=egl.eglCreateWindowSurface(eglDisplay,ecfg,window,None,)
  Attr3=c_ulong*3
  ctxattr=Attr3(
         0x3098,#EGL_CONTEXR_CLIENT_VERSION
         2,
         0x3038 #EGL_NONE
         )
  eglContext=egl.eglCreateContext(eglDisplay,ecfg,0,ctxattr)
  egl.eglMakeCurrent( eglDisplay, eglSurface, eglSurface, eglContext );
  xlib_wrapper.XSetInputFocus(display,root,xlib_wrapper.RevertToParent,xlib_wrapper.CurrentTime)
  xlib_wrapper.XSetInputFocus(display,window,xlib_wrapper.RevertToParent,xlib_wrapper.CurrentTime)

  return display,window,eglDisplay,eglSurface,eglContext

##############################################################

def render():
   global phase
   global updatePos
   global offset_x
   global offset_y
   global p1_pos_x
   global p1_pos_y

   glesv2.glClear ( GL_COLOR_BUFFER_BIT )

   glesv2.glUniform1f ( phaseLoc , GLfloat(phase) )
   phase  =  math.fmod ( phase + 0.5 , 2. * 3.141 )    

   if updatePos == True:
     old_offset_x  =  offset_x
     old_offset_y  =  offset_y

     offset_x  =  norm_x - p1_pos_x
     offset_y  =  norm_y - p1_pos_y

     p1_pos_x  =  norm_x
     p1_pos_y  =  norm_y

     offset_x  +=  old_offset_x
     offset_y  +=  old_offset_y

     updatePos = False

   glesv2.glUniform4f ( offsetLoc  ,  GLfloat(offset_x) , GLfloat(offset_y) , GLfloat(0.0) , GLfloat(0.0) )

   glesv2.glVertexAttribPointer ( positionLoc, 3, GL_FLOAT, GL_FALSE, 0, vertexArray );
   glesv2.glEnableVertexAttribArray ( positionLoc );
   glesv2.glDrawArrays ( GL_TRIANGLE_FAN, 0, 4 );

   egl.eglSwapBuffers ( eglDisplay, eglSurface );  

##############################################################
def cleanUp():
  egl.eglDestroyContext(eglDisplay,eglContext)
  egl.eglDestroySurface(eglDisplay,eglSurface)
  egl.eglTerminate(eglDisplay)
  xlib_wrapper.XDestroyWindow(xDisplay,xWindow)
  xlib_wrapper.XCloseDisplay(xDisplay)

##############################################################  

#ceate a suitable window
xDisplay,xWindow,eglDisplay,eglSurface,eglContext = createOglWindow("test")
#now the ogl parts-----------------------

#set up shader
vertexShader=loadShader(vertexShaderSrc,GL_VERTEX_SHADER)
fragmentShader=loadShader(fragmentShaderSrc,GL_FRAGMENT_SHADER)
shaderProgram=glesv2.glCreateProgram()
glesv2.glAttachShader(shaderProgram,vertexShader)
glesv2.glAttachShader(shaderProgram,fragmentShader)
glesv2.glLinkProgram(shaderProgram)
glesv2.glUseProgram(shaderProgram)
#location of shader params
positionLoc  = glesv2.glGetAttribLocation(shaderProgram,c_char_p("position") )
phaseLoc     = glesv2.glGetUniformLocation(shaderProgram,c_char_p("phase")    )
offsetLoc    = glesv2.glGetUniformLocation(shaderProgram,c_char_p("offset")   )
print str(positionLoc) + str(phaseLoc) + str(offsetLoc)            

window_width  = 800.0
window_height = 480.0

gwa =  xlib_wrapper.XWindowAttributes()
xlib_wrapper.XGetWindowAttributes ( xDisplay , xWindow , byref(gwa) )
glesv2.glViewport ( 0 , 0 , gwa.width , gwa.height )
glesv2.glClearColor ( GLfloat(0.308) , GLfloat(0.06) , GLfloat(0.07) , GLfloat(1.))

quit = False
while quit == False:
  while xlib_wrapper.XPending ( xDisplay ):
    xev = xlib_wrapper.XEvent()
    xlib_wrapper.XNextEvent( xDisplay, byref(xev) )
    print ""
    print xev.type
    print ""
    if xev.type == xlib_wrapper.MotionNotify:
      print "moveto " + str(xev.xmotion.x) + "," + str(xev.xmotion.y)
      window_y  =  (window_height - xev.xmotion.y) - window_height / 2.0;
      norm_y            =  window_y / (window_height / 2.0)
      window_x  =  xev.xmotion.x - window_width / 2.0
      norm_x            =  window_x / (window_width / 2.0)
      updatePos = True

    if xev.type == xlib_wrapper.KeyPress:
      print "keypress"
      quit = True

  render()

#end and cleanup------------------------
time.sleep (1)
cleanUp()
print "done"

divine intervention

Recently (ok, that actually means 3 weeks ago in this case) i finally went on vacation. I spend 2 weeks on Rügen, Germany’s largest island in the Baltic see. To thoroughly relax was the plan, to make many walks along the beach and maybe to find some Baltic amber.

Winter still had the island in its clutches. Snow was covering the ground, meter high in places and the ice formed abstract sculptures on the beach. But mild weather was approaching and the general lack of other tourists during this time of the year provided ideal prerequisites for getting rid of any stress.

kueste eispanzer

..if we would not have had to face the mystery of the dead swans..

Even on our first short walk we noticed the dead bodies. When we finaly extended our trips, we soon started to measure distances in “dS” (=dead Swans, our maximum travel distance along the beach was 14 dS in one direction and 16 dS in the other) All seem to have died recently.

We did not take this very seriously at first. But then we noticed something else: we found extremely large amounts of what is often called “thunder bolts” at the beach. We altogether collected about 2kg of those. Of course i know that common knowledge accounts those to be the fossil remains of belemnites. But legends tell that those are the weapons of Thor and usually can be found on the beach in the morning after his savage hunt through the stormy night. Divine weapons and dead swans anyone? My agnostic point of view is shaking. Thunderbolts are also the weapons of the greek deity Zeus. And he has reportedly used the form of a swan himself! Another coincidence?

We were unable to clarify in the end whether Zeus or Thor were responsible for murdering the swans. The turtle alien i met at the beach another day also did not want to clarify the matter. But since in the finallyi found 3 nice pieces of Baltic amber, i did not care too much after all. On the last day of my vacation, the cadavers had magically vanished anyway.

kormoran eis
kitsch

Slipjoint folder

The reason for not using my webspace in the past is probably that i was to busy with my many other hobbies. One is knifemaking. I mostly did fixed blade knifes until now, but always wanted something to carry around every day.

slipjoint size

Originally i wanted to make a back-lock folder. But since this is my first folder i decided to use a small piece of pattern welded steel i had forged some time ago, but which was to small for a fixed blade knife. (of course i used it only after i made a prototype out of scrap steel :-) ) Since the knife would become rather small, i decided to skip the back-lock and go with a simpler slipjoint mechanism. The steel was forged from Swedish C75 and Japanese white paper steel.

slipjoint open

For the handle i used pieces of mammoth ivory i bought several years ago when it was still sold on ebay. I love this material, it is 10’s of thousands of years old, can be carved easily and looks stunning after polishing with all its cracks and colors . For the bolsters i did not have any special materials left :-)

slipjoint front

So i had to use what i had lying around which was a bit of tool steel (1.2842) I heat blued it with a blow-torch.  I tried heat bluing also for the frame parts which are made of some scrap titan, but i found it hard to get an even color.

Ok this is quite a mix of materials, in the end i needed also a test bed for trying all kinds of things. Also the screws are recycled from old hard disk drives. It was actually pretty hard to find metric ones among them.

slipjoint closed

The axis was machined with a lathe. My lathe is probably more then 50 years old and quite bad, nothing for precise machining. But i got it basically for free when i bought my house (together with a belt driven 12to excenter press that i currently do not know what to use it for).

I think i do not have to tell you that i am pretty happy with the result :-)

slipjoint disassembled

Welcome!

Hi,

today i will finally start posting in my blog. My webspace, which i payed for the last 4-5 years, will finally be put to some use.
I will post all kinds of things here, probably mostly about hobby stuff.
I will try to keep this blog bilingual, lets see if i can manage this.

Have fun!
Jan

knife2 orgebraeu_dicker-man2