mind-tech

主にテクノロジーや啓発系、副業などのテーマ中心

OpenGLを用いてC言語で矢印を描くプログラム

openglC言語を用いて矢印を描く必要があった。

以下の理由で、自分で関数を作成した。

  • 矢印を描く関数はopenglでは標準で用意されてない
  • webに落ちてるものはC++等が多く、Cで書かれているものは自分の望む挙動をしない
  • アニメーションで動作するプログラムがなかった

動作結果

最初に動作結果を載せる。挙動のさせ方は関数への引数で決まる。今回は円上の点を追うようにした。







openglの座標系は以下のようになっている
今回は以下のような設計にした。x,y平面上で動作する2Dモデルとする。

ここで、ちょっと戸惑ったのがopenglでは以下のようなへこみを表現できない問題がある
GL_POLYGONやGL_QUADSを使う場合、図のような内側にへこんだ図形は正しく描くことができない。
このような図形を描くときは、三角形に分割して、GL_TRIANGLE_STRIPなどを使って描く必要がある。
参照

ただ頂点だけを結んでPOLYGON表示させた場合

LINE_LOOPであれば描く事は可能

よって矢印を描く場合は、以下のように三角形と四角形に分けて描写した
以下、ソース。includeするヘッダーファイルが正しく表示されない為、以下のヘッダをincludeして利用してください
#include math.h
#include stdio.h
#include stdlib.h
#include GL/glut.h
#include GL/gl.h
/*  arrow.c   Copyright (c) 2012 by Chikara Morito All rights reserved  */

/*
x1,y1 始点の座標
x2,y2 動かしたい座標
length_arrow 矢全体の長さ
width_arrow 尾の幅
scele 比率...これを帰ると矢印の大きさが変わる
*/



#define KEY_ESC 27

void timer(int value){
glutPostRedisplay();
glutTimerFunc(10,timer,0);
}

void glDrawArrowd(float x1, float y1,float x2, float y2,float length_arrow,float width_arrow,float scale);


void display( void )
{
static float x,y;
static int deg;
glClear( GL_COLOR_BUFFER_BIT );
x = 10*cos(deg*M_PI/180);
y = 10*sin(deg*M_PI/180);
glDrawArrowd(0,0,x,y,8,2,1);

deg++;
if(deg == 360){
deg =0;
}
}


void myKbd( unsigned char key, int x, int y )
{
if ( key == KEY_ESC ) exit( 0 );
}


void myInit ( char *progname )
{
int width = 500, height = 500;

glutInitWindowPosition( 0, 0 );
glutInitWindowSize( width, height );
glutInitDisplayMode( GLUT_RGBA );
glutCreateWindow( progname );

glClearColor ( 0.0, 0.0, 0.0, 1.0 );
glutKeyboardFunc( myKbd );

glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glOrtho( -20.0, 20.0, -20.0, 20.0, -20.0, 20.0 );
}

void glDrawArrowd(float x1, float y1,float x2, float y2,float length_arrow,float width_arrow,float scale)
{
double deg;
float length,width;
double sn,cs;
float ratio;

length = scale*length_arrow;
width = scale*width_arrow;
deg = atan2(y2-y1,x2-x1);
sn = sin(deg);
cs = cos(deg);
//矢印の傘の部分と棒の部分の長さの比率は1:2とする。
//普通に計算するとintの型変換で0になるのでratio変数へ格納
ratio = (float)2/(float)3;

glColor3f( 0, 1.0, 0 );
glBegin(GL_QUADS);
glVertex3f(x1+width/2*sn,y1-width/2*cs,0);
glVertex3f(x1+width/2*sn+ratio*length*cs,y1-width/2*cs+ratio*length*sn,0);
glVertex3f(x1-width/2*sn+ratio*length*cs,y1+width/2*cs+ratio*length*sn,0);
glVertex3f(x1-width/2*sn,y1+width/2*cs,0);
glEnd();

glBegin(GL_TRIANGLES);
glVertex3f(x1+ratio*length*cs,y1+ratio*length*sn,0);
glVertex3f(x1+width/2*sn+ratio*length*cs+width*sn,y1-width/2*cs+ratio*length*sn-width*cs,0);
glVertex3f(x1+length*cs,y1+length*sn,0);
glEnd();
glBegin(GL_TRIANGLES);
glVertex3f(x1+length*cs,y1+length*sn,0);
glVertex3f(x1-width/2*sn+ratio*length*cs-width*sn,y1+width/2*cs+ratio*length*sn+width*cs,0);
glVertex3f(x1+ratio*length*cs,y1+ratio*length*sn,0);
glEnd();

glFlush();
}


int main( int argc, char** argv )
{

glutInit( &argc, argv );
myInit( argv[0] );
glutDisplayFunc( display );
glutTimerFunc(1,timer,0);
glutMainLoop();

return( 0 );
}

Copyright ©mind-teck All rights reserved..
🔒プライバシーポリシー