From: "mpthompson at gmail.com" Date: 2006-09-21T02:35:19+09:00 Subject: Re: Opengl Tk widget for Ruby? mpthompson at gmail.com wrote: > Hidetoshi NAGAI wrote: > > There is a section "Windows 95/NT/2000/XP usage" on > > . > > However, Togl seems to be integrated into Tcl3D . I think I'm getting close to getting OpenGL and Tk playing nice in Ruby, but I'm not quite there yet. Any help would be appreciated. Based on the suggestion above I was able to get the Tcl3D installed with ActiveTcl 8.4 and get the Tcl based OpenGL demos distributed with Tcl3D working fine on my system. Next, I used Hidetoshi's code as a guide to create a simple wrapper, after a bit of fussing to determine the right way to get the tcl3d dll loaded, I created wrapper for togl within Tcl3D as shown below which includes an addition for postredisplay: --------------------------------------------------------- # # Togl wrapper for tcl3d Tk extension. # TkPackage.require('tcl3d') class Tk::Togl < TkWindow # By default, the constracter of a widget class (subclass of TkWindow) # uses TkCommandNames[0] as a command to create a widget object. TkCommandNames = ['togl'.freeze].freeze # The following definitions are used to create a widget object # from a widget path string. WidgetClassName = 'Togl'.freeze WidgetClassNames[WidgetClassName] = self def postredisplay tk_send_without_enc('postredisplay') self end def render tk_send_without_enc('render') self end def swapbuffers tk_send_without_enc('swapbuffers') self end def make_current tk_send_without_enc('makecurrent') self end end # f = TkFrame.new # togl_obj1 = Tk::Togl.new(f, :width=>200, :height=>200, :ident=>'Single', # :rgba=>true, :double=>false, :depth=>true).pack # togl_obj2 = Tk::Togl.new(f, :width=>200, :height=>200, :ident=>'Double', # :sharelist=>'Single', # :rgba=>true, :double=>true, :depth=>true).pack # togl_obj1.bind('B1-Motion', proc{....}) --------------------------------------------------------- Now I'm trying to get the standard gears.rb OpenGL application running within the tk managed window. This is where I'm really getting lost. I posted below the application as it looks now, but it isn't working and the window just comes up blank. I assume I'm missing something fundamental here. I'm hoping someone could either provide a working example of a Tk/OpenGL application using togl or help steer me in where my code is failing below. Thanks, Mike Thompson --------------------------------------------------------- # 2005-05-01 Ruby version by Arto Bendiken based on gears.c rev 1.8. # 2005-01-09 Original C version (gears.c) by Brian Paul et al. # http://cvs.freedesktop.org/mesa/Mesa/progs/demos/gears.c?rev=1.8 require 'opengl_c' require 'glut_c' require 'tk' require 'tkextlib/tkHTML' require 'togl' include OpenGL include Glut class Gears POS = [5.0, 5.0, 10.0, 0.0] RED = [0.8, 0.1, 0.0, 1.0] GREEN = [0.0, 0.8, 0.2, 1.0] BLUE = [0.2, 0.2, 1.0, 1.0] include Math # Draw a gear wheel. You'll probably want to call this function when # building a display list since we do a lot of trig here. # # Input: inner_radius - radius of hole at center # outer_radius - radius at center of teeth # width - width of gear # teeth - number of teeth # tooth_depth - depth of tooth def gear(inner_radius, outer_radius, width, teeth, tooth_depth) r0 = inner_radius r1 = outer_radius - tooth_depth / 2.0 r2 = outer_radius + tooth_depth / 2.0 da = 2.0 * PI / teeth / 4.0 glShadeModel(GL_FLAT) glNormal(0.0, 0.0, 1.0) # Draw front face glBegin(GL_QUAD_STRIP) for i in 0..teeth angle = i * 2.0 * PI / teeth glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5) glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5) if i < teeth glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5) glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5) end end glEnd() # Draw front sides of teeth glBegin(GL_QUADS) for i in 0...teeth angle = i * 2.0 * PI / teeth glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5) glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5) glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5) glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5) end glEnd() glNormal(0.0, 0.0, -1.0) # Draw back face glBegin(GL_QUAD_STRIP) for i in 0..teeth angle = i * 2.0 * PI / teeth glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5) glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5) if i < teeth glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5) glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5) end end glEnd() # Draw back sides of teeth glBegin(GL_QUADS) for i in 0...teeth angle = i * 2.0 * PI / teeth glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5) glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5) glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5) glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5) end glEnd() # Draw outward faces of teeth glBegin(GL_QUAD_STRIP) for i in 0...teeth angle = i * 2.0 * PI / teeth glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5) glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5) u = r2 * cos(angle + da) - r1 * cos(angle) v = r2 * sin(angle + da) - r1 * sin(angle) len = sqrt(u * u + v * v) u /= len v /= len glNormal(v, -u, 0.0) glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5) glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5) glNormal(cos(angle), sin(angle), 0.0) glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5) glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5) u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da) v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da) glNormal(v, -u, 0.0) glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5) glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5) glNormal(cos(angle), sin(angle), 0.0) end glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5) glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5) glEnd() glShadeModel(GL_SMOOTH) # Draw inside radius cylinder glBegin(GL_QUAD_STRIP) for i in 0..teeth angle = i * 2.0 * PI / teeth glNormal(-cos(angle), -sin(angle), 0.0) glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5) glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5) end glEnd() end def draw glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix() glRotate(@view_rotx, 1.0, 0.0, 0.0) glRotate(@view_roty, 0.0, 1.0, 0.0) glRotate(@view_rotz, 0.0, 0.0, 1.0) glPushMatrix() glTranslate(-3.0, -2.0, 0.0) glRotate(@angle, 0.0, 0.0, 1.0) glCallList(@gear1) glPopMatrix() glPushMatrix() glTranslate(3.1, -2.0, 0.0) glRotate(-2.0 * @angle - 9.0, 0.0, 0.0, 1.0) glCallList(@gear2) glPopMatrix() glPushMatrix() glTranslate(-3.1, 4.2, 0.0) glRotate(-2.0 * @angle - 25.0, 0.0, 0.0, 1.0) glCallList(@gear3) glPopMatrix() glPopMatrix() @glwin.swapbuffers end def idle #t = glutGet(GLUT_ELAPSED_TIME) / 1000.0 #@t0_idle = t if !defined? @t0_idle # 90 degrees per second #@angle += 70.0 * (t - @t0_idle) #@t0_idle = t #@glwin.postredisplay end # Change view angle, exit upon ESC def key(k, x, y) case k when ?z @view_rotz += 5.0 when ?Z @view_rotz -= 5.0 when 27 # Escape exit end @glwin.postredisplay end # Change view angle def special(k, x, y) case k when GLUT_KEY_UP @view_rotx += 5.0 when GLUT_KEY_DOWN @view_rotx -= 5.0 when GLUT_KEY_LEFT @view_roty += 5.0 when GLUT_KEY_RIGHT @view_roty -= 5.0 end @glwin.postredisplay end # New window size or exposure def reshape(width, height) h = height.to_f / width.to_f glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslate(0.0, 0.0, -40.0) end def init @angle = 0.0 @view_rotx, @view_roty, @view_rotz = 20.0, 30.0, 0.0 glLightfv(GL_LIGHT0, GL_POSITION, POS) glEnable(GL_CULL_FACE) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_DEPTH_TEST) # Make the gears @gear1 = glGenLists(1) glNewList(@gear1, GL_COMPILE) glMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, RED) gear(1.0, 4.0, 1.0, 20, 0.7) glEndList() @gear2 = glGenLists(1) glNewList(@gear2, GL_COMPILE) glMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, GREEN) gear(0.5, 2.0, 2.0, 10, 0.7) glEndList() @gear3 = glGenLists(1) glNewList(@gear3, GL_COMPILE) glMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, BLUE) gear(1.3, 2.0, 0.5, 10, 0.7) glEndList() glEnable(GL_NORMALIZE) ARGV.each do |arg| case arg when '-info' printf("GL_RENDERER = %s\n", glGetString(GL_RENDERER)) printf("GL_VERSION = %s\n", glGetString(GL_VERSION)) printf("GL_VENDOR = %s\n", glGetString(GL_VENDOR)) printf("GL_EXTENSIONS = %s\n", glGetString(GL_EXTENSIONS)) when '-exit' @autoexit = 30 printf("Auto Exit after %i seconds.\n", @autoexit); end end end def visible(vis) #glutIdleFunc((vis == GLUT_VISIBLE ? method(:idle).to_proc : nil)) end def mouse(button, state, x, y) @mouse = state @x0, @y0 = x, y end def motion(x, y) if @mouse == GLUT_DOWN then @view_roty += @x0 - x @view_rotx += @y0 - y end @x0, @y0 = x, y end def initialize @root = TkRoot.new @frame = TkFrame.new(@root) @glwin = Tk::Togl.new(@frame, :width=>300, :height=>300, :ident=>'Single', :rgba=>true, :depth=>true, :double=>false).pack('fill'=>'both') init() end def start Tk.mainloop end end Gears.new.start ---------------------------------------------------------