Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Jan 31, 2009

Ruby 1.9.1-p0 : VC++ 2008 Express Edition でビルド


「Ruby 1.9.1をリリースしました。」、ということで作業メモ。
  • OS は Windows Vista SP1 (Home Premium) です。
  • "D:\Programs\Microsoft Visual Studio 9.0" に VC++ 2008 をインストールしてあります。
  • ところどころで cygwin 由来のツール (wget、tar, gzip, bzip2) を使っています。
まずスタートメニューから「Visual C++ 9.0 Express Edition > Visual Studio Tools > Visual Studio 2008 コマンド プロンプト」起動。作業場へ移動します。
D:\Programs\Microsoft Visual Studio 9.0\VC> d:
D:\> cd tmp
D:\tmp>
ソースをいただいてきたら展開しておきます。
D:\tmp> wget ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p0.tar.bz2
...
D:\tmp> tar xvjf ruby-1.9.1-p0.tar.bz2
...
インストール先を指定して configure.bat を実行します。ここでは d:/ruby19 とします。
D:\tmp> cd ruby-1.9.1-p0
D:\tmp\ruby-1.9.1-p0> win32\configure.bat --prefix=d:/ruby19
Creating Makefile
confargs.c
type `D:\Programs\Microsoft Visual Studio 9.0\VC\BIN\nmake.exe to make ruby.
D:\tmp\ruby-1.9.1-p0>
ビルドとインストールを実行します。
※ 'compiling tk' の部分で時間がかかります。Tkのヘッダーファイルが無いかどうか、様々なインクルードパスを試しているようです。
D:\tmp\ruby-1.9.1-p0> nmake
...
D:\tmp\ruby-1.9.1-p0> nmake install
...
D:\tmp\ruby-1.9.1-p0> d:\ruby19\bin\ruby -v
ruby 1.9.1p0 (2009-01-30 revision 21907) [i386-mswin32_90]
ここまでの作業では RubyGems の実行に必要となる zlib.so がビルドされていません。以下で zlib.so のビルドとインストールを行います。 今 Ruby をビルドしたディレクトリはそのままにしておいて、適当な作業場へ移動します。
D:\tmp\ruby-1.9.1-p0>cd ..
zlib のソースコードをいただいて、ビルドを実行します。
D:\tmp> wget http://www.zlib.net/zlib-1.2.3.tar.gz
D:\tmp> tar xvzf zlib-1.2.3.tar.gz
D:\tmp> cd zlib-1.2.3
D:\tmp\zlib-1.2.3> nmake -f win32\Makefile.msc
D:\tmp\zlib-1.2.3> mt -manifest zlib1.dll.manifest -outputresource:zlib1.dll;2
Makefile.msc にはマニフェストを埋め込む記述が無かったので、手動で埋め込んでいることに注意してください。
できあがった zlib1.dll を ruby.exe が配置されている場所にコピーしておきます。
D:\tmp\zlib-1.2.3> copy zlib1.dll d:\ruby19\bin
zlib.so のビルドを行います。Ruby をビルドしたディレクトリにある ext\zlib へ移動します。
D:\tmp\zlib-1.2.3> cd ..\ruby-1.9.1-p0\ext\zlib
D:\tmp\ruby-1.9.1-p0\ext\zlib>
extconf.rb を実行して、Makefile を作り直します。先に zlib をビルドしたディレクトリを渡して、インクルードファイル zlib.h やリンクに必要なスタティックライブラリの場所を伝えます。
D:\tmp\ruby-1.9.1-p0\ext\zlib> d:\ruby19\bin\ruby.exe extconf.rb --with-zlib-include=d:\tmp\zlib-1.2.3 --with-zlib-lib=d:\tmp\zlib-1.2.3
checking for deflateReset() in z.lib... no
checking for deflateReset() in libz.lib... no
checking for deflateReset() in zlib1.lib... no
checking for deflateReset() in zlib.lib... yes
checking for zlib.h... yes
checking for kind of operating system... Win32
creating Makefile

D:\tmp\ruby-1.9.1-p0\ext\zlib>
ビルドとインストールを実行します。
D:\tmp\ruby-1.9.1-p0\ext\zlib>nmake
...
D:\tmp\ruby-1.9.1-p0\ext\zlib>nmake install

Microsoft(R) Program Maintenance Utility Version 9.00.30729.01
Copyright (C) Microsoft Corporation.  All rights reserved.

install -c -p -m 0755 zlib.so d:\ruby19\lib\ruby\site_ruby\1.9.1\i386-msvcr90

D:\tmp\ruby-1.9.1-p0\ext\zlib>
お疲れ様でした。

Sep 23, 2008

Yellow Dog Linux on PS3 で GL Excess / Ruby


暇なので Yellow Dog Linux on PS3 を整備して遊んでいました。 以下に GL Excess / Ruby を動かすまでの作業をメモしておきます。
  • root で作業してください。
  • Yellow Dog Linux 6.0 は PS3 にインストール済みであるとします。
まずは /etc/X11/xorg.conf を編集。 GLX 拡張をロードするため、"Module" セクションに次のように追記します:
Section "Module"
       Load  "dbe"
       Load  "extmod"
       Load  "fbdevhw"
       Load  "freetype"
       Load  "type1"
       #Load   "dri"
       Load  "glx"  # ←この行を追記
EndSection
X Window が起動中の場合、編集終了後にを再起動を (Ctrl+Alt+Backspace)。まだ起動していないなら startx を。問題なく起動することを確認してください。
次に freeglut のインストール。パッケージ化されているのですぐに終了します:
[root@localhost ~] yum install freeglut
...
[root@localhost ~] yum install freeglut-devel
続いて Ruby 1.9.0-4 をビルド&インストール。すでに Ruby 1.8.5 がインストールされているので、ここでは Ruby 1.9 の関連プログラムが ruby19 や gem19 といった名前となるよう、--program-suffix で指定しています:
[root@localhost tmp] wget ftp://ftp.ruby-lang.org/pub/ruby/ruby-1.9.0-4.tar.bz2
...
[root@localhost tmp] tar xvjf ruby-1.9.0-4.tar.bz2
...
[root@localhost tmp] cd ruby-1.9.0-4
...
[root@localhost ruby-1.9.0-4] ./configure --program-suffix=19
...
[root@localhost ruby-1.9.0-4] make && make install
ここまでで /usr/local/bin/ruby19 や /usr/local/bin/gem19 などが利用できるようになっています。 あとは ruby-opengl のインストール。ソースパッケージのダウンロード、ビルド、拡張ライブラリのインストールが自動的に実行されます:
[root@localhost ~] gem19 install ruby-opengl
GL Excess / Ruby を動かしてみます。一般ユーザーに戻って作業しても OK です。
[lt140@localhost tmp] wget http://sites.google.com/site/ltsevenscore/archives/glxsruby-20091223.7z
...
[lt140@localhost tmp] 7z x glxsruby-20091223.7z
...
[lt140@localhost tmp] cd glxsruby
...
[lt140@localhost glxsruby] ruby19 glxs.rb -s 9
写真は PS3 上の X Window で動く GL Excess / Ruby。 GPU Acceleration が効かないので遅いです。酔狂もいいところ。 ちなみにディスプレイは BRAVIA 。遊び道具をありがとうございます>ソニーグループ御中



Aug 8, 2008

Ruby/SDL をビルド


素の Ruby/SDL を Visual C++ 2008 Express Edition でビルドするまでのメモです。 TTF や draw_line などを使用しているサンプルは動きませんのでご注意を。

用意するもの

  • Visual C++ 2008 (Express Edition SP1)
  • OpenGL
    • include : c:/Program Files/Microsoft SDKs/Windows/v6.0A/Include
    • lib : c:/Program Files/Microsoft SDKs/Windows/v6.0A/Lib
  • DirectX SDK
SDL のビルドに必要です。March 2009 を利用しました。
D:\tmp>ruby -v
ruby 1.9.1p243 (2009-07-16 revision 24175) [i386-mswin32_90]
d:/ruby19 にインストール & d:/ruby19/bin にパス設定済みとします。

ビルドとインストール

SDL
  • VisualC.zip を展開、SDL.sln を開いて Release ビルド。
  • dsound.h が無いとビルドエラー。⇒ 要 DirectX SDK
できあがった VisualC/SDL/Release/SDL.dll は d:/ruby19/bin にコピーしておきます。
Ruby/SDL
Makefile を書くのも面倒なので、sdl.so を作成するための新規プロジェクトを作成して対応します。
rubysdl-2.1.0 を展開したフォルダに 新規プロジェクトを作成します。ここでは `VCBuild' という名前にします。

DLL を作りたいのでそう選択します。空のプロジェクトに設定して、ソースコードの追加を後で行います。


既存の要素として Ruby/SDL のソースコードをプロジェクトに追加します。


プロジェクトのプロパティを設定する前に下準備をします。VCBuild フォルダの中に `sdl.so.def' という名前のテキストファイルを新規作成します。


内容はこちらの2行だけです:


ここから VCBuild プロジェクトのプロパティ設定を行います。ソリューション構成は Release にした 上で、まずは "C/C++ > 全般 > 追加のインクルード ディレクトリ" に以下のように記入します(各自の環境で適宜読み換えてください):


記入するのは SDL と Ruby のインクルードファイルが配置してある場所です。次に "C/C++ > プリプロセッサ > プリプロセッサの定義" に追記します:


ENABLE_OPENGL と追記しました。次は "リンカ > 全般 > 追加のライブラリ ディレクトリ" にパスを記入します:


SDL.lib, SDLmain.lib そして Ruby のエクスポートライブラリの場所を指定します。 次は "リンカ > 全般 > 出力ファイル" で名前を 'sdl.so' と明記します。


次は "リンカ > 入力 > 追加の依存ファイル" :


最後は "リンカ > コマンドライン > 追加のオプション" に sdl.so.def を使用するよう記入しておきます。


ビルドすると 'VCBuild/Release' に sdl.so が作成されます。


… Makefile 書くのとどっちが面倒だったろう?(^^;
それはそれとして、この DLL を含め、 Ruby/SDL のライブラリファイルを既定の場所へコピーしてインストール完了です。
  • VCBuild/Release/sdl.so
    • -> d:/ruby19/lib/ruby/site_ruby/1.9.1/i386-msvcr90 にコピー
  • lib/sdl.rb, lib/rubysdl_aliases.rb, lib/rubysdl_compatible.ver1.rb
    • -> d:/ruby19/lib/ruby/site_ruby/1.9.1/ にコピー
コマンドラインから実行:
D:\tmp\RubySDL\rubysdl-2.1.0\sample>ruby randrect.rb



今回ビルドしたのは素の SDL のみなので、フォントや高レベルの描画機能(draw_line, etc.)は 動作しませんのでご注意を。

Aug 3, 2008

Ruby 1.9.0-3 : インタプリタ DLL を C から呼ぶ例

(2010-08-29 追記 : 以下の記事は古くなっています。こちらが参考になるかもしれません。 http://sites.google.com/site/ltsevenscore/ruby/tips/interpreter_dll )


  • ruby_options が値を返すようになっている
  • ruby_run という関数がない
など、Rubyの初期化・実行に関する README.EXT の内容は現状に追いついていないようです。
そのようなわけで、Ruby 1.9 を外部から利用する方法を少し調べてみました。
  • アプリケーションに Ruby を組み込みたい
  • rubyw.exe に代わる前処理プログラムを作りたい
といったときに役立つかもしれません。
利用したのは Ruby 1.9.0-3です。 これを VC++ 2008 でビルドした msvcr90-ruby190.dll を C プログラムから利用してみます。
こちらがアプリケーションのソースコード。必要最小限のエントリーポイント を取得した後、インタプリタの初期化と実行に移っています。
UseRubyDLL.c:
#define WIN32_LEAN_AND_MEAN
#include 

#define APP_NAME                "UseRubyDLL.exe"
#define RUBY_DLL_NAME           "d:\\ruby19\\bin\\msvcr90-ruby190.dll"
#define RUBY_SCRIPT_NAME        "script.rb"

HINSTANCE ruby_dll;

/* from include/ruby/ruby.h */
void  (*ruby_init)( void );
void  (*ruby_sysinit)( int*, char*** );
void* (*ruby_options)( int, char** );
/* from include/ruby/intern.h */
void  (*ruby_init_loadpath)( void );
int   (*ruby_run_node)( void* );

void
WinMainCRTStartup()
{
    /* Dummy arguments for ruby_sysinit(). */
    int         sysinit_argc = 0;
    char**      sysinit_argv = NULL;

    /* Manually construct interpreter arguments. */
    int         app_argc = 3;
    char*       app_args[3];
    char**      app_argv = app_args;
    app_args[0] = APP_NAME;
    app_args[1] = RUBY_SCRIPT_NAME;
    app_args[2] = "See ya.";

    ruby_dll = LoadLibrary( RUBY_DLL_NAME );
    if ( ruby_dll )
    {
        ruby_sysinit       = (void (*)( int*, char*** ))GetProcAddress( ruby_dll, "ruby_sysinit" );
        ruby_init          = (void (*)( void ))GetProcAddress( ruby_dll, "ruby_init" );
        ruby_init_loadpath = (void (*)( void ))GetProcAddress( ruby_dll, "ruby_init_loadpath" );
        ruby_options       = (void* (*)( int, char** ))GetProcAddress( ruby_dll, "ruby_options" );
        ruby_run_node      = (int (*)( void* ))GetProcAddress( ruby_dll, "ruby_run_node" );

        ruby_sysinit( &sysinit_argc, &sysinit_argv );
        ruby_init();
        ruby_init_loadpath();

        ruby_run_node( ruby_options( app_argc, app_argv ) );

        /* NOTE: After the execution, +ruby_run_node+ automatically
           calls +ruby_cleanup+. So there's no need to explicitly call
           Ruby's finalizer here(otherwise cause disaster).
         */

        FreeLibrary( ruby_dll );
    }
}
上記の ruby_*() 系関数の利用方法は Ruby のソースコード(winmain.c, eval.c, etc.)から把握したものです。 当然ですがインタプリタ DLL の場所など、ハードコードした部分は適宜変更する必要があります。
アプリケーションから呼び出すスクリプトはこちら。インタプリタ DLL の場所 次第では、標準ライブラリ(ここでは matrix.rb)jの require に失敗しますの でご注意を。
script.rb:
require 'matrix'
File.open( 'result.txt', 'w' ) do |f|
  f.puts Time.now
  f.puts Vector[rand,100*rand,10000*rand]
  f << ARGV
end
ビルドによって生成された UseRubyDLL.exe を以下のように実行します。 script.rb は同じ場所にあるものとします。
$ ./UseRubyDLL
実行すると同じ場所に result.txt ができているはず。以下が結果の一例です。
result.txt(例)
2008-08-03 18:52:16 +0900
Vector[0.434646515113465, 27.44515575993, 9534.51425972162]
["See ya."]
ちなみにビルド用の Makefile はこちら。実行ファイルを小さくするため、あえて Cygwin gcc (gcc -mno-cygwin -mwindows) を利用してみました。
Makefile:
TARGET = UseRubyDLL.exe
SRC = $(TARGET:exe=c)
OBJ = $(TARGET:exe=o)

CC = gcc -mno-cygwin -mwindows
CFLAGS = -Wall -Os
LDFLAGS = -lkernel32 -nostdlib

all: $(TARGET)

$(TARGET): $(OBJ)
 $(CC) -o $(TARGET) $< $(LDFLAGS)
 strip $(TARGET)

clean:
 rm $(OBJ) $(TARGET)

.c.o:
 $(CC) $(CFLAGS) -c $<
手元での結果はこちら:
$ gcc --version
gcc (GCC) 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


kazuwe@kazuwe-PC ~/UseRubyDLL
$ ls -l UseRubyDLL.exe
-rwxr-xr-x 1 kazuwe None 2560 Aug  3 18:58 UseRubyDLL.exe
ちょっと心配になるくらい小さくなるものですね :-)

参考

  • embedding Ruby 1.9.0 inside pthread
  • BDS2006(C++Builder)からRubyを使う (山本隆の開発日誌)

Jul 20, 2008

RMath

今年1月に書いておきながら、 そのまま忘れて半年放置していた 3D CG 向けの数学関数の拡張ライブラリを公開しておこうと思います。
RMath といいます。
RMath は行列(3x3,4x4)、ベクトル(3要素,4要素)、クォータニオンの各クラスを含んだ拡張ライブラリです。 デバッグ用に同じインタフェースを持った Ruby 実装版も同梱しています(RMath.rb)。
ライセンスは zlib/libpng としました。
リファレンスやサンプルが少ないので、それらの充実が当面の課題ですね。
(2009-12-26 URLを新しいものに修正しました)

Jun 8, 2008

wxRuby2


wxWidgets の Ruby バインディング・ wxRuby というものを試そうとしてみました。 利用しているのは One-Click Ruby Installer 1.8.6-26。以下の作業は主に Cygwin Bash シェルで行っています。
インストールは RubyGems で楽勝でした。
$ gem.bat install wxruby
Bulk updating Gem source index for: http://gems.rubyforge.org
Building native extensions.  This could take a while...
Successfully installed wxruby-1.9.7-x86-mswin32-60
1 gem installed
wxRuby 1.9.7 の Windows 版バイナリがインストールされます。
それではさっそくサンプル起動!
$ ruby -rubygems d\:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/samples/minimal/minimal.rb
しかしその瞬間、よくありがちなダイアログボックスが登場しました。
---------------------------
Microsoft Visual C++ Runtime Library
---------------------------
Runtime Error!

Program: d:\ruby\bin\ruby.exe

R6034
An application has made an attempt to load the C runtime library incorrectly.
Please contact the application's support team for more information.

---------------------------
OK   
---------------------------
そしてターミナルにはエラーメッセージが:
d:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/lib/wxruby2.so: 1114: ダイナミック リンク ライブラリ (DLL) 初期化ルーチンの実行に失敗しました。
- d:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/lib/wxruby2.so (LoadError)
from d:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from d:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/lib/wx.rb:12
from d:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `gem_original_require'
from d:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:32:in `require'
from d:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/samples/minimal/minimal.rb:8
要するに wxruby2.so の LoadError だそうです。見に行きましょう。
$ cd d\:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/lib/
$ ls
wx  wx.rb  wxruby2.exp  wxruby2.lib  wxruby2.so  wxruby2.so.manifest
む、wxruby2.so.manifest が。まさか。
$ strings wxruby2.so | grep manifest

$
埋 め 込 ま れ て な い
LoadLibrary される DLL の場合は外部マニフェストが無視されるそうです。最終的なバイナリファイルにはマニフェストの埋め込みが必要となります。
そのようなわけで Visual Studio のコマンドプロンプトから以下の作業をしました:
Setting environment for using Microsoft Visual Studio 2008 x86 tools.

D:\Programs\Microsoft Visual Studio 9.0\VC>cd D:\ruby\lib\ruby\gems\1.8\gems\wxruby-1.9.7-x86-mswin32-60\lib

D:\ruby\lib\ruby\gems\1.8\gems\wxruby-1.9.7-x86-mswin32-60\lib>mt -manifest wxruby2.so.manifest -outputresource:wxruby2.so;2
確かめてみましょう。元の Cygwin ターミナルから:
$ strings wxruby2.so | grep manifest
無事に埋め込まれた模様。ではあらためて!
$ ruby -rubygems d\:/ruby/lib/ruby/gems/1.8/gems/wxruby-1.9.7-x86-mswin32-60/samples/minimal/minimal.rb


うまくいきました。

May 18, 2008

メニューなどのテスト




Qtの各種機能を試してみました。前回のものではGLUTとの違いがわかりませんからね。
OpenGLによる描画とQtによる2Dオブジェクトの描画機能が併用できる、というのは強力だと思いました(画面右下のRubyロゴがそれ)。
中にはGLUTのソースコード(glut_teapot.c)から移植した 'teapot.rb' というものも入ってます。 GLUTから離れてティーポットが拝めなくなってしまったのが寂しかったものですから(^^;
アーカイブの展開後に
$ ruby -rubygems menutest.rb
…として起動してください。
動作に必要なものは以下の通り:

※menutest.rb: 利用したQtオブジェクトのリファレンス

May 15, 2008

glwidget.rb




QtのOpenGLサンプルにあるglwidget.cppを qt4-qtruby向けに書き直してみました。ruby-openglを併用しています。
これ単体で動くようにしてありますので、
$ ruby -rubygems glwidget.rb
…とすれば起動します。
動作に必要なものは以下の通りです:
コード:
require 'qt'
require 'opengl'

class GLWidget < Qt::GLWidget
  signals 'xRotationChanged(int)'
  signals 'yRotationChanged(int)'
  signals 'zRotationChanged(int)'

  slots 'setXRotation(int)'
  slots 'setYRotation(int)'
  slots 'setZRotation(int)'

  def initialize
    super
    @object = 0
    @xRot = 0
    @yRot = 0
    @zRot = 0
    @lastPos = Qt::Point.new

    @trolltechGreen = Qt::Color::fromCmykF( 0.40, 0.0, 1.0, 0.0 )
    @trolltechPurple = Qt::Color::fromCmykF( 0.39, 0.39, 0.0, 0.0 )
  end

  def destroy
    makeCurrent()
    glDeleteLists( @object, 1 )
  end

  def minimumSizeHint
    return Qt::Size.new( 50, 50 )
  end

  def sizeHint
    return Qt::Size.new( 400, 400 )
  end

  def setXRotation( angle )
    normalizeAngle( angle )
    if ( angle != @xRot )
      @xRot = angle
      emit xRotationChanged( angle )
      updateGL()
    end
  end

  def setYRotation( angle )
    normalizeAngle( angle )
    if ( angle != @yRot )
      @yRot = angle
      emit yRotationChanged( angle )
      updateGL()
    end
  end

  def setZRotation( angle )
    normalizeAngle( angle )
    if ( angle != @zRot )
      @zRot = angle
      emit zRotationChanged( angle )
      updateGL()
    end
  end

  def initializeGL
    qglClearColor( @trolltechPurple.dark() )
    @object = makeObject()
    glShadeModel( GL_FLAT )
    glEnable( GL_DEPTH_TEST )
    glEnable( GL_CULL_FACE )
  end

  def paintGL
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
    glLoadIdentity()
    glTranslated( 0.0, 0.0, -10.0)
    glRotated( @xRot / 16.0, 1.0, 0.0, 0.0 )
    glRotated( @yRot / 16.0, 0.0, 1.0, 0.0 )
    glRotated( @zRot / 16.0, 0.0, 0.0, 1.0 )
    glCallList( @object )
  end

  def resizeGL( width, height )
    # [NOTE] +qMin+ in the original code is a C++ Template Function.
    # Ref.: $(QTDIR)/src/corelib/global/qglobal.h
    #   template 
    #   inline const T &qMin(const T &a, const T &b) { if (a < b) return a; return b; }
    side = [width, height].min
    glViewport( (width - side) / 2, (height - side) / 2, side, side )

    glMatrixMode( GL_PROJECTION )
    glLoadIdentity()
    glOrtho( -0.5, +0.5, +0.5, -0.5, 4.0, 15.0 )
    glMatrixMode( GL_MODELVIEW )
  end

  def mousePressEvent( event ) # event : Qt::MouseEvent
    @lastPos = event.pos
  end

  def mouseMoveEvent( event ) # event : Qt::MouseEvent
    dx = event.x - @lastPos.x
    dy = event.y - @lastPos.y

    if ( event.buttons() & Qt::LeftButton.to_i )
      setXRotation( @xRot + 8 * dy )
      setYRotation( @yRot + 8 * dx )
    elsif ( event.buttons() & Qt::RightButton.to_i )
      setXRotation( @xRot + 8 * dy )
      setZRotation( @zRot + 8 * dx )
    end
    @lastPos = event.pos
  end

  def makeObject
    list = glGenLists( 1 )
    glNewList( list, GL_COMPILE )

    glBegin( GL_QUADS )

    x1 = +0.06
    y1 = -0.14
    x2 = +0.14
    y2 = -0.06
    x3 = +0.08
    y3 = +0.00
    x4 = +0.30
    y4 = +0.22

    quad( x1, y1, x2, y2, y2, x2, y1, x1 )
    quad( x3, y3, x4, y4, y4, x4, y3, x3 )

    extrude( x1, y1, x2, y2 )
    extrude( x2, y2, y2, x2 )
    extrude( y2, x2, y1, x1 )
    extrude( y1, x1, x1, y1 )
    extrude( x3, y3, x4, y4 )
    extrude( x4, y4, y4, x4 )
    extrude( y4, x4, y3, x3 )

    num_sectors = 200

    for i in 0...num_sectors do
      angle1 = (i * 2 * Math::PI) / num_sectors
      x5 = 0.30 * Math::sin( angle1 )
      y5 = 0.30 * Math::cos( angle1 )
      x6 = 0.20 * Math::sin( angle1 )
      y6 = 0.20 * Math::cos( angle1 )

      angle2 = ((i + 1) * 2 * Math::PI) / num_sectors
      x7 = 0.20 * Math::sin( angle2 )
      y7 = 0.20 * Math::cos( angle2 )
      x8 = 0.30 * Math::sin( angle2 )
      y8 = 0.30 * Math::cos( angle2 )

      quad( x5, y5, x6, y6, x7, y7, x8, y8 )

      extrude( x6, y6, x7, y7 )
      extrude( x8, y8, x5, y5 )
    end

    glEnd()

    glEndList()
    return list

  end

  def quad( x1,  y1,  x2,  y2,  x3,  y3,  x4,  y4 )
    qglColor( @trolltechGreen )

    glVertex3d( x1, y1, -0.05 )
    glVertex3d( x2, y2, -0.05 )
    glVertex3d( x3, y3, -0.05 )
    glVertex3d( x4, y4, -0.05 )

    glVertex3d( x4, y4, +0.05 )
    glVertex3d( x3, y3, +0.05 )
    glVertex3d( x2, y2, +0.05 )
    glVertex3d( x1, y1, +0.05 )

  end

  def extrude( x1,  y1,  x2,  y2 )
    qglColor( @trolltechGreen.dark(250 + (100 * x1).to_i) )

    glVertex3d( x1, y1, +0.05 )
    glVertex3d( x2, y2, +0.05 )
    glVertex3d( x2, y2, -0.05 )
    glVertex3d( x1, y1, -0.05 )
  end

  def normalizeAngle( angle )
    while ( angle < 0 ) do
      angle += 360 * 16
    end
    while ( angle > 360 * 16 ) do
      angle -= 360 * 16
    end
  end

end


#
# Application starts here.
#
begin
  a = Qt::Application.new(ARGV)

  w = GLWidget.new
  w.show

  a.exec
ensure
  w.destroy
end

Mar 8, 2008

GL Excess/Ruby : Scene 11 移植完了


Scene 11 はエンディングです。スタッフロールが流れます。

これで GL Excess 全12シーンの Ruby 移植ができたことになります。なんとかなるもんですね。
今後は
  • 全シーンをまとめたものを再パッケージ化
    • シーン個別での配布は廃止する
  • 特に遅い Scene 2, Scene 8 の一部を拡張ライブラリ化(「チート版」が適切かな?)
を予定しています。
GL Excess / Ruby のページも更新。 Scene 11 をダウンロードできるようにしておきました:
※ Scene 2 と 8 は動作が非常に遅くなってしまっています。 そこで glxsruby にもオリジナルと同様、更新のタイプステップを変更する機能が実装されています。 アプリケーション起動後に以下の操作を行ってください:
  • 'a' を押すと @step += 1 (更新速度アップ)
  • 'z' を押すと @step -= 1 (更新速度ダウン)
画面表示が遅い場合には、'a' をしばらく押しっぱなしにしておくと吉です。

Mar 2, 2008

GL Excess / Ruby : Scene 10 移植完了


Scene 10 です。これといって問題になるような部分はありませんでした。

このシーンで印象的なのはやはりレーザー効果ですが、本質的には GL_TRIANGLE_FAN だけでシンプルに実装されています。このようなことが勉強 できるのも、ソースコードが公開されているおかげですね。
GL Excess / Ruby のページも更新。 Scene 10 をダウンロードできるようにしておきました:
未実装のシーンは 11。とうとう残り 1 個になりました。
※ Scene 2 と 8 は動作が非常に遅くなってしまっています。 そこで glxsruby にもオリジナルと同様、更新のタイプステップを変更する機能が実装されています。 アプリケーション起動後に以下の操作を行ってください:
  • 'a' を押すと @step += 1 (更新速度アップ)
  • 'z' を押すと @step -= 1 (更新速度ダウン)
画面表示が遅い場合には、'a' をしばらく押しっぱなしにしておくと吉です。

Mar 1, 2008

RDフォーマット


Re: RDoc,RDフォーマットの公式文書はどこにあるのでしょうか

「仕様書」と呼ぶべきかどうかはともかくとして、Ruby自身の配布ファイル
の中に"lib/rdocs/README"というのが含まれています。公式のドキュメントの中で
は、これが一番良く書かれたものだと思います。

Module: RDoc

Rdoc is an application that produces documentation for one or more Ruby source files.

GL Excess / Ruby : Scene 8 移植


Scene 8 ですが…遅いっ。

原因は Scene 2 と 同様で、水面の表現に利用している 64x64 個のグリッドの更新が重荷になって います。描画の部分に頂点配列(glVertexPointer/glDrawArrays)を利用するよ うに書き直してみたりもしたのですが、有意な差が見られるほどの改善には至 りませんでした。
移植の最中に思い出しましたが、Ruby では !0 == false なのでした。
$ irb.bat
irb(main):001:0> some_value = 0
=> 0
irb(main):002:0> !some_value
=> false
irb(main):003:0> some_value==0
=> true
irb(main):004:0>
C/C++ によくあるイディオムの移植には注意が必要ですね。
GL Excess / Ruby のページも更新。 Scene 8 をダウンロードできるようにしておきました:
未実装のシーンは 10 と 11。残りは 2 個となりました。
※ Scene 2 と 8 は動作が非常に遅くなってしまっています。 そこで glxsruby にもオリジナルと同様、更新のタイプステップを変更する機能が実装されています。 アプリケーション起動後に以下の操作を行ってください:
  • 'a' を押すと @step += 1 (更新速度アップ)
  • 'z' を押すと @step -= 1 (更新速度ダウン)
画面表示が遅い場合には、'a' をしばらく押しっぱなしにしておくと吉です。。

Feb 17, 2008

GL Excess/Ruby : Scene 7 を移植


レンズフレアの効果がかっこいい Scene 7 です。

Scene 7 では 10x10x10 の多次元配列が登場しますが、次のように定義してみました:
@f_angle = Array.new(10) { Array.new(10) { Array.new(10) { 0.0 } } }
...
@f_angle[i][j][k] = (100*a + 10*b + c).to_f
他にも Hash と Array を組み合わせることで、もっときれいに記述することもできます:
ary = Hash.new
...
ary[[i,j,k]] = ... # ここで [i,j,k] が Array。
こちらの方が簡潔ですが、配列を参照するたびに Array のインスタンスが生成されてしまいます。今回のように速度が要求されるケースでは利用しない方が無難であると思います。
GL Excess / Ruby のページも更新。 Scene 7 をダウンロードできるようにしておきました:
未実装のシーンは 8, 10, 11 の 3 個となりました。

Feb 16, 2008

ruby-breakpoint, etc.


[ruby-list:44570] Re: Q: 動的デバッグ方法

> (1) 動的にデバッグモードに移るようなライブラリ関数はあります
>    でしょうか?

ruby-breakpointはどうでしょうか?
breakpointと書いた時点でirbに突入します。

RubyForge: ruby-breakpoint: Project Info

ruby-breakpoint lets you inspect and modify state, diagnose bugs,
patch applications and more all via IRB by simply doing a method
call at the place you want to investigate. It is no longer being
maintained. Please consider using ruby-debug instead.

RubyとCursesを使ったコンソールテキストエディタ

連載第二回目です。今回も引き続きRubyとCursesを使ったコンソールプログラムを作っていきます。

GL Excess / Ruby : Scene 6 の移植完了


結局、ロケットの形状データはオリジナル版と同様に配列ベタ持ちで使うことにしました。 パフォーマンスに深刻な影響が出ることもありませんでしたので。
あと実行終了後のクリーンアップ部分に glDeleteLists( @shiplist, 1 ) と追記。これってオリジナル版には見当らないのですが、大丈夫なんでしょうかね。

GL Excess / Ruby のページも更新。 Scene 6 をダウンロードできるようにしておきました:
未実装のシーンは 7, 8, 10, 11 の 4 個。

Feb 15, 2008

GL Excess/Ruby : Scene 6 の移植中


Scene 6 です。GL Excess で唯一、何らかのツールでモデリングされたジオメトリ(ロケットです)が登場します。 とりあえず、ロケット以外のもの全部を移植してしまいました。

ロケットの準備ができるまでの間、かわりに Teapot に飛んでもらうことにしました(^^;
オリジナル版ではモデルデータ(頂点情報とインデックス)を C の配列でベタ持ちしています。 Ruby ではこれをどのような形式で持つのがいいか、考え中です。
(案)
  • Marshal.dump で前処理しておいたバイト列を Marshal.load で復活
  • Array#pack/String#unpack

Feb 11, 2008

GL Excess / Ruby : Scene 5 を移植


バンプマッピングが印象的な Scene 5 です。最近主流のピクセル単位の処理で はないことから、負荷はそれほどでもありません。バンプマップの処理よりも、 燈台の炎を表現するパーティクルが負担になっている印象を受けます。

GL Excess / Ruby のページも更新。 Scene 5 をダウンロードできるようにしておきました:
未実装のシーンは 6, 7, 8, 10, 11 の 5 個です。

Feb 6, 2008

GL Excess / Ruby : Scene 1 を移植


GL Excess のオープニングである Scene 1 を移植しました。全然問題なしです。

GL Excess / Ruby のページも更新。 Scene 1 をダウンロードできるようにしておきました:
残りは 6 シーンになりました。未実装のシーンは 5, 6, 7, 8, 10, 11。大物ばかりですね。

Feb 4, 2008

GL Excess / Ruby : Scene 12 をサクッと移植、と思いきや


Scene 12 は GL Excess 全12シーンで一番短い行数のプログラムです(scene12.cppが281行)。

移植なんて一瞬だぜ、と思っていたら。
texture.rb で raw テクスチャの幅が正しく取れないケースがあることがわかりました。 Ruby 1.8 と 1.9 との間で、 String#to_i の挙動に違いがあることが原因のようです。
両方のバージョンで動かしたかったがために、次のようにして対処してみました:
texture.rb
major, minor, micro = RUBY_VERSION.scan( /\d+/ )

if ( major == "1" && minor == "8" )
  # for Ruby 1.8.
  width  = pow2( w[0].to_i - "0"[0].to_i )
  height = pow2( h[0].to_i - "0"[0].to_i )
else
  # for Ruby 1.9.
  width  = pow2( w[0].unpack("U")[0].to_i - "0"[0].unpack("U")[0].to_i )
  height = pow2( h[0].unpack("U")[0].to_i - "0"[0].unpack("U")[0].to_i )
end
普通であればどのようにして対処するべきところなのでしょうか?
GL Excess / Ruby のページも更新。 Scene 12 をダウンロードできるようにしておきました:

Feb 3, 2008

GL Excess / Ruby : Scene 4 を移植


パーティクルが多いように見えるので心配でしたが、特に問題なく移植できました。

GL Excess / Ruby のページも更新。 Scene 4 をダウンロードできるようにしておきました: