hit   今日   昨日

OpenGLでのロケット製作について

[このトピックは解決済みです]

フォーラムルール
フォーラムルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Name: pity
[URL]
Date: 2011年12月03日(土) 19:45
No: 1
(OFFLINE)

 OpenGLでのロケット製作について

[1] (1)ロケットをy軸回りに回転させよ。
(2)一段目(羽のついてる所)を異なる速度で回転させよ。
(3)polarviewを用いて、斜め上30度から見た画面にせよ。
(4)マウス操作で視点の変更を可能とする。
   ・左ボタンの左右方向のドラッグで物体が垂直軸回りに回転。また同ボタンの
    上下方向のドラッグで水平軸回りに回転。
   ・右ボタンのドラッグで、物体が拡大縮小する。
   ・ビューイング変換にはpolrviewを用いる。
(5)F1キーを押すと一段目が離れるようにせよ。
という宿題が出されました。

 [1.1] (3)(5)の作成をしたいと思っております。
 [1.2]
コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <stdlib.h>
#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <math.h>
#include "myShape.h"
#define KEY_ESC 27
 
void polarview( void );
void resetview( void );
unsigned char wireFlag = GL_TRUE;
unsigned char revolveFlag = GL_FALSE;
int xBegin, yBegin;
 
int mButton;
float distance, twist, elevation, azimuth;
 
float theta=0.0;  /*物体の回転角度*/
float theta2=0.0;  /*物体の回転角度*/
 
void display( void )
{
    glClear( GL_COLOR_BUFFER_BIT );
    glPushMatrix();
 
      glTranslatef( 0.0, 0.0, -20.0 );
    polarview();  /*ビューイング*/
        glPushMatrix();
    glRotatef( theta, 0.0, 1.0, 0.0 );  /*回転させたいところ*/
      glTranslatef( 0.0, 1.0, 0.0 );
    glColor3f(1.0,0.0,0.0);
    myWireCylinder( 1.0, 2.0, 12 );
    glTranslatef( 0.0, 1.0, 0.0);
    glRotatef( -90.0, 1.0, 0.0, 0.0 );
    glColor3f(1.0,0.5,0.0);
 
    glutWireCone( 1.0, 2.0, 12, 3 );
    glPopMatrix();
    glRotatef( theta2, 0.0, 1.0, 0.0 );  /*回転させたいところ*/
    glTranslatef( 0.0, -1.0, 0.0 );
    glColor3f(0.0,1.0,0.0);
    myWireCylinder( 1.0, 2.0, 12 );
    glPopMatrix();
 
    glPushMatrix();
    glTranslatef( 0.0, -1.0, -20.0);
    polarview();  /*ビューイング*/
    glRotatef( theta2, 0.0, 1.0, 0.0 );  /*回転させたいところ*/
   
    glTranslatef( 0.0, -1.5, 0.0);
    glRotatef( -90.0, 1.0, 0.0, 0.0 );
    glColor3f(0.0,1.0,1.0);
    glutWireCone( 0.5, 0.8, 12, 1 );
 
    glTranslatef(0.0,0.0,1.5);
    glScalef(0.8,0.07,0.5);
    glColor3f(1.0,0.0,1.0);
    glutWireCube(4.0);
 
    glTranslatef(0.0,0.0,0.0);
    glScalef(0.08,11.0,1.0);
    glColor3f(1.0,1.0,0.0);
    glutWireCube(4.0);
 
    glPopMatrix();
    glutSwapBuffers();  /*バッファをスワップする*/
}
 
void idle(void)  /*イベントがなければidleが常に実行される*/
{
      theta=fmod(theta+0.2,360.0);  /*回転角を0~360まで0.2ずつ増加*/
    theta2=fmod(theta2+2.0,360.0);  /*回転角を0~360まで2.0ずつ増加*/
    glutPostRedisplay();
}
 
void myKbd( unsigned char key, int x, int y )
 
{
      if( key == KEY_ESC ) exit( 0 );
}
 
void myMouse( int button, int state, int x, int y )
{
    if (state == GLUT_DOWN) {
        switch(button) {
        case GLUT_LEFT_BUTTON:
            mButton = button;
            break;
        case GLUT_MIDDLE_BUTTON:
            revolveFlag = !revolveFlag;
            if( revolveFlag == GL_TRUE )
                glutIdleFunc( idle );
            else
                glutIdleFunc(NULL);
            break;
        case GLUT_RIGHT_BUTTON:
            mButton = button;
            break;
        }
        xBegin = x;
        yBegin = y;
    }
}
 
void myMotion( int x, int y )
{
    int xDisp, yDisp;
   
    xDisp = x - xBegin;
    yDisp = y - yBegin;
 
    switch (mButton) {
    case GLUT_LEFT_BUTTON:
        azimuth += (float) xDisp/2.0;
        elevation -= (float) yDisp/2.0;
        break;
    case GLUT_RIGHT_BUTTON:
        distance += (float) yDisp/40.0;
        break;
    }
    xBegin = x;
    yBegin = y;
    glutPostRedisplay();
}
 
void myInit (char *progname)
{
      int width = 300, height = 600;
        float aspect = (float) width / (float) height;
        glutInitWindowPosition(0, 0);
      glutInitWindowSize( width, height );
      glutInitDisplayMode( GLUT_RGBA );
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);  /*ダブルバッファ宣言*/
      glutCreateWindow(progname);
      glClearColor (0.0, 0.0, 0.0, 1.0);
        glutKeyboardFunc( myKbd );
    glutMouseFunc(myMouse);
      glutMotionFunc(myMotion);
    resetview();
 
      glMatrixMode(GL_PROJECTION);
      glLoadIdentity();
      gluPerspective(30.0, aspect, 1.0, 50.0);
      glMatrixMode(GL_MODELVIEW);
}
 
void resetview( void )
{
      distance = 5.0;
      twist = 0.0;
      elevation = 0.0;
      azimuth = 0.0;
} 
 
void polarview( void )
{
      glTranslatef( 0.0, 0.0, -distance);
      glRotatef( -twist, 0.0, 0.0, 1.0);
      glRotatef( -elevation, 1.0, 0.0, 0.0);
      glRotatef( -azimuth, 0.0, 1.0, 0.0);
}
 
int main(int argc, char** argv)
{
      glutInit(&argc, argv);
    myInit(argv[0]);
      glutDisplayFunc(display);
    glutIdleFunc(idle);  /*イベントがない場合にはidleを繰り返す*/
    glutMainLoop();
    return( 0 );
}


 [1.3] 特にありません。
 [1.4]4枚の羽根が作れず、その上視点を変えると羽と噴射口の位置がずれます。
どのように直せばよいのか分からないため、修正をお願い致します。

[2] 環境  
 [2.1] OS : Windows
 [2.2] コンパイラ名 : Microsoft Visual C++ 2010 Express
[3] その他
 ・初心者です。
 ・期限は12月5日までです。
どうぞ、よろしくお願いいたします。

Name: うしお
[URL]
中級者(14,208 ポイント)
Date: 2011年12月03日(土) 20:06
No: 2
(OFFLINE)

 Re: OpenGLでのロケット製作について

全部追いかけたわけではありませんが、いくつか気になった所に触れてみます。

行列スタックの考え方で混乱してはいませんか?
projectionはdisplayでは操作していませんので問題ないとして、
polarviewでビュー行列を設定しようとしているのだとおもいますが、
基本的に描画のフローとしては、
ビュー行列掛け算→glPushMatrix→モデル1のワールド行列掛け算→モデル1を描画→glPopMatrix
           →glPushMatrix→モデル2のワールド行列掛け算→モデル2を描画→glPopMatrix....
という流れを意識されると整理されると思います。

なんとなく出題意図として「gluLookAtを使わないでやってみよう」という意志が感じられますが、
横着するならgluLookAt関数がいいかなと思います。

Name: pity
[URL]
Date: 2011年12月03日(土) 21:27
No: 3
(OFFLINE)

 Re: OpenGLでのロケット製作について

ご回答ありがとうございます。(3)については出来そうです。
>基本的に描画のフローとしては、
 ビュー行列掛け算→glPushMatrix→モデル1のワールド行列掛け算→モデル1を描画→glPopMatrix
         →glPushMatrix→モデル2のワールド行列掛け算→モデル2を描画→glPopMatrix....
 という流れを意識されると整理されると思います。

ということは、流れを整理できれば羽や噴射口がずれることはないということですか?
教科書レベルのものもまともにできないため、言葉のみで説明していただいてもこの頭では理解することができませんでした。
可能であれば、プログラムで説明していただければと思います。申し訳ありません。

Name: うしお
[URL]
中級者(14,208 ポイント)
Date: 2011年12月03日(土) 22:52
No: 4
(OFFLINE)

 Re: OpenGLでのロケット製作について

一応ビルドして実行してみましたが(myWireCylinder以外)、
すみません、いまいちどこがずれていてどう直したいのかがわかりません。

ただ流れをはっきりと理解すれば、
どこが意図していないプログラムなのかが見つかりやすくなり、
バグ修正への道は開けます。

Name: pity
[URL]
Date: 2011年12月04日(日) 12:45
No: 5
(OFFLINE)

 Re: OpenGLでのロケット製作について

http://kie.nu/2lB
このリンク先の白黒画像の様にしたいのですが、カラー画像の様に羽と噴射口がずれてしまいます。
これを中央に直したいのです。逆さまにしてもロケットの形が崩れないようにもしたいです。
また、これは2つの四角形で羽を作ってますが、白黒画像の様に4枚羽にしたいと思っています。

Name: うしお
[URL]
中級者(14,208 ポイント)
Date: 2011年12月04日(日) 14:03
No: 6
(OFFLINE)

 Re: OpenGLでのロケット製作について

コード[C++]: 全て選択
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <stdlib.h>
#include <math.h>
#include <openglut.h>
#include <GL/gl.h>
#include <GL/glu.h>
 
#define KEY_ESC 27
 
void polarview( void );
void resetview( void );
unsigned char wireFlag = GL_TRUE;
unsigned char revolveFlag = GL_FALSE;
int xBegin, yBegin;
 
int mButton;
float distance, elevation, azimuth;
 
float theta=0.0;  /*物体の回転角度*/
float theta2=0.0;  /*物体の回転角度*/
 
float rocketRotation = 0.0f;
float lowerBodyRotation = 0.0f;
 
void display( void )
{
    glLoadIdentity();
    polarview();  /*ビューイング*/
 
    glClear( GL_COLOR_BUFFER_BIT );
 
    //x,y,z軸 これがあるとやりやすい
    glBegin(GL_LINES);
    glColor3f(1.0f,0,0); glVertex3f(0,0,0); glVertex3f(100.0f,0,0);
    glColor3f(0,1.0f,0); glVertex3f(0,0,0); glVertex3f(0,100.0f,0);
    glColor3f(0,0,1.0f); glVertex3f(0,0,0); glVertex3f(0,0,100.0f);
    glEnd();
 
    //ロケット全体を回転させるにはここでpush
    rocketRotation += 0.3f;
    glPushMatrix();
    glRotatef(rocketRotation, 0, 1.0f, 0);
    { /*見やすくするためだけのインデント*/
        //噴射口
        glColor3f(0,0,1.0f);
        glPushMatrix();
            glRotatef(-90.0f, 1.0f, 0,0);
            glutWireCone(0.2, 0.2, 10, 1);
        glPopMatrix();
 
        // 羽とボディをまとめて回転するにはここでpush→回転
        lowerBodyRotation += 0.5f; // 回転角度を更新
        glPushMatrix(); // 羽とボディ
        glRotatef(lowerBodyRotation, 0, 1.0f, 0);
        {
            // ボディ下
            glColor3f(1.0,0.5,0.0);
            glPushMatrix();
                glTranslatef(0, 0.2f, 0);
                glRotatef(-90.0f, 1.0f, 0,0);
                glutWireCylinder(0.2, 0.3, 10, 1);
            glPopMatrix();
 
            // 羽
            glPushMatrix();
                glTranslatef(0.25f,0.35f,0);
                glScalef(0.1f, 0.3f, 0.05f);
                glutWireCube(1.0);
            glPopMatrix();
            glPushMatrix();
                glRotatef(90.0f, 0, 1.0f, 0);
                glTranslatef(0.25f,0.35f,0);
                glScalef(0.1f, 0.3f, 0.05f);
                glutWireCube(1.0);
            glPopMatrix();
            glPushMatrix();
                glRotatef(180.0f, 0, 1.0f, 0);
                glTranslatef(0.25f,0.35f,0);
                glScalef(0.1f, 0.3f, 0.05f);
                glutWireCube(1.0);
            glPopMatrix();
            glPushMatrix();
                glRotatef(270.0f, 0, 1.0f, 0);
                glTranslatef(0.25f,0.35f,0);
                glScalef(0.1f, 0.3f, 0.05f);
                glutWireCube(1.0);
            glPopMatrix();
        }
        glPopMatrix();// 羽とボディ
 
        // ボディ上
        glColor3f(0.0,1.0,1.0);
        glPushMatrix();
            glTranslatef(0, 0.5f, 0);
            glRotatef(-90.0f, 1.0f, 0,0);
            glutWireCylinder(0.2, 0.3, 10, 1);
        glPopMatrix();
 
        //頭
        glColor3f(1.0,1.0,0.0);
        glPushMatrix();
            glTranslatef(0, 0.8f, 0);
            glRotatef(-90.0f, 1.0f, 0,0);
            glutWireCone(0.2, 0.3, 10, 1);
        glPopMatrix();
    }
    glPopMatrix();
 
  glutSwapBuffers(); /*バッファをスワップする*/
}
void idle(void)  /*イベントがなければidleが常に実行される*/
{
  glutPostRedisplay();
}
void myKbd( unsigned char key, int, int)
{
    if( key == KEY_ESC ) exit( 0 );
}
void myMouse( int button, int state, int x, int y )
{
    if (state == GLUT_DOWN) {
        switch(button) {
        case GLUT_LEFT_BUTTON:
            mButton = button;
            break;
        case GLUT_MIDDLE_BUTTON:
            revolveFlag = !revolveFlag;
            if( revolveFlag == GL_TRUE )
                glutIdleFunc( idle );
            else
                glutIdleFunc(NULL);
            break;
        case GLUT_RIGHT_BUTTON:
            mButton = button;
            break;
        }
        xBegin = x;
        yBegin = y;
    }
}
 
void myMotion( int x, int y )
{
    int xDisp, yDisp;
   
    xDisp = x - xBegin;
    yDisp = y - yBegin;
 
    switch (mButton) {
    case GLUT_LEFT_BUTTON:
        azimuth += (float)xDisp / 2.0f;
        elevation += (float)yDisp / 2.0f;
        break;
    case GLUT_RIGHT_BUTTON:
        distance += (float)yDisp/40.0f;
        break;
    }
    xBegin = x;
    yBegin = y;
    glutPostRedisplay();
}
 
void myInit (char *progname)
{
    int width = 300, height = 600;
    float aspect = (float) width / (float) height;
    glutInitWindowPosition(0, 0);
    glutInitWindowSize( width, height );
    glutInitDisplayMode( GLUT_RGBA );
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);  /*ダブルバッファ宣言*/
    glutCreateWindow(progname);
    glClearColor (0.0, 0.0, 0.0, 1.0);
   
    glutKeyboardFunc( myKbd );
    glutMouseFunc(myMouse);
    glutMotionFunc(myMotion);
    resetview();
 
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(30.0, aspect, 1.0, 50.0);
    glMatrixMode(GL_MODELVIEW);
}
 
void resetview( void )
{
    distance = 5.0;
    elevation = 0.0;
    azimuth = 0.0;
}
void polarview( void )
{
    glTranslatef( 0.0, 0.0, -distance);
    glRotatef( -elevation, 1.0, 0.0, 0.0);
    glRotatef( -azimuth, 0.0, 1.0, 0.0);
}
 
int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    myInit(argv[0]);
    glutDisplayFunc(display);
    glutIdleFunc(idle);/*イベントがない場合にはidleを繰り返す*/
    glutMainLoop();
    return 0;
}

できるだけ意味を把握しやすく整理してみました。
行列スタックの考え方をしっかりと把握することが大切かと思います。
例えば、
Push
 移動(右に1)
 物体1の描画
 Push
 回転(半回転)
 移動(右に2)
 物体2の描画
 Pop
Pop
という構造の時は、
物体1は 右に1移動した状態
物体2は 右に2移動→半回転→右に1移動した状態
という状態になります。
すこしややこしいでしょうか?
実際にためしながら、体で覚えるといいかと思います。

追記
openglutなのは気にせずglutで問題ないはずです。

Name: pity
[URL]
Date: 2011年12月04日(日) 18:32
No: 7
(OFFLINE)

 Re: OpenGLでのロケット製作について

[解決!]

教科書と文がだいぶ違っていたので初めは分かりませんでしたが、
何とか出来たと思います。有難うございました!


Return to C言語何でも質問掲示板

オンラインデータ

このフォーラムを閲覧中のユーザー: Dixq (管理人), h2so5 & ゲスト[28人]