PyOpenGL 8

メニュー

GLUT によってメニューを作成するには以下の関数を使用します。

glutCreateMenu(func)
メニューを作成し、メニューが選ばれたときに関数funcを実行します。
サブメニューを作成するときは、返り値を使用します。
glutAddMenuEntry(label, num)
メニュー項目を作成します。
labelには項目に表示する文字列、numにはこの項目を表すintの番号を指定します。
glutAddSubMenu(lable, submenu)
サブメニュー項目を作成します。
labelには項目に表示する文字列、submenuにはサブメニューを作成したglutCreateMenu()の返り値を指定します。
glutAttachMenu(mouse)
メニューをマウスのボタンにアタッチします。
mouseは、以下のいずれかです。
GLUT_RIGHT_BUTTON
マウス右ボタン
GLUT_MIDDLE_BUTTON
マウス中ボタン
GLUT_LEFT_BUTTON
マウス左ボタン

メニューの使用例

#!env python

import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *


vertex = [
    [ 0.0, 0.0, 0.0 ],
    [ 1.0, 0.0, 0.0 ],
    [ 1.0, 1.0, 0.0 ],
    [ 0.0, 1.0, 0.0 ],
    [ 0.0, 0.0, 1.0 ],
    [ 1.0, 0.0, 1.0 ],
    [ 1.0, 1.0, 1.0 ],
    [ 0.0, 1.0, 1.0 ]]

edge = [
    [ 0, 1 ],
    [ 1, 2 ],
    [ 2, 3 ],
    [ 3, 0 ],
    [ 4, 5 ],
    [ 5, 6 ],
    [ 6, 7 ],
    [ 7, 4 ],
    [ 0, 4 ],
    [ 1, 5 ],
    [ 2, 6 ],
    [ 3, 7 ]]


direction = 0
angle = [0.0, 0.0, 0.0]
mousex = 0
rstart = False


def resize(w, h):
    glViewport(0, 0, w, h)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(30.0, w/h, 1.0, 100.0)
    glMatrixMode(GL_MODELVIEW)


def draw():
    global angle

    glClearColor(0.0, 0.0, 1.0, 0.0)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    glLoadIdentity()
    gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
    glRotated(angle[0], 1.0, 0.0, 0.0);
    glRotated(angle[1], 0.0, 1.0, 0.0);
    glRotated(angle[2], 0.0, 0.0, 1.0);


    glBegin(GL_LINES)
    for i in range(0, 12):
        glVertex(vertex[edge[i][0]])
        glVertex(vertex[edge[i][1]])
    glEnd()

    glFlush()
    glutSwapBuffers()


def mouse(button, state, x, y):
    global mousex
    global rstart

    if button != GLUT_LEFT_BUTTON:
        return
    if state == GLUT_DOWN:
        mousex = x
        rstart = True
    elif state == GLUT_UP:
        rstart = False


def motion(x, y):
    global mousex
    global angle
    global rstart

    if rstart == False:
        return
    angle[direction] += mousex - x
    mousex = x
    glutPostRedisplay()


def menu(item):
    global direction

    if item == 3:
        sys.exit()
    else:
        direction = item
    return 0


glutInit(sys.argv)
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
glutInitWindowSize(320, 320)
glutCreateWindow("PyOpenGL 19")
glutDisplayFunc(draw)
glutReshapeFunc(resize)
glutMouseFunc(mouse)
glutMotionFunc(motion)

glutCreateMenu(menu); 
glutAddMenuEntry('rotateX', 0) 
glutAddMenuEntry('rotateY', 1) 
glutAddMenuEntry('rotateZ', 2) 
glutAddMenuEntry('quit', 3)
glutAttachMenu(GLUT_RIGHT_BUTTON)

glutMainLoop()

スクリプト解説

direction = 0
どの方向を回転させるかを決める数値を代入しておく変数です。
angle = [0.0, 0.0, 0.0]
回転角度を表すリストです。
angle[0]がrotateX、 angle[1]がrotateY、 angle[2]がrotateZを表します。
mousex = 0
マウスのX方向の位置を保存しておく変数です。
rstart = False
回転を始まったかどうかを保存しておく変数です。
マウス左ボタンがクリックされるとTrueになり、離されるとFalseになります。
direction = item
itemの数値が、そのまま回転方向を表す数値になるのでdirection変数にメニュー番号を代入しておきます。
glutCreateMenu(menu);
メニューを作成し、メニューが選ばれたときに実行される関数をmenuに設定します。
glutAddMenuEntry('rotateX', 0)
一つ目のメニュー項目に'rotateX'というラベルを付けて、0を選ばれたときにmenu()の引数に渡す番号にします。
glutAddMenuEntry('rotateY', 1)
二つ目のメニュー項目に'rotateY'というラベルを付けて、1を選ばれたときにmenu()の引数に渡す番号にします。
glutAddMenuEntry('rotateZ', 2)
三つ目のメニュー項目に'rotateZ'というラベルを付けて、2を選ばれたときにmenu()の引数に渡す番号にします。
glutAddMenuEntry('quit', 3)
四つ目のメニュー項目に'quit'というラベルを付けて、3を選ばれたときにmenu()の引数に渡す番号にします。
glutAttachMenu(GLUT_RIGHT_BUTTON)
作成したメニューをマウス左ボタンに割り当てます。

サブメニュー

サブメニューを作成するには、glutAddSubMenu() を使用します。
上記のスクリプトを、サブメニュー化するにはmenu()とメニュー作成部分を以下のように変更します。

def menu1(item):
    global direction

    direction = item


def menu2(item):
    if item == 0:
        sys.exit()


submenu = glutCreateMenu(menu1); 
glutAddMenuEntry('rotateX', 0) 
glutAddMenuEntry('rotateY', 1) 
glutAddMenuEntry('rotateZ', 2) 
glutCreateMenu(menu2); 
glutAddSubMenu('rotate', submenu)
glutAddMenuEntry('quit', 0)
glutAttachMenu(GLUT_RIGHT_BUTTON)

練習問題

  1. 前回のスクリプトを参考にして、以下のようなメニューを追加して、回転とスケールができるようにしてみましょう。
    表示するメニュー
    select
    前回と同じ選択モード
    rotateX
    rotateY
    rotateZ
    回転モード
    scaleX
    scaleY
    scaleZ
    原点中心のスケールモード

    # python objdisplay8.py sphere.obj

参考


Prev
index | home
abetmhr@gmail.com