前回は、GLUTをクラス化して使用するCGLUT.hをやりました。今回からBCCSkeltonによるプログラミング部分になります。
いつものことですが(と言いつつ、最近はとんとBCCSkeltonで書いていなかったのでお分かりではないかもしれませんが)、説明が簡単な順に、
(1)Glut_BCC.cpp-メインのエントリーポイントがあるファイル。
(2)Glut_BCC.h-ウィンドウやダイアログのクラス定義やメンバー関数の宣言があるファイル。
をやって、最後に
(3)Glut_BCCProc.h-メンバー関数の実装を行うファイル。
(4)Glut_CBFunc.h-GLUT用のコールバック関数を記述しているファイル。
をやろうかと思います。
【Glut_BCC.cpp】
//////////////////////////////////////////
// Glut_BCC.cpp
//Copyright (c) 10/25/2021 by BCCSkelton
//////////////////////////////////////////
#include "Glut_BCC.h"
#include "Glut_CBFunc.h" //GLUT外部コールバック関数ヘッダー
#include "Glut_BCCProc.h"
////////////////
// WinMain関数
////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
//2重起動防止
if(!Glut_BCC.IsOnlyOne()) {
//ここに2重起動時の処理を書く
HWND hWnd = FindWindow("MainWnd", "Glut_BCC");
if(IsIconic(hWnd))
ShowWindow(hWnd, SW_RESTORE);
SetForegroundWindow(hWnd);
return 0L;
}
//モードレスダイアログを作成Create(hParent, DlgName, DlgProc);
if(!Glut_BCC.Create(NULL, hInstance, "IDD_GLUT", ModelessProc))
return 0L;
//メッセージループに入る
return Glut_BCC.Loop();
}
//解説:今回のプログラムは(普通のSDIウィンドウのような)モードレスダイアログ(注)で書いていますが、↑は典型的なエントリーポイントのWinMain関数です。ダイアログを作成してメッセージループに入る2行だけですが、本当はもっと長々としたプログラムが(BCCSkelton.hの中のコードで)動いています。
//注:メッセージボックスのように、呼び出したウィンドウをフリーズさせることなく、一緒に仲良く機能するダイアログ。
【Glut_BCC.h】
/////////////////////////////////////////////////////////////////////////////
// Glut_BCC.h
// Copyright (c) 10/26/2021 by BCCSkelton
// 参考:https://mitani.cs.tsukuba.ac.jp/lecture/old2015/cg/03/03_slides.pdf
/////////////////////////////////////////////////////////////////////////////
#include <stdio.h> //単精度実数を文字列化する為のsprintf関数を使う為に追加しました。
//BCCSkeltonのヘッダー-これに必要なヘッダーが入っている
#include "BCCSkelton.h"
//リソースIDのヘッダー
#include "ResGlut_BCC.h"
//CGLクラスのヘッダー
#include "CGLUT.h"
/////////////////////////////////////////////////////////////////////
//CMyWndクラスをCDLGクラスから派生させ、メッセージ用の関数を宣言する
/////////////////////////////////////////////////////////////////////
class CMyWnd : public CDLG //解説:コメントに書かれている通り、BCCSkeltonのCDLGクラスから派生させて今回のダイアログを作ります。
{
public: //以下はコールバック関数マクロと関連している
//2重起動防止用のMutex用ID名称
CMyWnd(char* UName) : CDLG(UName) {}
//メニュー項目、ダイアログコントロール関連(解説:ここで宣言している関数をProcファイルで実装します。)
bool OnSelected(WPARAM);
bool OnSelCol();
bool OnCreate();
bool OnSetLA();
bool OnSelProj(WPARAM);
bool OnSetProj();
bool OnRotate();
bool OnEndXChanged(WPARAM);
bool OnEndYChanged(WPARAM);
bool OnEndZChanged(WPARAM);
bool OnLight();
bool OnLightXChanged(WPARAM);
bool OnLightYChanged(WPARAM);
bool OnLightZChanged(WPARAM);
bool OnSelLight(WPARAM);
bool OnIdok();
//ウィンドウメッセージ関連
bool OnInit(WPARAM, LPARAM);
bool OnHScroll(WPARAM, LPARAM); //解説:普段は使わないWM_HSCROLLですが、スライダーのメッセージを受けるために使います。
bool OnClose(WPARAM, LPARAM);
bool OnDestroy(WPARAM, LPARAM);
//ユーザー定義関数
GLdouble GetDouble(UINT); //テキストボックスからGLDouble値を取得する
void SetControlState(int); //解説:操作状態でコントロールを有効、無効にする必要がある為
};
////////////////////////////////////////////////////////////////////////
//派生させたCMyWndクラスのインスタンスとコールバック関数(マクロ)の作成
//主ウィンドウはダイアログと違い、コールバック関数は一つしか作れない
////////////////////////////////////////////////////////////////////////
CMyWnd Glut_BCC("Glut_BCC"); //ウィンドウクラスインスタンスの生成(解説:この変数宣言で実際に↑のクラスの実体を作ります。)
BEGIN_MODELESSDLGMSG(ModelessProc, Glut_BCC) //コールバック関数名は主ウィンドウの場合ModelessProcにしている(解説:この部分はマクロでウィンドウメッセージ処理を行うコールバック関数に変わります。)
//メニュー項目、ダイアログコントロール関連(解説:↑の関数と関連しています。)
ON_COMMAND(Glut_BCC, IDC_SELOBJ, OnSelected(wParam))
ON_COMMAND(Glut_BCC, IDC_COLOR, OnSelCol())
ON_COMMAND(Glut_BCC, IDC_CREATE, OnCreate())
ON_COMMAND(Glut_BCC, IDC_SETLA, OnSetLA())
ON_COMMAND(Glut_BCC, IDC_SELPROJ, OnSelProj(wParam))
ON_COMMAND(Glut_BCC, IDC_SETPROJ, OnSetProj())
ON_COMMAND(Glut_BCC, IDC_ROTATE, OnRotate())
ON_COMMAND(Glut_BCC, IDC_ENDX, OnEndXChanged(wParam))
ON_COMMAND(Glut_BCC, IDC_ENDY, OnEndYChanged(wParam))
ON_COMMAND(Glut_BCC, IDC_ENDZ, OnEndZChanged(wParam))
ON_COMMAND(Glut_BCC, IDC_LIGHT, OnLight())
ON_COMMAND(Glut_BCC, IDC_LIGHTX, OnLightXChanged(wParam))
ON_COMMAND(Glut_BCC, IDC_LIGHTY, OnLightYChanged(wParam))
ON_COMMAND(Glut_BCC, IDC_LIGHTZ, OnLightZChanged(wParam))
ON_COMMAND(Glut_BCC, IDC_SELLIGHT, OnSelLight(wParam))
ON_COMMAND(Glut_BCC, IDOK, OnIdok())
//ウィンドウメッセージ関連(解説:↑の関数と関連しています。)
//自動的にダイアログ作成時にOnInit()、終了時にOnClose()を呼びます
ON_HSCROLL(Glut_BCC)
ON_DESTROY(Glut_BCC)
END_DLGMSG
/////////////////////////////
//Glutクラス(CGL)外部変数
/////////////////////////////
CGLUT gl; //解説:前回作ったCGLUTクラスの実体(インスタンス)を、外部変数として作ります。
/////////////////////////////
//GLUT描画オブジェクト名配列(解説:18の基本図形の名称を配列化しています。)
/////////////////////////////
char* g_ObjName[18] = { "ワイアーティーポット", "ソリッドティーポット",
"ワイアー直方体", "ソリッド直方体",
"ワイアー球体", "ソリッド球体",
"ワイアー円錐", "ソリッド円錐",
"ワイアー円環", "ソリッド円環",
"ワイアー四面体", "ソリッド四面体",
"ワイアー八面体", "ソリッド八面体",
"ワイアー十二面体", "ソリッド十二面体",
"ワイアー二十面体", "ソリッド二十面体"};
/////////////////////
//GLUT投影方法名配列(解説:投影方法を配列化しています。)
/////////////////////
char* g_ProjName[3] = {"透視投影(gluPerspective)", "透視投影(glFrustum)", "並行投影(glOrtho)"};
////////////////////
//glLight照光名配列(解説:ライトの光属性を配列化しています。)
////////////////////
char* g_LightName[3] = {"環境光(ambient)", "拡散光(diffuse)", "鏡面光(specular)"};
//外部変数(解説:実際にプログラムで使う外部変数です。Glut_BCCProc.hファイルやGlut_CBFunc.hファイルで使います。)
bool g_rotate = TRUE; //常時回転フラグ
bool g_light = FALSE; //Light使用フラグ
int g_prjctrls = 0; //投影方式ID(0-gluPerspective、1-glFrustum、2-glOrtho)
GLdouble g_Red = 1.0, g_Green = 0, g_Blue = 0, g_Alpha = 1.0; //描画色
GLdouble g_r = 0.0; //回転角度
GLdouble g_x = 0.0, g_y = 1.0, g_z = 0.0; //回転軸(起点(0, 0, 0))の軸端座標
GLfloat g_lightpos[4] = {50.0, 50.0, 50.0, 1.0}; //光源の座標(初期値(50.0, 50.0, 0.0)(解説:最初これをダイアログから変えるつもりでしたが、余りに煩瑣なので止めました。)
int g_selected = 0; //ライト、光属性とRGBA強度配列用添字
const GLenum g_lightno[] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2}; //ライト識別子(解説:本プログラムでは3つ使用)
/*
const GLenum m_lightno[] = {GL_LIGHT0, GL_LIGHT1, GL_LIGHT2, //ライト識別子(解説:8つ迄使えるので拡張性の為に。)
GL_LIGHT3, GL_LIGHT4, GL_LIGHT5,
GL_LIGHT6, GL_LIGHT7};
*/
const GLenum g_kind[] = {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR,}; //光属性(GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR)
/*
const GLenum m_lightparam[] = { //光属性(GL_AMBIENT、GL_DIFFUSE、GL_SPECULAR)
GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR,
GL_POSITION, GL_SPOT_DIRECTION,
GL_SPOT_EXPONENT, GL_SPOT_CUTOFF,
GL_CONSTANT_ATTENUATIO, GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION};
*/ //解説:これも拡張性の為に、です。今回は使っていません。
const GLfloat g_lightcolor[3][4] = {{1.0, 1.0, 1.0, 1.0}, //RGBA強度(環境光)-GL_LIGHT0
{1.0, 1.0, 1.0, 1.0}, //RGBA強度(拡散光)-GL_LIGHT1
{1.0, 1.0, 1.0, 1.0}}; //RGBA強度(鏡面光)-GL_LIGHT2
//解説:環境光、拡散光、鏡面光の初期値を配列にしています。
/*
const GLfloat g_lightcolor[3][4] = {{0.0, 0.0, 0.0, 0.0}, //RGBA強度(環境光)-GL_LIGHT0
{1.0, 1.0, 1.0, 1.0}, //RGBA強度(拡散光)-GL_LIGHT1
{1.0, 1.0, 1.0, 1.0}}; //RGBA強度(鏡面光)-GL_LIGHT2
*/
/*
const GLfloat g_lightcolor[3][4] = {{0.0, 0.0, 0.0, 1.0}, //RGBA強度(環境光)-GL_LIGHT0
{0.0, 0.0, 0.0, 1.0}, //RGBA強度(拡散光)-GL_LIGHT1
{0.0, 0.0, 0.0, 1.0}}; //RGBA強度(鏡面光)-GL_LIGHT2
*/
/*
const GLfloat g_lightcolor[3][4] = {{0.0, 0.0, 0.0, 1.0}, //RGBA強度(環境光)-GL_LIGHT0
{0.5, 0.5, 0.5, 1.0}, //RGBA強度(拡散光)-GL_LIGHT1
{0.5, 0.5, 0.5, 1.0}}; //RGBA強度(鏡面光)-GL_LIGHT2
*/ //解説:このコメントは開発時に色々な値を試してみた際に又使うかもしれないから、と残したものです。
さて、ここまでで定義や宣言が終わりましたので、その内容をGlut_BCCProc.hとGlut_CBFunc.hのプログラムで実装してゆきましょう。