ページ 11

エラー修正お願いします。

Posted: 2011年10月28日(金) 22:48
by Ryo
初心者なので、サンプルコードに新しい関数を自分で入れるとどうしてもエラーが出てしまいます。
今後、エラーが出ないように出来るコツも教えてほしいです。
OpenGLで、仮想三次元を作って、マウスで視点の向きを変えたいのです。
あと、カーソルキーで視点の場所を平行移動出来る関数もついでに入れてほしいです。

(43) : error C2664: 'glutMotionFunc' : 1 番目の引数を 'void (__cdecl *)(void)' から 'void (__cdecl *)(int,int)' に変換できません。
(44) : error C2664: 'glutMouseFunc' : 1 番目の引数を 'void (__cdecl *)(void)' から 'void (__cdecl *)(int,int,int,int)' に変換できません。
(89) : error C2660: 'PolarCoordinatesLookAt' : 関数に 6 個の引数を指定できません。


#include <GL/glut.h>
#define _USE_MATH_DEFINES
#include "math.h"

//----------------------------------------------------
// 変数の宣言
//----------------------------------------------------
int WindowPositionX = 200; //生成するウィンドウ位置のX座標
int WindowPositionY = 200; //生成するウィンドウ位置のY座標
int WindowWidth = 512; //生成するウィンドウの幅
int WindowHeight = 512; //生成するウィンドウの高さ
char WindowTitle[] = "世界の始まり"; //ウィンドウのタイトル
int mouseFlag = GL_FALSE;
int mouseXStart;
int mouseYStart;
double mouseXAngle = 0.0;
double mouseYAngle = 0.4*M_PI;
double mouseXDis =5.0;

//----------------------------------------------------
// 関数プロトタイプ(後に呼び出す関数名と引数の宣言)
//----------------------------------------------------
void Initialize(void); //初期設定時に呼び出す関数
void Idle(void); //アイドル時に呼び出す関数
void Display(void); //画面描画時に呼び出す関数
void Ground(void); //大地の描画用の関数
void PolarCoordinatesLookAt(void);
void myMouseMotion(void);
void myMouseFunc(void);

//----------------------------------------------------
// メイン関数
//----------------------------------------------------
int main(int argc, char *argv[]){
glutInit(&argc, argv); //環境の初期化
glutInitWindowPosition(WindowPositionX, WindowPositionY); //ウィンドウの位置の指定
glutInitWindowSize(WindowWidth, WindowHeight); //ウィンドウサイズの指定
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //ディスプレイモードの指定
glutCreateWindow(WindowTitle); //ウィンドウの作成
glutIdleFunc(Idle); //プログラムアイドル状態時に呼び出される関数
glutDisplayFunc(Display); //描画時に呼び出される関数を指定する(関数名:Display)
Initialize(); //初期設定の関数を呼び出す
glutMotionFunc(myMouseMotion);
glutMouseFunc(myMouseFunc);
glutMainLoop();
return 0;
}

void PolarCoordinatesLookAt(void){
double r, theta, phi, cx, cy, cz, x, y, z;

//球座標から直交座標に変換
x = r*sin(phi)*cos(theta) + cx;
y = r*sin(phi)*sin(theta) + cy;
z = r*cos(phi) + cz;

//z軸が上方向
gluLookAt(x, y, z, cx, cy, cz, 0.0, 0.0, 1.0);
}

//----------------------------------------------------
// 初期設定の関数
//----------------------------------------------------
void Initialize(void){
glClearColor(1.0, 1.0, 1.0, 0.0); //背景色
glEnable(GL_DEPTH_TEST);//デプスバッファを使用:glutInitDisplayMode() でGLUT_DEPTH を指定する

//透視変換行列の設定------------------------------
glMatrixMode(GL_PROJECTION);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
glLoadIdentity();//行列の初期化
gluPerspective(30.0, (double)WindowWidth/(double)WindowHeight, 0.1, 1000.0); //透視投影法の視体積gluPerspactive(th, w/h, near, far);
//------------------------------------------------
}
//----------------------------------------------------
// アイドル時に呼び出される関数
//----------------------------------------------------
void Idle(){
glutPostRedisplay(); //glutDisplayFunc()を1回実行する
}
//----------------------------------------------------
// 描画の関数
//----------------------------------------------------
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //バッファの消去
//モデルビュー変換行列の設定--------------------------
glMatrixMode(GL_MODELVIEW);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
glLoadIdentity();//行列の初期化
glViewport(0, 0, WindowWidth, WindowHeight);
PolarCoordinatesLookAt(mouseXDis, mouseXAngle, mouseYAngle, 0.0, 0.0, 0.0);

//----------------------------------------------

Ground();

glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可
}
//----------------------------------------------------
// 大地の描画
//----------------------------------------------------
void Ground(void) {
double ground_max_x = 300.0;
double ground_max_y = 300.0;
glColor3d(0.8, 0.8, 0.8); // 大地の色
glBegin(GL_LINES);
for(double ly = -ground_max_y ;ly <= ground_max_y; ly+=20.0){
glVertex3d(-ground_max_x, ly,0);
glVertex3d(ground_max_x, ly,0);
}
for(double lx = -ground_max_x ;lx <= ground_max_x; lx+=20.0){
glVertex3d(lx, ground_max_y,0);
glVertex3d(lx, -ground_max_y,0);
}
glEnd();
}

void myMouseMotion(void){
int x, y, xdis, ydis;

switch(mouseFlag){
case 0x100: //GLUT_LEFT_BUTTON
xdis = x - mouseXStart;
ydis = y - mouseYStart;

mouseXAngle -= (double)xdis * 0.002;
mouseYAngle -= (double)ydis * 0.002;
break;

case 0x001: //GLUT_RIGHT_BUTTON
xdis = x - mouseXStart;

mouseXDis += (double)xdis * 0.002;
break;
}

mouseXStart = x;
mouseYStart = y;
}

void myMouseFunc(void){

int button, state, x, y;

if(state == GLUT_DOWN ){
switch(button){
case GLUT_LEFT_BUTTON:
mouseXStart = x;
mouseYStart = y;
mouseFlag = 0x100;
break;

case GLUT_RIGHT_BUTTON:
mouseXStart = x;
mouseYStart = y;
mouseFlag = 0x001;
break;

default:
break;
}
}else{
mouseFlag = 0x000;
}
}

Re: エラー修正お願いします。

Posted: 2011年10月28日(金) 22:54
by softya(ソフト屋)
マルチポストに該当しますので相互リンクをお願いします。詳しくはフォーラムルールをお読みください。
http://dixq.net/board/board.html

「C++のエラーを治してほしいのです。 後、今後にエラーが出ないようにするためのコ... - Yahoo!知恵袋」
http://detail.chiebukuro.yahoo.co.jp/qa ... 1074306555

それとC言語を勉強せずにOpenGLを扱うことは困難です。
フォーラムルールにあるテンプレートにしたがって今までのC/C++の理解度についてできるだけ詳しい書き込みと、今後のcodeタグの利用をお願いします。

Re: エラー修正お願いします。

Posted: 2011年10月28日(金) 23:25
by Ryo
見やすくなるように修正。
Yahooの方は字数制限があるので、こちらで全文を表示してみました。
C++は独学でだいたい6カ月程度で、HTML、JAVA、PHPは独学で1年ぐらいです。
ARTookit弄るぐらいの趣味レベルです。

コード:

 

#include <GL/glut.h>
#define _USE_MATH_DEFINES
#include "math.h"

//----------------------------------------------------
// 変数の宣言
//----------------------------------------------------
int WindowPositionX = 200; //生成するウィンドウ位置のX座標
int WindowPositionY = 200; //生成するウィンドウ位置のY座標
int WindowWidth = 512; //生成するウィンドウの幅
int WindowHeight = 512; //生成するウィンドウの高さ
char WindowTitle[] = "世界の始まり"; //ウィンドウのタイトル
int	mouseFlag = GL_FALSE;
int	mouseXStart;
int mouseYStart;
double	mouseXAngle = 0.0; 
double mouseYAngle = 0.4*M_PI;
double	mouseXDis =5.0;

//----------------------------------------------------
// 関数プロトタイプ(後に呼び出す関数名と引数の宣言)
//----------------------------------------------------
void Initialize(void); //初期設定時に呼び出す関数
void Idle(void); //アイドル時に呼び出す関数
void Display(void); //画面描画時に呼び出す関数
void Ground(void); //大地の描画用の関数
void PolarCoordinatesLookAt(void);
void myMouseMotion(void);
void myMouseFunc(void);

//----------------------------------------------------
// メイン関数
//----------------------------------------------------
int main(int argc, char *argv[]){
glutInit(&argc, argv); //環境の初期化
glutInitWindowPosition(WindowPositionX, WindowPositionY); //ウィンドウの位置の指定
glutInitWindowSize(WindowWidth, WindowHeight); //ウィンドウサイズの指定
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //ディスプレイモードの指定
glutCreateWindow(WindowTitle); //ウィンドウの作成
glutIdleFunc(Idle); //プログラムアイドル状態時に呼び出される関数
glutDisplayFunc(Display); //描画時に呼び出される関数を指定する(関数名:Display)
Initialize(); //初期設定の関数を呼び出す
glutMotionFunc(myMouseMotion);
glutMouseFunc(myMouseFunc);
glutMainLoop();
return 0;
}

void PolarCoordinatesLookAt(void){
double r, theta, phi, cx, cy, cz, x, y, z;

//球座標から直交座標に変換
x = r*sin(phi)*cos(theta) + cx;
y = r*sin(phi)*sin(theta) + cy;
z = r*cos(phi) + cz;

//z軸が上方向
gluLookAt(x, y, z, cx, cy, cz, 0.0, 0.0, 1.0);
}

//----------------------------------------------------
// 初期設定の関数
//----------------------------------------------------
void Initialize(void){
glClearColor(1.0, 1.0, 1.0, 0.0); //背景色
glEnable(GL_DEPTH_TEST);//デプスバッファを使用:glutInitDisplayMode() でGLUT_DEPTH を指定する

//透視変換行列の設定------------------------------
glMatrixMode(GL_PROJECTION);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
glLoadIdentity();//行列の初期化
gluPerspective(30.0, (double)WindowWidth/(double)WindowHeight, 0.1, 1000.0); //透視投影法の視体積gluPerspactive(th, w/h, near, far);
//------------------------------------------------
}
//----------------------------------------------------
// アイドル時に呼び出される関数
//----------------------------------------------------
void Idle(){
glutPostRedisplay(); //glutDisplayFunc()を1回実行する
}
//----------------------------------------------------
// 描画の関数
//----------------------------------------------------
void Display(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //バッファの消去
//モデルビュー変換行列の設定--------------------------
glMatrixMode(GL_MODELVIEW);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
glLoadIdentity();//行列の初期化
glViewport(0, 0, WindowWidth, WindowHeight);
PolarCoordinatesLookAt(mouseXDis, mouseXAngle, mouseYAngle, 0.0, 0.0, 0.0);

//----------------------------------------------

Ground();

glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可
}
//----------------------------------------------------
// 大地の描画
//----------------------------------------------------
void Ground(void) {
double ground_max_x = 300.0;
double ground_max_y = 300.0;
glColor3d(0.8, 0.8, 0.8); // 大地の色
glBegin(GL_LINES);
for(double ly = -ground_max_y ;ly <= ground_max_y; ly+=20.0){
glVertex3d(-ground_max_x, ly,0);
glVertex3d(ground_max_x, ly,0);
}
for(double lx = -ground_max_x ;lx <= ground_max_x; lx+=20.0){
glVertex3d(lx, ground_max_y,0);
glVertex3d(lx, -ground_max_y,0);
}
glEnd();
}

void myMouseMotion(void){
int x, y, xdis, ydis;

switch(mouseFlag){
case 0x100: //GLUT_LEFT_BUTTON
xdis = x - mouseXStart;
ydis = y - mouseYStart;

mouseXAngle -= (double)xdis * 0.002;
mouseYAngle -= (double)ydis * 0.002;
break;

case 0x001: //GLUT_RIGHT_BUTTON
xdis = x - mouseXStart;

mouseXDis += (double)xdis * 0.002;
break;
}

mouseXStart = x;
mouseYStart = y;
}

void myMouseFunc(void){

int button, state, x, y;

if(state == GLUT_DOWN ){
switch(button){
case GLUT_LEFT_BUTTON:
mouseXStart = x;
mouseYStart = y;
mouseFlag = 0x100;
break;

case GLUT_RIGHT_BUTTON:
mouseXStart = x;
mouseYStart = y;
mouseFlag = 0x001;
break;

default:
break;
}
}else{
mouseFlag = 0x000;
}
}


Re: エラー修正お願いします。

Posted: 2011年10月28日(金) 23:41
by Ryo
「OpenGLで、仮想三次元を作って、マウスで視点の向きを変えたいのです。」
上はなんとか自己解決しました。

後は、「カーソルキーで視点の場所を平行移動出来る関数」と「中クリックで拡大縮小出来る関数」もついでに入れてほしいです。

コード:

 

#include <GL/glut.h>
#define _USE_MATH_DEFINES
#include "math.h"

//----------------------------------------------------
// 変数の宣言
//----------------------------------------------------
int WindowPositionX = 200;  //生成するウィンドウ位置のX座標
int WindowPositionY = 200;  //生成するウィンドウ位置のY座標
int WindowWidth = 512;      //生成するウィンドウの幅
int WindowHeight = 512;     //生成するウィンドウの高さ
char WindowTitle[] = "世界の始まり";  //ウィンドウのタイトル
int	mouseFlag = GL_FALSE;
int	mouseXStart;
int mouseYStart;
double	mouseXAngle = 0.0; 
double  mouseYAngle = 0.4*M_PI;
double	mouseXDis =5.0;

//----------------------------------------------------
// 関数プロトタイプ(後に呼び出す関数名と引数の宣言)
//----------------------------------------------------
void Initialize(void);   //初期設定時に呼び出す関数
void Idle(void);         //アイドル時に呼び出す関数
void Display(void);      //画面描画時に呼び出す関数
void Ground(void);       //大地の描画用の関数
void PolarCoordinatesLookAt(void);
void myMouseMotion(int,int);
void myMouseFunc(int,int,int,int);

//----------------------------------------------------
// メイン関数
//----------------------------------------------------
int main(int argc, char *argv[]){
  glutInit(&argc, argv);                                     //環境の初期化
  glutInitWindowPosition(WindowPositionX, WindowPositionY);  //ウィンドウの位置の指定
  glutInitWindowSize(WindowWidth, WindowHeight);             //ウィンドウサイズの指定
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //ディスプレイモードの指定
  glutCreateWindow(WindowTitle);                             //ウィンドウの作成
  glutIdleFunc(Idle);                                        //プログラムアイドル状態時に呼び出される関数
  glutDisplayFunc(Display);                                  //描画時に呼び出される関数を指定する(関数名:Display)
  Initialize();                                              //初期設定の関数を呼び出す
  glutMotionFunc(myMouseMotion);
  glutMouseFunc(myMouseFunc);
  glutMainLoop();
  return 0;
}

void PolarCoordinatesLookAt(double r, double theta, double phi, double cx, double cy, double cz){
	double x, y, z;

	//球座標から直交座標に変換
	x = r*sin(phi)*cos(theta) + cx;
	y = r*sin(phi)*sin(theta) + cy;
	z = r*cos(phi) + cz;

	//z軸が上方向
	gluLookAt(x, y, z, cx, cy, cz, 0.0, 0.0, 1.0);
}

//----------------------------------------------------
// 初期設定の関数
//----------------------------------------------------
void Initialize(void){
  glClearColor(1.0, 1.0, 1.0, 0.0); //背景色
  glEnable(GL_DEPTH_TEST);//デプスバッファを使用:glutInitDisplayMode() でGLUT_DEPTH を指定する

  //透視変換行列の設定------------------------------
  glMatrixMode(GL_PROJECTION);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
  glLoadIdentity();//行列の初期化
  gluPerspective(30.0, (double)WindowWidth/(double)WindowHeight, 0.1, 1000.0); //透視投影法の視体積gluPerspactive(th, w/h, near, far);
  //------------------------------------------------
}
//----------------------------------------------------
// アイドル時に呼び出される関数
//----------------------------------------------------
void Idle(){
  glutPostRedisplay(); //glutDisplayFunc()を1回実行する
}
//----------------------------------------------------
// 描画の関数
//----------------------------------------------------
void Display(void) {
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //バッファの消去
  //モデルビュー変換行列の設定--------------------------
  glMatrixMode(GL_MODELVIEW);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
  glLoadIdentity();//行列の初期化
  glViewport(0, 0, WindowWidth, WindowHeight);
  PolarCoordinatesLookAt(mouseXDis, mouseXAngle, mouseYAngle, 0.0, 0.0, 0.0);
 
  //----------------------------------------------

  Ground();

  glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可
}
//----------------------------------------------------
// 大地の描画
//----------------------------------------------------
void Ground(void) {
    double ground_max_x = 300.0;
    double ground_max_y = 300.0;
    glColor3d(0.8, 0.8, 0.8);  // 大地の色
    glBegin(GL_LINES);
    for(double ly = -ground_max_y ;ly <= ground_max_y; ly+=20.0){
      glVertex3d(-ground_max_x, ly,0);
      glVertex3d(ground_max_x, ly,0);
    }
    for(double lx = -ground_max_x ;lx <= ground_max_x; lx+=20.0){
      glVertex3d(lx, ground_max_y,0);
      glVertex3d(lx, -ground_max_y,0);
    }
    glEnd();
}

void myMouseMotion(int x, int y){
	int xdis, ydis;

	switch(mouseFlag){
	case 0x100: //GLUT_LEFT_BUTTON
		xdis = x - mouseXStart;
		ydis = y - mouseYStart;

		mouseXAngle -= (double)xdis * 0.002;
		mouseYAngle -= (double)ydis * 0.002;
		break;

	case 0x001: //GLUT_RIGHT_BUTTON
		xdis = x - mouseXStart;

		mouseXDis += (double)xdis * 0.002;
		break;
	}

	mouseXStart = x;
	mouseYStart = y;
}

void myMouseFunc(int button, int state, int x, int y){

	if(state == GLUT_DOWN ){
		switch(button){
		case GLUT_LEFT_BUTTON:
			mouseXStart = x;
			mouseYStart = y;
			mouseFlag = 0x100;
			break;
		
		case GLUT_RIGHT_BUTTON:
			mouseXStart = x;
			mouseYStart = y;
			mouseFlag = 0x001;
			break;

		default:
			break;
		}
	}else{
		mouseFlag = 0x000;
	}
}


Re: エラー修正お願いします。

Posted: 2011年10月29日(土) 00:09
by softya(ソフト屋)
こちらはお手伝いが基本ですので、アイデアやヒントを出すことは出来ますが作成するのはご本人です。

●「カーソルキーで視点の場所を平行移動出来る関数」
キーボードの取り扱い。
http://www.wakayama-u.ac.jp/~tokoi/open ... t.html#7.3

●「中クリックで拡大縮小出来る関数」
マウスボタンをクリックする
http://www.wakayama-u.ac.jp/~tokoi/open ... t.html#7.1

Re: エラー修正お願いします。

Posted: 2011年10月29日(土) 00:47
by box
Ryo さんが書きました:

コード:

void PolarCoordinatesLookAt(void);
void PolarCoordinatesLookAt(double r, double theta, double phi, double cx, double cy, double cz){
プロトタイプ宣言と実体定義とで引数の並びが食い違っている点が大いに気になりますが、
まあ、自己解決したと書かれているのですから、たいしたことではなかったのでしょうね。

Re: エラー修正お願いします。

Posted: 2011年10月29日(土) 01:32
by Ryo
「マウスクリック」で視点の向き、「i」でズームイン、「o」でズームアウト、「a」でボール作成までは行きました。
ですが、なぜかボールが思うように動いてくれません。反発係数と重力加速度を組み込みたいのと(組み込んでいるはず?)、デバックで「fstream::open() failed」と出てしまうのですが、どうしてでしょうか?

コード:

 

#include <math.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include <direct.h>
#include <time.h>
#include <GL/glut.h>
#include <GL/gl_material.h>
#include <GL/gl_screenshot.h>
using namespace std;
double PI = acos(-1.0);

//////////////////////////////////////////////////////////////////////////
// 変数の定義
//////////////////////////////////////////////////////////////////////////
#define _BITMAP 0 //アニメーション作成用ビットマップの保存 0:しない 1:する

//--------------------------------------------------------
// 仮想物理実験室変数の定義
//--------------------------------------------------------
double t = 0.0;  //時刻
double dt= 0.01; //時間刻み
int tn = 0;      //ステップ数
//--------------------------------------------------------
// OpenGL用変数定義
//--------------------------------------------------------
//////////////////////////////////////////
// ウィンドウ生成用
int WindowPositionX = 200;                         //生成するウィンドウ位置のX座標
int WindowPositionY = 200;                         //生成するウィンドウ位置のY座標
int WindowWidth     = 512;                         //生成するウィンドウの幅
int WindowHeight    = 512;                         //生成するウィンドウの高さ
char WindowTitle[]  = "仮想物理実験室(ver 1.0)";   //ウィンドウのタイトル
bool _Bitmap = true; 

//////////////////////////////////////////
// アニメーション用 ビットマップ保存
gl_screenshot gs; //「gl_screenshot」クラスのインスタンス「gs」を宣言

struct {
  double x, y, z;
  double vx, vy, vz;
}p[100];
int pn = 0;
double ax = 0.0 , ay = 0.0 , az = -2.0;
double vx = 5.0 , vy = 10.0 , vz = 20.0; 
double hanpatu = 0.9;

/////////////////////////////////////////
// 床描画用
static GLfloat floor_planar[4];
static GLfloat floor_s = 50.0f; //床の広さ(1辺=2.0*floor_s)
static GLfloat pM[16];
static GLfloat LightPosition[4] = { -10, -20, 70, 1 }; //光源の位置
typedef struct _QUADS_VERTEX{
 GLfloat v0[3];
 GLfloat v1[3];
 GLfloat v2[3];
 GLfloat v3[3];
}QUADS_VERTEX;
static QUADS_VERTEX floor_v = {
 {  floor_s,  floor_s, 0.0f },
 { -floor_s,  floor_s, 0.0f },
 { -floor_s, -floor_s, 0.0f },
 {  floor_s, -floor_s, 0.0f },
};
void findPlane(GLfloat plane[4], GLfloat v0[3], GLfloat v1[3], GLfloat v2[3]);
void DrawFloor(bool bTexture);

//////////////////////////////////////////
// マウスドラッグ用
int cx, cy;                                             // ドラッグ開始位置
double sx, sy;                                          // マウスの絶対位置→ウィンドウ内での相対位置の換算係数
double cq[4] = { 1.0, 0.0, 0.0, 0.0 };                  // 回転の初期値 (クォータニオン)
double tq[4];                                           // ドラッグ中の回転 (クォータニオン)
double rt[16];                                          // 回転の変換行列
unsigned int listNumber;
float camera_z_pos =200.0;

//////////////////////////////////////////
// 文字描画用
int text_list;
char t_char[20];
char t_char2[20];
void DRAW_STRING(int x, int y, char *string, void *font = GLUT_BITMAP_TIMES_ROMAN_24);
void DISPLAY_TEXT(int x, int y, char *string);

//--------------------------------------------------------
// 回転用
//--------------------------------------------------------
void qmul(double r[], const double p[], const double q[]);
void qrot(double r[], double q[]);

//--------------------------------------------------------
// 関数のプロトタイプ
//--------------------------------------------------------
//////////////////////////////////////////
// メイン関数用
void Initialize(void);
void Display(void);
void Idle(void);
void Keyboard(unsigned char key, int x, int y);
void mouse_motion(int x, int y);
void mouse_on(int button, int state, int x, int y);
void mouse_wheel(float);
//////////////////////////////////////////
// 描画用
void Calculate(void);      //計算
void DrawStructure(void);  //描画
void Ground(void);         //大地の描画
//////////////////////////////////////////
// 影描画用
void shadowMatrix(GLfloat *m, GLfloat plane[4],  GLfloat light[4]);
void DrawShadow(void);

//--------------------------------------------------------
// メイン関数
//--------------------------------------------------------
int main(int argc, char *argv[]){
 srand((unsigned)time(NULL));
#if _BITMAP
 _mkdir("bitmap"); //bmpファイル保存用のフォルダの作成
#endif
 glutInit(&argc, argv);                                     //環境の初期化
 glutInitWindowPosition(WindowPositionX, WindowPositionY);  //ウィンドウの位置の指定
 glutInitWindowSize(WindowWidth, WindowHeight);             //ウィンドウサイズの指定
 glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); //ディスプレイモードの指定
 glutCreateWindow(WindowTitle);                             //ウィンドウの作成
 glutDisplayFunc(Display);                                  //描画時に呼び出される関数を指定する(関数名:Display)
 glutMouseFunc(mouse_on);                                   //マウスクリック時に呼び出される関数
 glutMotionFunc(mouse_motion);                              //マウスドラッグ解除時に呼び出される関数
 glutKeyboardFunc(Keyboard);                                //キーボード入力時に呼び出される関数を指定する(関数名:Keyboard)
 glutIdleFunc(Idle);                                        //プログラムアイドル状態時に呼び出される関数
 Initialize();                                              //初期設定の関数を呼び出す
 glutMainLoop();
 return 0;
}
//--------------------------------------------------------
// 初期設定の関数
//--------------------------------------------------------
void Initialize(void){
 glClearColor(1.0, 1.0, 1.0, 1.0); //背景色
 glEnable( GL_DEPTH_TEST ); //デプスバッファを使用:glutInitDisplayMode() で GLUT_DEPTH を指定する
 glDepthFunc( GL_LEQUAL );
 glClearDepth( 1.0 );
 //////////////////////////////////////////
 // ディスプレイリストを作成
 listNumber = glGenLists(1);
 glNewList( listNumber, GL_COMPILE );
 glEndList();
 //////////////////////////////////////////
 // マウスポインタ位置のウィンドウ内の相対的位置への換算用
 sx = 1.0 / (double)WindowWidth;
 sy = 1.0 / (double)WindowHeight;
 // 回転行列の初期化
 qrot(rt, cq);
 //////////////////////////////////////////
 // 床
 findPlane( floor_planar,
       floor_v.v0,
       floor_v.v1,
       floor_v.v2 );
 //////////////////////////////////////////
 //透視変換行列の設定
 glMatrixMode(GL_PROJECTION);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
 glLoadIdentity();//行列の初期化
 gluPerspective(30.0, (double)WindowWidth/(double)WindowHeight, 0.1, 1000.0); //透視投影法の視体積gluPerspactive(th, w/h, near, far);

}
//--------------------------------------------------------
// 描画の関数
//--------------------------------------------------------
void Display(void) {
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
 //////////////////////////////////////////
 //モデルビュー変換行列の設定
 glMatrixMode(GL_MODELVIEW);//行列モードの設定(GL_PROJECTION : 透視変換行列の設定、GL_MODELVIEW:モデルビュー変換行列)
 glLoadIdentity();//行列の初期化
 glViewport(0, 0, WindowWidth, WindowHeight);

 //////////////////////////////////////////
 //視点の設定
 gluLookAt(
      0.0,  0.0,  camera_z_pos, // 視点の位置x,y,z;
      0.0,  0.0,  0.0,   // 視界の中心位置の参照点座標x,y,z
      0.0,  1.0,  0.0 ) ;  //視界の上方向のベクトルx,y,z

 //////////////////////////////////////////
 //ステンシルバッファクリア値の設定
 glClearStencil( 0 );
 glCullFace( GL_BACK );
 glEnable( GL_CULL_FACE );
 glEnable( GL_AUTO_NORMAL );
 glEnable( GL_NORMALIZE );

 //////////////////////////////////////////
 // 平面射影行列の算出
 shadowMatrix(pM,floor_planar,LightPosition);

 //////////////////////////////////////////
 // 回転
 glMultMatrixd(rt);

 //////////////////////////////////////////
 // 光源ON
 glEnable( GL_LIGHTING );
 glEnable( GL_LIGHT0 );
 glLightfv( GL_LIGHT0,GL_POSITION,LightPosition );

 //////////////////////////////////////////
 // 描画
 glPushMatrix();
   Calculate();     //計算
   DrawStructure(); //物体
   DrawShadow();    //影
 glPopMatrix();

 //////////////////////////////////////////
 //陰影OFF
 glDisable(GL_AUTO_NORMAL);
 glDisable(GL_NORMALIZE);
 glDisable(GL_LIGHTING);

 Ground(); // 地面の描画

if(_Bitmap){
    ostringstream fname;
    int tt = tn +10000;
    fname  << "bitmap/" << tt << ".bmp" ;//出力ファイル名
    string name = fname.str();
    gs.screenshot(name.c_str(), 24);
  }
  tn++ ;

 //////////////////////////////////////////
 //文字の描画
 strcpy_s(t_char2, "t = ");
 sprintf_s(t_char, "%5.2f", t);
 strcat_s(t_char2, t_char);
 DISPLAY_TEXT(5, 95, t_char2  );

 //////////////////////////////////////////
 //ビットマップの保存
 #if _BITMAP
   ostringstream fname;
   int tt = tn +10000;
   fname  << "bitmap/" << tt << ".bmp" ;//出力ファイル名
   string name = fname.str();
   gs.screenshot(name.c_str(), 24);
 #endif

 glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可
}
//--------------------------------------------------------
// 計算と物体の描画
//--------------------------------------------------------
void Calculate(){
  t = dt * double(tn);
  tn++;
}
void DrawStructure(){
  for(int i=1; i<=pn; i++){
    p[i].vx += ax * dt;
    p[i].vy += ay * dt;
    p[i].vz += az * dt;
    p[i].x += p[i].vx * dt;
    p[i].y += p[i].vy * dt;
    p[i].z += p[i].vz * dt;
    if(p[i].z < 4){
      p[i].z = 4.0;
      p[i].vz = -hanpatu * p[i].vz;
    }
    glPushMatrix();
    glMaterialfv(GL_FRONT, GL_AMBIENT, ms_ruby.ambient);
    glMaterialfv(GL_FRONT, GL_DIFFUSE, ms_ruby.diffuse);
    glMaterialfv(GL_FRONT, GL_SPECULAR, ms_ruby.specular);
    glMaterialfv(GL_FRONT, GL_SHININESS, &ms_ruby.shininess);
    glTranslated(p[i].x , p[i].y , p[i].z );//平行移動値の設定
    glutSolidSphere(4.0, 20, 20);//引数:(半径, Z軸まわりの分割数, Z軸に沿った分割数)
    glPopMatrix();
  }
}
//--------------------------------------------------------
// 大地の描画
//--------------------------------------------------------
void Ground(void) {
   double ground_max_x = 300.0;
   double ground_max_y = 300.0;
   glColor3d(0.8, 0.8, 0.8);  // 大地の色
   glBegin(GL_LINES);
   for(double ly = -ground_max_y ;ly <= ground_max_y; ly+=10.0){
     glVertex3d(-ground_max_x, ly, -1.1);
     glVertex3d(ground_max_x, ly , -1.1);
   }
   for(double lx = -ground_max_x ;lx <= ground_max_x; lx+=10.0){
     glVertex3d(lx, ground_max_y , -1.1);
     glVertex3d(lx, -ground_max_y, -1.1);
   }
   glEnd();
}
//--------------------------------------------------------
// アイドル時に呼び出される関数
//--------------------------------------------------------
void Idle(){
 glutPostRedisplay(); //glutDisplayFunc()を1回実行する
}
//--------------------------------------------------------
// キーボード入力時に呼び出される関数
//--------------------------------------------------------
void Keyboard(unsigned char key, int x, int y){
 switch ( key )
 {
 case 'a':
    pn++;
    p[pn].x = 0.0;
    p[pn].y = 0.0;
    p[pn].z = 4.0;
    p[pn].vx = vx * ( (double)rand()/(double)RAND_MAX - (double)rand()/(double)RAND_MAX );
    p[pn].vy = vy * ( (double)rand()/(double)RAND_MAX );
    p[pn].vz = vz * ( (double)rand()/(double)RAND_MAX );

    break;
 case 'i':
    camera_z_pos -= 10.0;
    break;
 case 'o':
    camera_z_pos += 10.0;
    break;

 default:
   break;
 }
 cout << camera_z_pos << endl;
}
//--------------------------------------------------------
// マウスドラッグ時
//--------------------------------------------------------
void mouse_motion(int x, int y){
 double dx, dy, a;

 // マウスポインタの位置のドラッグ開始位置からの変位
 dx = (x - cx) * sx;
 dy = (y - cy) * sy;

 // マウスポインタの位置のドラッグ開始位置からの距離
 a = sqrt(dx * dx + dy * dy);

 if( a != 0.0 )
 {
   // マウスのドラッグに伴う回転のクォータニオン dq を求める
   double ar = a * 2.0 * PI * 0.5;
   double as = sin(ar) / a;
   double dq[4] = { cos(ar), dy * as, dx * as, 0.0 };

   // 回転の初期値 cq に dq を掛けて回転を合成
   qmul(tq, dq, cq);

   // クォータニオンから回転の変換行列を求める
   qrot(rt, tq);
 }
}
//--------------------------------------------------------
// マウスクリック時
//--------------------------------------------------------
void mouse_on(int button, int state, int x, int y){
 switch (button) {
 case 0:
   switch (state) {
   case 0:
     // ドラッグ開始点を記録
     cx = x;
     cy = y;
     break;
   case 1:
     // 回転の保存
     cq[0] = tq[0];
     cq[1] = tq[1];
     cq[2] = tq[2];
     cq[3] = tq[3];
     break;
   default:
     break;
   }
   break;
 default:
   break;
 }
 cout << x << " " << y<<endl;
}
//--------------------------------------------------------
// 床平面の方程式と行列の計算
//--------------------------------------------------------
void findPlane(
 GLfloat plane[4],  // 作成する平面方程式の係数
 GLfloat v0[3],    // 頂点1
 GLfloat v1[3],    // 頂点2
 GLfloat v2[3])    // 頂点3
{
 GLfloat vec0[3], vec1[3];

 // Need 2 vectors to find cross product.
 vec0[0] = v1[0] - v0[0];
 vec0[1] = v1[1] - v0[1];
 vec0[2] = v1[2] - v0[2];

 vec1[0] = v2[0] - v0[0];
 vec1[1] = v2[1] - v0[1];
 vec1[2] = v2[2] - v0[2];

 // find cross product to get A, B, and C of plane equation
 plane[0] = vec0[1] * vec1[2] - vec0[2] * vec1[1];
 plane[1] = -(vec0[0] * vec1[2] - vec0[2] * vec1[0]);
 plane[2] = vec0[0] * vec1[1] - vec0[1] * vec1[0];

 plane[3] = -(plane[0] * v0[0] + plane[1] * v0[1] + plane[2] * v0[2]);
}
void shadowMatrix(
 GLfloat *m,      // 作成する行列のポインタ
 GLfloat plane[4],  // 射影する表面の平面方程式の係数
 GLfloat light[4])  // 光源の同時座標値
{
 GLfloat dot;

 // Find dot product between light position vector and ground plane normal.
 dot = plane[0] * light[0] +
     plane[1] * light[1] +
     plane[2] * light[2] +
     plane[3] * light[3];

 m[0]  = dot - light[0] * plane[0];
 m[4]  = 0.f - light[0] * plane[1];
 m[8]  = 0.f - light[0] * plane[2];
 m[12] = 0.f - light[0] * plane[3];

 m[1]  = 0.f - light[1] * plane[0];
 m[5]  = dot - light[1] * plane[1];
 m[9]  = 0.f - light[1] * plane[2];
 m[13] = 0.f - light[1] * plane[3];

 m[2]  = 0.f - light[2] * plane[0];
 m[6]  = 0.f - light[2] * plane[1];
 m[10] = dot - light[2] * plane[2];
 m[14] = 0.f - light[2] * plane[3];

 m[3]  = 0.f - light[3] * plane[0];
 m[7]  = 0.f - light[3] * plane[1];
 m[11] = 0.f - light[3] * plane[2];
 m[15] = dot - light[3] * plane[3];
}
//--------------------------------------------------------
// 床の描画と影の描画
//--------------------------------------------------------
void DrawFloor(bool bTexture){
 if( bTexture ){
 // 床にテクスチャを使う時はココで設定する
 //  glBindTexture( GL_TEXTURE_2D, );

   glDisable(GL_LIGHTING);
   glBegin(GL_QUADS);
 //    glTexCoord2f( , );
     glVertex3fv( floor_v.v0 );
 //    glTexCoord2f( , );
     glVertex3fv( floor_v.v1 );
 //    glTexCoord2f( , );
     glVertex3fv( floor_v.v2 );
 //    glTexCoord2f( , );
     glVertex3fv( floor_v.v3 );
   glEnd();
   glEnable(GL_LIGHTING);
 }else{
   glDisable(GL_LIGHTING);
   glBegin(GL_QUADS);
     glVertex3fv( floor_v.v0 );
     glVertex3fv( floor_v.v1 );
     glVertex3fv( floor_v.v2 );
     glVertex3fv( floor_v.v3 );
   glEnd();
   glEnable(GL_LIGHTING);
 }
}
void DrawShadow(void){
 /////////////////////////////////////////////
 //床のステンシルを付ける
 glEnable(GL_STENCIL_TEST);
 glStencilFunc( GL_ALWAYS, 1, ~0);
 //これから描画するもののステンシル値にすべて1タグをつける
 glStencilOp(GL_KEEP,GL_KEEP ,GL_REPLACE);
 glColor4f(0.7f, 0.4f, 0.0f, 1.0f);
 DrawFloor( true );//床の描画

 /////////////////////////////////////////////
 //カラー・デプスバッファマスクをセットする
 //これで以下の内容のピクセルの色の値は、書き込まれない。
 glColorMask(0,0,0,0);
 glDepthMask(0);
 /////////////////////////////////////////////
 //床にオブジェクトの影のステンシルを付ける
 glEnable(GL_STENCIL_TEST);
 glStencilFunc( GL_EQUAL, 1, ~0);
 //これから描画するもののステンシル値にすべて1タグをつける
 glStencilOp(GL_KEEP,GL_KEEP ,GL_INCR);
 glDisable(GL_DEPTH_TEST);
 glPushMatrix();
   glMultMatrixf(pM);
   DrawStructure();
 glPopMatrix();
 glEnable(GL_DEPTH_TEST);

 /////////////////////////////////////////////
 //ビットマスクを解除
 glColorMask(1,1,1,1);
 glDepthMask(1);

 /////////////////////////////////////////////
 //影をつける
 glStencilFunc( GL_EQUAL, 2, ~0 );
 glEnable(GL_BLEND);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   glColor4f(0.1f, 0.1f, 0.1f, 0.5f);
   glDisable(GL_DEPTH_TEST);
     DrawFloor( false );//床の描画
   glEnable(GL_DEPTH_TEST);
   glDisable(GL_BLEND);
 glDisable(GL_STENCIL_TEST);

}

//--------------------------------------------------------
// 文字描画
//--------------------------------------------------------
void DISPLAY_TEXT(int x, int y, char *string){
glDisable(GL_LIGHTING);
glDisable(GL_LIGHT0);

 glPushAttrib(GL_ENABLE_BIT);
 glMatrixMode(GL_PROJECTION);
 glPushMatrix();
 glLoadIdentity();
 gluOrtho2D(0, 100, 0, 100);
 glMatrixMode(GL_MODELVIEW);
 glPushMatrix();
 glLoadIdentity();
 glColor3f(0.0, 0.0, 0.0);
 glCallList(text_list);
 glPopMatrix();
 glMatrixMode(GL_PROJECTION);
 glPopMatrix();
 glPopAttrib();
 glMatrixMode(GL_MODELVIEW);
 text_list=glGenLists(1);
 glNewList(text_list,GL_COMPILE);

 DRAW_STRING(x, y, string , GLUT_BITMAP_TIMES_ROMAN_24);
 glEndList();

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
}
void DRAW_STRING(int x, int y, char *string, void *font){
 int len, i;
 glRasterPos2f(x, y);
 len = (int) strlen(string);
 for (i = 0; i < len; i++){
   glutBitmapCharacter(font, string[i]);
 }
}
//--------------------------------------------------------
// マウスドラッグによる回転
//--------------------------------------------------------
//////////////////////////////////////////////
// クォータニオンの積 r <- p x q
static void qmul(double r[], const double p[], const double q[])
{
 r[0] = p[0] * q[0] - p[1] * q[1] - p[2] * q[2] - p[3] * q[3];
 r[1] = p[0] * q[1] + p[1] * q[0] + p[2] * q[3] - p[3] * q[2];
 r[2] = p[0] * q[2] - p[1] * q[3] + p[2] * q[0] + p[3] * q[1];
 r[3] = p[0] * q[3] + p[1] * q[2] - p[2] * q[1] + p[3] * q[0];
}
/////////////////////////////////////////////
// 回転の変換行列 r <- クォータニオン q
static void qrot(double r[], double q[]){
 double x2 = q[1] * q[1] * 2.0;
 double y2 = q[2] * q[2] * 2.0;
 double z2 = q[3] * q[3] * 2.0;
 double xy = q[1] * q[2] * 2.0;
 double yz = q[2] * q[3] * 2.0;
 double zx = q[3] * q[1] * 2.0;
 double xw = q[1] * q[0] * 2.0;
 double yw = q[2] * q[0] * 2.0;
 double zw = q[3] * q[0] * 2.0;

 r[ 0] = 1.0 - y2 - z2;
 r[ 1] = xy + zw;
 r[ 2] = zx - yw;
 r[ 4] = xy - zw;
 r[ 5] = 1.0 - z2 - x2;
 r[ 6] = yz + xw;
 r[ 8] = zx + yw;
 r[ 9] = yz - xw;
 r[10] = 1.0 - x2 - y2;
 r[ 3] = r[ 7] = r[11] = r[12] = r[13] = r[14] = 0.0;
 r[15] = 1.0;
}


Re: エラー修正お願いします。

Posted: 2011年10月29日(土) 10:55
by softya(ソフト屋)
ここのサイトの情報を使っていますね?
必要な情報はすべて提供してくださいね。Ryoさんの知っていることをみんなが知っているとは思わないほうが良いですよ。
「VisualC++ と OpenGL を利用した仮想物理実験室仮想物理実験室の構築 (ver1.0)」
http://www.natural-science.or.jp/articl ... 225032.php

ところで、自分で組んでいるんじゃなくてサイトや本を参考にされていますね?
よく分かっていないなら、そこの所をちゃんと書いてくださいね。

>デバックで「fstream::open() failed」と出てしまうのですが、どうしてでしょうか?
プログラムでそうなっているにも関わらず環境が不十分だからです。思い当たる部分は無いのでしょうか?

Re: エラー修正お願いします。

Posted: 2011年10月29日(土) 12:16
by Ryo
>プログラムでそうなっているにも関わらず環境が不十分だからです。思い当たる部分は無いのでしょうか?

「VisualC++ と OpenGL を利用した仮想物理実験室仮想物理実験室の構築 (ver1.0)」
http://www.natural-science.or.jp/articl ... 225032.php

↑は何もエラーなく作動しますが、
このプログラムに自分で付け加えたりしたら、
デバックで「fstream::open() failed」と出てしまうのです。。。
だから、自分で付け加えたところに問題があると思います。

Re: エラー修正お願いします。

Posted: 2011年10月29日(土) 14:16
by softya(ソフト屋)
このエラーは、本当に単なるオープンエラーです。
C++のfstreamやファイル作成の動作を理解していれば、原因は自ずと分かるはずですが何が原因か本当に思い当たりませんか?
自分でファイル名や書きだすディレクトリを指定している事になるのですが。