質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

Q&A

受付中

openGLで描画したい 色を変えたり、消したり

0126tami
0126tami

総合スコア60

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

1回答

0グッド

0クリップ

8076閲覧

投稿2018/07/17 07:42

前提・実現したいこと

前回もここでまったくわからないopenGLについて質問させていただいたのですが、また質問させていただきたいと思います。

openGLでの描画がしたいと思っていてペイントソフトのように作るとこまでは前の質問にて解決しました。
次は画面上にボタンを作ってそのボタンを押すとペンの色が変わるというものとまた違うボタンを押すと一度描画した線が消えるというものを作りたいです。

ボタンだと難しいようでしたらあらかじめキーボード入力を決めておいて Bを入力したら 青色のペイント Yを入力したら 一度描画した線が消えるものです。

自分のような無知が質問するのも申し訳ないのですがどうしても作りたいので、協力してくださると助かります!!
よろしくお願いいたします

ソースコード

int WINW = 600;
int WINH = 400;
const int TEXTMAX = 40;
const int POINTMAX = 10000; // 大量の角を持つ折れ線を描いているのだから、バッファサイズが10点分しかないと線がすぐ消えていってしまう
char text[TEXTMAX];
double xList[POINTMAX];
double yList[POINTMAX];
int textnum;
int pointnum;

void DrawString() {
glRasterPos3d(0, 0, 0);//0,0,0位置をスタート位置にする

glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'P'); glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'a'); glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'i'); glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'n'); glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 't'); glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, '!');

}

void myDisplay() {
int i, j;

glClearColor(1.0, 1.0, 1.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); DrawString(); glColor3d(1.0, 0.0, 0.0); glBegin(GL_LINE_STRIP); for (i = 0; i < POINTMAX; i++) { j = (pointnum + i) % POINTMAX; if (xList[j] == -20.0) { // 座標バッファに目印となる値が見つかったら、そこをラインストリップの区切りとする glEnd(); glBegin(GL_LINE_STRIP); } else if (xList[j] >= -1.0 && yList[j] >= -1.0) { glVertex2d(xList[j], yList[j]); } } glEnd(); glRasterPos2d(-0.9, -0.7); glutSwapBuffers();

}

void myKeyboard(unsigned char key, int x, int y) {
if (key == 0x1B) exit(0);
text[textnum] = key;
textnum = (textnum + 1) % TEXTMAX;
glutPostRedisplay();
}

void myMouseFunc(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) {
// マウスボタンが放されたら、目印となる適当な値を座標バッファに入れてやる
// myDisplay中でその値が見つかったら、そこでラインストリップを区切ってやる
xList[pointnum] = -20.0;
yList[pointnum] = 0.0;
pointnum = (pointnum + 1) % POINTMAX;
glutPostRedisplay();
}
}

void myMotionFunc(int x, int y) {
// 前回のマウス座標と相違があれば、変更前のmyMouseFuncの
// ifブロック内でやっていたのと同じことを行う
static int prevX = -10.0, prevY = -10.0;
if (x == prevX && y == prevY) return;
prevX = x;
prevY = y;
xList[pointnum] = (((double)x / WINW) * 2) - 1;
yList[pointnum] = ((((double)y / WINH) * 2) - 1)*(-1);
pointnum = (pointnum + 1) % POINTMAX;
glutPostRedisplay();
}

void myReshape(int width, int height) {
glViewport(0, 0, width, height);
WINW = width;
WINH = height;
}

void myInit(char* progname) {
int i;
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(WINW, WINH);
glutInitWindowPosition(0, 0);
glutCreateWindow(progname);
pointnum = 0;
for (i = 0; i < POINTMAX; i++) {
xList[i] = -10.0;
yList[i] = -10.0;
}
textnum = 0;
for (i = 0; i < TEXTMAX; i++) {
text[i] = '?0';
}
}

int main(int argc, char* argv[]) {
glutInit(&argc, argv);
myInit(argv[0]);
glutKeyboardFunc(myKeyboard);
glutMouseFunc(myMouseFunc);
glutMotionFunc(myMotionFunc); // モーションイベント用のハンドラーを登録
glutReshapeFunc(myReshape);
glutDisplayFunc(myDisplay);
glutMainLoop();
return 0;
}

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答1

0

GLUT自体にはUIを簡単に描画できる機能は付属していないようなので、ひとまずキーボード操作で色変更機能と描画クリア機能を作ってみるのがいいかと思います。

描いた線を消すのは、myInit内で初期化した時と同じようにxListyListの中身を全部(-10.0, -10.0)にリセットしてしまえばいいでしょう。
色変えについては、正直自分でもちょっと妙なやり方だとは思うのですが...

  • 新たな目印値-30.0を導入し、描画時、座標バッファ中にこの目印が現れたら色変えを行う。
  • 変えるべき色は座標バッファのy成分、およびその次の座標のx成分とy成分に埋め込む。

といった方法を試してみました。
下記のようにmyDisplaymyKeyboardに変更を加え、色情報埋め込み用関数setColorを追加しました。

C

1void myDisplay() { 2 int i, j; 3 4 glClearColor(1.0, 1.0, 1.0, 0.0); 5 glClear(GL_COLOR_BUFFER_BIT); 6 7 glColor3d(1.0, 0.0, 0.0); // 最初のglColor3dをDrawStringより手前に移動 8 DrawString(); 9 10 glBegin(GL_LINE_STRIP); 11 for (i = 0; i < POINTMAX; i++) { 12 j = (pointnum + i) % POINTMAX; 13 if (xList[j] == -20.0) { 14 // 座標バッファに目印となる値が見つかったら、そこをラインストリップの区切りとする 15 glEnd(); 16 glBegin(GL_LINE_STRIP); 17 } else if (xList[j] == -30.0) { 18 // 色変更の目印が見つかったら、そこに埋め込まれた色情報を取り出してglColor3dに渡す 19 double red = yList[j]; 20 i++; 21 j = (pointnum + i) % POINTMAX; 22 double green = xList[j]; 23 double blue = yList[j]; 24 glColor3d(red, green, blue); 25 } else if (xList[j] >= -1.0 && yList[j] >= -1.0) { 26 glVertex2d(xList[j], yList[j]); 27 } 28 } 29 glEnd(); 30 31 glRasterPos2d(-0.9, -0.7); 32 33 glutSwapBuffers(); 34} 35 36void setColor(double red, double green, double blue) { 37 // 座標バッファに色変更の目印、および色情報を埋め込む 38 xList[pointnum] = -30.0; // 目印の値 39 yList[pointnum] = red; // 赤 40 pointnum = (pointnum + 1) % POINTMAX; 41 xList[pointnum] = green; // 緑 42 yList[pointnum] = blue; // 青 43 pointnum = (pointnum + 1) % POINTMAX; 44} 45 46void myKeyboard(unsigned char key, int x, int y) { 47 if (key == 0x1B) exit(0); 48 if (key == 'r') { 49 // Rキー押下...赤色に変更 50 setColor(1.0, 0.0, 0.0); 51 } else if (key == 'g') { 52 // Gキー押下...緑色に変更 53 setColor(0.0, 1.0, 0.0); 54 } else if (key == 'b') { 55 // Bキー押下...青色に変更 56 setColor(0.0, 0.0, 1.0); 57 } else if (key == 'y') { 58 // Yキー押下...座標バッファの内容全体を初期値(-10.0, -10.0)に戻す 59 for (int i = 0; i < POINTMAX; i++) { 60 xList[i] = -10.0; 61 yList[i] = -10.0; 62 } 63 } else { 64 text[textnum] = key; 65 textnum = (textnum + 1) % TEXTMAX; 66 } 67 glutPostRedisplay(); 68}

本来なら座標だけを格納するべきxListyListをどんどん引っかき回してしまい申し訳ないです...
この先もっとプログラムを機能拡張していくつもりでしたら、そろそろ設計見直しの頃合いかもしれません。

あいにく私はCやC++の経験が足りず具体的なアドバイスができないのですが、一例としてはオブジェクト指向的に「文字列オブジェクト...文字列、文字の色、描画座標を持つ」「フリーハンド曲線オブジェクト...曲線の色、頂点座標のリストを持つ」...といった感じに図形を設計しておいて、myDisplay内では画面内のこれらオブジェクトの描画メソッドを順次実行していく、なんていうのはどうでしょう?

※今回はキーボード入力で各機能を実行する方式にしましたが、GLUT向けのUIキットとしてGLUI(GLUI User Interface Library, v1GitHub - libglui/glui: GLUI is a GLUT-based C++ user interface library which provides controls such as buttons, checkboxes, radio buttons, and spinners to OpenGL applications. It is window-system independent, using GLUT or FreeGLUT.)といったものがあるようです。
検索してみただけで試してはおりませんが、ボタンなどの他にも3Dオブジェクトの移動や回転のためのコントロールも用意されているようですので、なかなか便利そうです。

投稿2018/07/17 22:26

Bongo

総合スコア10549

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

0126tami

2018/07/19 02:13

回答ありがとうございます! 思ったとおりのものができてよかったです

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。