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

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

ただいまの
回答率

90.47%

  • Visual Studio

    1914questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • OpenGL

    169questions

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

OpenGLでマウスで描画できるようにしたい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 423

0126tami

score 4

OpenGL(2015)をつかって簡単なお絵かきソフトのようなものを作りたいと思っています。

そしてプログラムを途中まで作ることができました
今の時点で、マウスでクリックしていくとクリックしたところから次にクリックしたところまで直線がかけるというプログラムになっています。

それをマウスでクリックし続けているときに線が書けるようにしたいのです。
いわゆる普通のペイントみたいな感じです。

マウスでクリックしているときからマウスの手をはなすまでの間にディスプレイ上に描画するような関数?を作ればいいのかなとは思うのですが
OpenGL初心者なものでまったくわかりません。

だからわかる方ぜひ教えてください。

#include "stdafx.h"
#include <stdlib.h>
#include <gl/glut.h>


int WINW = 600;
int WINH = 400;
const int TEXTMAX = 40;
const int POINTMAX = 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] >= -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_DOWN) {
        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);
    glutReshapeFunc(myReshape);
    glutDisplayFunc(myDisplay);
    glutMainLoop();
    return 0;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

現状のコードではマウスボタン押下のたびに折れ線の頂点を追加していますが、代わりにドラッグイベント(GLUTだと「モーション」というらしいですね...初めて知りました)で同じことをしてみるのはどうでしょう?
細かい折れ線で曲線を表現するイメージです。どちらかというとペイント系ソフトよりもドロー系ソフトのようなアプローチですが...

#include "stdafx.h"
#include <stdlib.h>
#include <gl/glut.h>

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;
}

(参考:WisdomSoft(旧) - OpenGL入門 - GLUT のイベント

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/01 12:41

    とっても助かりますありがとうございます

    キャンセル

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • Visual Studio

    1914questions

    Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

  • OpenGL

    169questions

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