Altglass

Seit einiger Zeit schon habe ich ne Panasonic G1, also eine sogenannte “Systemkamera” bei der man Objektive wechseln kann. Das eröffnet dann ungeahnte Möglichkeiten des Geldausgebens, da es immer noch ein weiteres Objektiv gibt das man noch kaufen könnte. Der Preis eines solchen Objektivs kann dann schon mal den Preis der Kamera + Kit-Objektiv um ein mehrfaches übersteigen.
Zum Glück gibt es für experimentierfreudige Menschen Alternativen. Fotografie ist nichts Neues und daher gibt es einen riesigen Fundus an “Altglas”, der dank Adapter an die modernen Kameras angeschraubt werden kann. Man verliert nur den doch eigentlich recht unwichtigen Autofokus. Angefangen habe ich mit nem lichtstarken, russischen, 50 Jahre alten 50mm Objektiv. Nach einiger Zeit habe ich mit dem mehr fotografiert als mit dem original Kit-Objektiv.
Das hat Lust auf mehr gemacht. Mittlerweile habe ich einige Objektive die ich für nen Appel und nen Ei aus der Bucht gefischt hab. Letzte Woche hab ich mir dann ein Panagor 90mm Macro geleistet. Für immer noch den Bruchteil dessen hab ich jetzt ein Macro das bei Masstab 1:1 20mm kleine Sachen Bildschirmfüllend abbilden kann. Man macht das Spaß. Mehr Bilder auf http://www.orgetik.de/cpg

Ja, ich hab eins und ich liebe es. Mein schnuckeliges kleines Linuxgerät für die Hosentasche. Ich mag auch Python. Seit ich Python programmiere mag ich C++ nicht mehr und Java auch nicht. Und ich mag 3D. Bunt muss es sein und programmierbar und flexibel, so wie… so wie OpenGL ES2.0. Genau. Aber geht das alles zusammen?

Klar geht das. Über das ctypes interface kann ich grundsaetzlich jede system library benutzen. OpenGL ist sogar relativ einfach, nur woher bekommt man ein Fenster zum reinzeichnen? Xlib ist eine Moeglichkeit, nur sind die X Datenstrukturen so hässlich das ich keine Lust hatte ctype varianten dafuer anzufertigen. Gluecklicherweise haben das schon andere gemacht. Pyglet ist eine ctypes basierte cross plattform windowing und multimedia library die auch einen python wrapper fuer Xlib beinhaltet. Damit habe ich das maemo.org SimpleGL example als “proof of concept” nach python portiert.

Der port ist absolut minimal, den EGL/OpenGL part habe ich manuell ueber ctypes angesprochen und nur das noetigste gemapt, Pyglet beinhaltet ein script das viel schoenere wrapper aus egl.h und gl2.h automatisch bauen koennte. Schoener machen könnt ihr es aber selber :-P

Hier jedenfalls der Port, vieleicht hillft es ja dem Einen oder Anderen.

Hier der Xlib wrapper pyglet,ich habe nur die Abhaengigkeit von pyglet.lib.load beseitigt indem ich libX11.so.6 direkt lade:

xlib wrapper.py

Und hier der port des OpenGL Beispieles:

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"

göttliches Wirken

Kürzlich (naja, ist auch schon wieder 3 Wochen her) bin ich tatsächlich in den Urlaub gefahren. 2 Wochen Rügen waren angesagt. Der Plan war richtig gründlich zu entspannen, viele Standspaziergänge zu machen und vielleicht auch ein paar Bernsteine zu finden.

Der Winter hatte die Insel noch ziemlich fest im Griff, an einigen Stellen lag der Schnee noch meterhoch und am Strand türmte sich das Eis zu abstrakten Skulpturen . Allerdings waren milde Tage im Anmarsch und damit waren die Voraussetzung ideal, um uns auf der um diese Jahreszeit Touristen-leeren Insel zu entspannen.

kueste eispanzer

..wenn das Mysterium der toten Schwäne nicht gewesen währe.

Schon bei unserem ersten kurzen Standspaziergang fielen uns die Schwanenkadaver auf. Als wir unsere Streifzüge ausdehnten, begannen wir bald die zurückgelegte Strecke in “tS” zu messen. (=tote Schwäne, wir wanderten maximal 14 tS in die eine und 16tS in die andere Richtung am Strand entlang. Alle Tiere schienen erst vor Kurzem gestorben zu sein.

Zuerst maßen wir dem nicht viel Bedeutung bei. Dann fiel uns eine andere Merkwürdigkeit auf: wir fanden außergewöhnlich große Mengen an Donnerkeilen am Strand. Insgesamt sammelten wir während des Urlaubs so 2kg Donnerkeile. Natürlich weiss ich, das nach vorherrschender Lehrmeinung diese Donnerkeile als fossile Überbleibsel von Belemniten betrachtet werden. In Legenden allerdings werden sie als die Waffen Thors beschrieben, die nach einer wilden Jagd in stürmischer Nach morgens am Strand zurückbleiben. Göttliche Waffen und tote Schwäne: Zufall? Mein sonst agnostischer Standpunkt wankt. Donnerkeile werden auch mit dem griechischen Gott Zeus in Verbindung gebracht. Und der hat ja bekanntlich selbst die Schwanengestalt schon benutzt. Noch ein Zufall?

Wir konnten schlussendlich nicht klären ob es Zeus oder Thor war der für den Tod der Schwäne verantwortlich war. Und auch das Schildkröten-Alien das ich später am Strand entdeckte wollte mir dazu keine Auskunft erteilen. Aber da ich insgesamt doch 3 recht schöne Bernsteine gefunden habe, ist mir das dann auch egal. An unserem letzten Urlaubstag waren die Kadaver jedenfalls auf magische Weise verschwunden.

kormoran eis
kitsch

Taschenmesser

Der Grund dafür das ich meinen webspace so lange nicht genutzt habe, ist wahrscheinlich das ich viel zu beschäftigt war mit meinen anderen Hobbys. Eines davon ist die Messermacherei. Bisher habe ich hauptsächlich feststehende Messer gebaut, wollte aber schon immer eines zum immer Dabei haben bauen.

slipjoint size

Ursprünglich wollte ich ein  back-lock Taschenmesser bauen. Da es allerdings mein erstes Klappmesser ist, entschied ich mich für die Klinge ein kleines Reststück Schweissdamast zu benutzen.  (natürlich hab ich vorher eine Testklinge aus einem einfachen Stahlrest gemacht :-) ). Das Damaststück hatte ich schon fertig geschmiedet, fand es aber zu klein für ein feststehendes Messer.  Da es so klein war, habe ich auf den back-lock zugunsten eines einfacheren slipjoint mechanismus verzichtet. Den Damast besteht aus schwedischem C75 und japanischen weissen Papier Stahl.

slipjoint open

Die Griffschalen sind aus Mammut Elfenbein das ich schon vor Jahren gekauft hatte, als es noch auf ebay gehandelt wurde. Ich liebe dieses Material, es ist zehntausende Jahre alt, lässt sich super bearbeiten und sieht nach der Politur wundervoll aus mit all seinen Rissen und Verfärbungen. Für die Backen hatte ich dann keine ausgefallenen Materialien mehr übrig :-)

slipjoint front

Ich hab für die Backen Stücke Werkzeugstahl benutzt (1.2842) den ich mit einer Lötlampe gebläut habe. Die Rahmenteile aus Titanresten hab ich auch versucht blau zu färben, fand es aber schwer eine gleichmässige Färbung zu erzeugen.

Das ist nun ein ziemlicher Mischmasch von Materialien. Im Endeffekt war es halt auch ein Möglichkeit für mich, alle möglichen Sachen auszuprobieren. Die Schrauben sind auch recycled, aus alten Festplatten zum grössten Teil. Es war ganz schön schwer unter all den Schrauben welche mit metrischem Gewinde zu finden.

slipjoint closed

Die Achse habe ich mit einer Drehmaschine gefertigt. Meine Drehmaschine ist wahrscheinlich mehr als 50 Jahre alt und in keinem guten Zustand. Eigentlich kein Gerät für Präzisionsarbeiten. Aber ich hab sie fast für Umsonst bekommen als ich mein Haus gekauft hab. (zusammen mit einer 12to, riemengetriebenen Excenterpresse für die ich noch keine richtige Verwendung gefunden habe).

Ich denke es ist Überflüssig zu erwähnen das ich recht Zufrieden mit dem Ergebnis bin ;-)

slipjoint disassembled

Wilkommen!

Hi,

heute fange ich endlich mal an in mein blog zu posten. Mein webspace, den ich nun schon 4-5 Jahre lang bezahle, soll endlich mal genutzt werden.
Ich werde alle möglichen Sachen hier posten, vermutlich am meisten über meine Hobbys
Den blog werde ich versuchen zweisprachig zu halten, mal sehen ob ich das durchhalte.

have fun,
Jan

knife2 orgebraeu_dicker-man2