第6章 作図法の基礎
著者:梅谷 武
語句:点, 直線, 多角形, 頂点配列, 多面体, メッシュ, 文字列, 幾何学的変換, 2次曲面, 透明化, 群論的作図法
ToposNoteにおける作図の基本技法について簡単な例を使って説明する。
作成:2009-12-28
更新:2011-03-08
 描画色と点の大きさを指定して3点を描画します。
(0) 準備
package.path = "std/?.lua"   標準ライブラリパス指定
require( "OpenGL" )          OpenGL定数ファイル
 
(1) 状態変更
glDisable( GL_LIGHTING )     シェーディングOFF
 
(2) 図形描画
glPointSize( 5.0 )           点の大きさ指定
glBegin( GL_POINTS )         図形の種類指定
glColor3( 1.0, 1.0, 1.0 )  描画色指定
glVertex3( 0.1, 0.1, 0.0 ) 頂点定義
glColor3( 1.0, 0.0, 0.0 )
glVertex3( 0.2, 0.2, 0.0 )
glColor3( 0.0, 0.0, 1.0 )
glVertex3( 0.3, 0.3, 0.0 )
glEnd()
 
(4) 状態復帰
glEnable( GL_LIGHTING )      シェーディングON
 
(5) トポスオブジェクト生成
tnNewObject()
 外部参照パスはプログラムがインストールされたディレクトリに対する相対パスになっています。絶対パスを指定することもできます。パス指定においては日本語を使わないという原則を守ってください。
 ToposNoteにおいては既定状態でシェーディングをONにしていますので、描画時にはシェーディングをOFFにして描画しています。
 GL_LINES, GL_LINE_STRIP, GL_LINE_LOOPの3種類の方法で直線を描画します。
package.path = "std/?.lua"
require( "OpenGL" )
 
glDisable( GL_LIGHTING )
 
glLineWidth( 2.0 )           線幅指定
glColor3( 1.0, 0.0, 0.0 )    描画色指定
glBegin( GL_LINES )
glVertex3( 0.3, 0.3, 0.0 )
glVertex3( 0.7, 0.3, 0.0 )
glVertex3( 0.7, 0.7, 0.0 )
glVertex3( 0.3, 0.7, 0.0 )
glEnd()
 
glLineWidth( 3.0 )
glColor3( 0.0, 1.0, 0.0 )
glEnable( GL_LINE_STIPPLE )  破線ON
glLineStipple( 1, 0xCCCC )   破線形状指定
glBegin( GL_LINE_STRIP )
glVertex3( 0.2, 0.2, 0.0 )
glVertex3( 0.8, 0.2, 0.0 )
glVertex3( 0.8, 0.8, 0.0 )
glVertex3( 0.2, 0.8, 0.0 )
glEnd()
glDisable( GL_LINE_STIPPLE ) 破線OFF
 
glLineWidth( 4.0 )
glColor3( 0.0, 0.0, 1.0 )
glBegin( GL_LINE_LOOP )
glVertex3( 0.1, 0.1, 0.0 )
glVertex3( 0.9, 0.1, 0.0 )
glVertex3( 0.9, 0.9, 0.0 )
glVertex3( 0.1, 0.9, 0.0 )
glEnd()
 
glLineWidth( 1.0 )           線幅復帰
glEnable( GL_LIGHTING )
 
tnNewObject()
 GL_QUADSにより四角形の辺及び面を描画します。
package.path = "std/?.lua"
require( "OpenGL" )
 
glDisable( GL_LIGHTING )
 
glColor3( 1.0, 1.0, 0.0 )
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ) 辺の描画
glBegin( GL_QUADS )
glVertex3( 0.1, 0.1, 0.0 )
glVertex3( 0.9, 0.1, 0.0 )
glVertex3( 0.9, 0.9, 0.0 )
glVertex3( 0.1, 0.9, 0.0 )
glEnd()
 
glColor3( 0.0, 1.0, 1.0 )
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ) 面の描画
glBegin( GL_QUADS )
glVertex3( 0.2, 0.2, 0.0 )
glVertex3( 0.8, 0.2, 0.0 )
glVertex3( 0.8, 0.8, 0.0 )
glVertex3( 0.2, 0.8, 0.0 )
glEnd()
 
glEnable( GL_LIGHTING )
 
tnNewObject()
 三角形の各頂点に異なる3色を指定して面を描画します。この場合、頂点以外の点においては各頂点からの距離に応じて色が補間されます。
package.path = "std/?.lua"
require( "OpenGL" )
 
glDisable( GL_LIGHTING )
 
glBegin( GL_TRIANGLES )
glColor3( 1.0, 0.0, 0.0 )
glVertex3( 0.1, 0.1, 0.0 )
glColor3( 0.0, 1.0, 0.0 )
glVertex3( 1.0, 0.1, 0.0 )
glColor3( 0.0, 0.0, 1.0 )
glVertex3( 0.1, 1.0, 0.0 )
glEnd()
 
glEnable( GL_LIGHTING )
 
tnNewObject()
 頂点数が多くなる場合は、頂点配列を使って図形を定義します。頂点配列を使うことによりメモリ領域が節約され、処理効率が上がります。
 ここでは前節の2例を頂点配列を使って書き直してみます。
(0) 準備
package.path = "std/?.lua"
require( "OpenGL" )
 
(1) 状態変更
glDisable( GL_LIGHTING )
glEnableClientState( GL_VERTEX_ARRAY ) 頂点配列ON
 
(2) 頂点定義
glArray( GL_VERTEX_ARRAY, 8, { 頂点配列設定
0.1, 0.1, 0.0,
0.9, 0.1, 0.0,
0.9, 0.9, 0.0,
0.1, 0.9, 0.0,
0.2, 0.2, 0.0,
0.8, 0.2, 0.0,
0.8, 0.8, 0.0,
0.2, 0.8, 0.0
} )
 
(3) 図形描画
glColor3( 1.0, 1.0, 0.0 )
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE )
glDrawElements( GL_QUADS, 4, { 0, 1, 2, 3 } ) 頂点番号による描画
 
glColor3( 0.0, 1.0, 1.0 )
glPolygonMode( GL_FRONT_AND_BACK, GL_FILL )
glDrawElements( GL_QUADS, 4, { 4, 5, 6, 7 } ) 頂点番号による描画
 
(4) 状態復帰
glDisableClientState( GL_VERTEX_ARRAY ) 頂点配列OFF
glEnable( GL_LIGHTING )
 
(5) トポスオブジェクト生成
tnNewObject()
 ToposNoteにおいては既定状態で頂点配列を無効にしていますので、描画時に頂点配列を有効にします。
 頂点番号はC言語の配列と同様に添え字が0から始まります。Luaの配列は添え字が1から始まりますので、両者を混同しないように注意してください。
 色も配列で定義することができます。
package.path = "std/?.lua"
require( "OpenGL" )
 
glDisable( GL_LIGHTING )
glEnableClientState( GL_VERTEX_ARRAY )
glEnableClientState( GL_COLOR_ARRAY ) 色配列ON
 
glArray( GL_VERTEX_ARRAY, 3, {
0.1, 0.1, 0.0,
1.0, 0.1, 0.0,
0.1, 1.0, 0.0,
} )
glArray( GL_COLOR_ARRAY, 3, { 色配列設定
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
} )
 
glDrawElements( GL_TRIANGLES, 3, { 0, 1, 2 } )
 
glDisableClientState( GL_COLOR_ARRAY ) 色配列OFF
glDisableClientState( GL_VERTEX_ARRAY )
glEnable( GL_LIGHTING )
 
tnNewObject()
 材質指定によるシェーディングが施された立方体を描画します。
package.path = "std/?.lua"
require( "OpenGL" )
 
glEnableClientState( GL_VERTEX_ARRAY )
glEnableClientState( GL_NORMAL_ARRAY ) 法線ベクトル配列ON
 
a = math.sqrt( 3.0 ) / 3.0
glArray( GL_VERTEX_ARRAY, 8, {
-a,  -a,  -a,
-a,   a,  -a,
a,   a,  -a,
a,  -a,  -a,
-a,  -a,   a,
-a,   a,   a,
a,   a,   a,
a,  -a,   a
} )
glArray( GL_NORMAL_ARRAY, 8, {
-a,  -a,  -a,
-a,   a,  -a,
a,   a,  -a,
a,  -a,  -a,
-a,  -a,   a,
-a,   a,   a,
a,   a,   a,
a,  -a,   a
} )
glDisable( GL_COLOR_MATERIAL ) 色指定無効
glMaterialSet( emerald )       材質指定
glDrawElements( GL_QUADS, 24, {
0, 1, 2, 3,
1, 5, 6, 2,
5, 4, 7, 6,
4, 0, 3, 7,
0, 4, 5, 1,
2, 6, 7, 3
} )
 
glDisableClientState( GL_NORMAL_ARRAY ) 法線ベクトル配列OFF
glDisableClientState( GL_VERTEX_ARRAY )
 
tnNewObject()
 標準ライブラリ"std/OpenGL.lua"内にいくつか材質が定義されています。このプログラムでは、その中の"emerald"という材質を利用しています。
 シェーディングする場合は、各頂点における正規化された法線ベクトルを指定しなければなりません。
 材質指定によるシェーディングが施されたメッシュを描画します。
package.path = "std/?.lua"
require( "OpenGL" )
 
glDisable( GL_COLOR_MATERIAL )
glMaterialSet( emerald )
glMesh( 0.0, 0.0, 1.0, 1.0, 4, 3, { メッシュ描画
0.1, 0.2, 0.3, 0.2,
0.2, 0.3, 0.2, 0.1,
0.3, 0.2, 0.1, 0.0
} )
 
tnNewObject()
 テクスチャ付きメッシュを描画します。
package.path = "std/?.lua"
require( "OpenGL" )
 
glEnable( GL_COLOR_MATERIAL )
glColor3( 1.0, 1.0, 1.0 )
glTexMesh( "sample1/DSC_0036.jpg", 0.0, 0.0, 1.0, 1.0, 4, 3, {
0.1, 0.2, 0.3, 0.2,
0.2, 0.3, 0.2, 0.1,
0.3, 0.2, 0.1, 0.0
} )
 
tnNewObject()
 ToposNoteはOpenGL内部に英数字のビットマップフォントをもっており、glPrint命令で空間内に英数字文字列を表示することができます。
package.path = "std/?.lua"
require( "OpenGL" )
 
glEnableClientState( GL_VERTEX_ARRAY )
glEnableClientState( GL_NORMAL_ARRAY )
 
a = math.sqrt( 3.0 ) / 3.0
glArray( GL_VERTEX_ARRAY, 8, {
-a,  -a,  -a,
-a,   a,  -a,
a,   a,  -a,
a,  -a,  -a,
-a,  -a,   a,
-a,   a,   a,
a,   a,   a,
a,  -a,   a
} )
glArray( GL_NORMAL_ARRAY, 8, {
-a,  -a,  -a,
-a,   a,  -a,
a,   a,  -a,
a,  -a,  -a,
-a,  -a,   a,
-a,   a,   a,
a,   a,   a,
a,  -a,   a
} )
glDisable( GL_COLOR_MATERIAL )
glMaterialSet( emerald )
glDrawElements( GL_QUADS, 24, {
0, 1, 2, 3,
1, 5, 6, 2,
5, 4, 7, 6,
4, 0, 3, 7,
0, 4, 5, 1,
2, 6, 7, 3
} )
 
glDisable( GL_LIGHTING )
glColor3( 1.0, 1.0, 1.0 )
glPrint( -a-0.1, -a-0.1, -a-0.1, "0" )
glPrint( -a-0.1,  a+0.1, -a-0.1, "1" )
glPrint(  a+0.1,  a+0.1, -a-0.1, "2" )
glPrint(  a+0.1, -a-0.1, -a-0.1, "3" )
glPrint( -a-0.1, -a-0.1,  a+0.1, "4" )
glPrint( -a-0.1,  a+0.1,  a+0.1, "5" )
glPrint(  a+0.1,  a+0.1,  a+0.1, "6" )
glPrint(  a+0.1, -a-0.1,  a+0.1, "7" )
glPrint(    0.0, -a-0.1, -a-0.1, "cube" )
glEnable( GL_LIGHTING )
 
glDisableClientState( GL_NORMAL_ARRAY )
glDisableClientState( GL_VERTEX_ARRAY )
 
tnNewObject()
 同じ図形を繰り返し描画する場合は変換行列を使います。
 変換行列はスタック構造をもち、何もしないで図形を定義するとその先頭行列が左から図形に乗じられます。この先頭行列の内容はToposNote側で設定されており、作図終了後は元の状態に戻さなければなりません。
 一時的に変換行列を変えるときには、処理開始前にglPushMatrixで先頭行列を退避し、処理終了後にglPopMatrixで復帰させます。この操作は階層的に行なうことができ、図形に階層構造をもたせることができます。
 次の例ではHSVで色指定した色相環を描いています。
package.path = "std/?.lua"
require( "OpenGL" )
 
function square()
glDrawElements( GL_QUADS, 4, { 0, 1, 2, 3 } )
end
 
glDisable( GL_LIGHTING )
glEnableClientState( GL_VERTEX_ARRAY )
 
glArray( GL_VERTEX_ARRAY, 4, {
-0.5,-0.5, 0.0,
0.5,-0.5, 0.0,
0.5, 0.5, 0.0,
-0.5, 0.5, 0.0
} )
 
for arg = 0.0, 345.0, 15.0 do
glPushMatrix()  先頭行列退避
glRotateZ( -arg )
glTranslate( 0.0, 5.0, 0.0 )
glColorHSV( arg, 1.0, 1.0 )
square()
glPopMatrix()   先頭行列復帰
end
 
glDisableClientState( GL_VERTEX_ARRAY )
glEnable( GL_LIGHTING )
 
tnNewObject()
 GLUライブラリを使った2次曲面生成関数が4種類用意されています。
package.path = "std/?.lua"
require( "OpenGL" )
 
glDisable( GL_COLOR_MATERIAL )
 
glMaterialSet( emerald )
glPushMatrix()
gluSphere( 0.5, 32, 32 ) 
glPopMatrix()
 
glMaterialSet( bronze )
glPushMatrix()
glTranslate( 2.0, 0.0, -0.5 )
glRotateX( -90.0 )
gluCylinder( 0.6, 0.3, 1.0, 32, 32 ) 円柱
glPopMatrix()
 
glMaterialSet( turquoise )
glPushMatrix()
glTranslate( 4.0, 0.0, 0.0 )
glRotateX( -90.0 )
gluDisk( 0.3, 0.6, 32, 32 ) 円盤
glPopMatrix()
 
glMaterialSet( brass )
glPushMatrix()
glTranslate( 6.0, 0.0, 0.0 )
glRotateX( -90.0 )
gluPartialDisk( 0.3, 0.6, 32, 32, 0.0, 270.0 ) 部分円盤
glPopMatrix()
 
tnNewObject()
 OpenGLのブレンディング機能が実装されています。
package.path = "std/?.lua"
require("OpenGL")
 
function square()
glBegin( GL_QUADS )
glVertex3( -1.0,-1.0, 0.0 )
glVertex3(  1.0,-1.0, 0.0 )
glVertex3(  1.0, 1.0, 0.0 )
glVertex3( -1.0, 1.0, 0.0 )
glEnd()
end
 
glDisable( GL_LIGHTING )
glEnable( GL_BLEND ) ブレンドON
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ブレンド法指定
 
glPushMatrix()
glTranslate( 0.0, 0.0, -1.0 )
glColor4( 0.8, 0.0, 0.0, 1.0 ) 色透過率指定
square()
glPopMatrix()
 
glPushMatrix()
glTranslate( 0.0, 0.0, 1.0 )
glColor4( 0.8, 0.8, 1.0, 0.5 ) 色透過率指定
square()
glPopMatrix()
 
glDisable( GL_BLEND ) ブレンドOFF
glEnable( GL_LIGHTING )
 
tnNewObject()
 群論的作図法に関しては『正多面体論』を参照してください。
Published by SANENSYA Co.,Ltd.