0001: // ----------------------------------------------------------------------------
0002: //
0003: // main.cpp - GLUT で Cg のサンプルソース
0004: // 
0005: // Copyright (c) 2002 今給黎 隆 (imagire@nify.com)
0006: // All Rights Reserved.
0007: //
0008: // ----------------------------------------------------------------------------
0009: #include <math.h>
0010: #include <stdio.h>
0011: #include <assert.h>
0012: #include <GL/glut.h>
0013: #include <Cg/cg.h>
0014: #include <Cg/cgGL.h>
0015: 
0016: // ---------------------------------------------------------------------------
0017: // オブジェクト
0018: // ---------------------------------------------------------------------------
0019: 
0020: // Cg のオブジェクト
0021: static cgContext     *Context           = NULL; // Cg の実態
0022: static cgProgramIter *ProgramIter       = NULL; // プログラム
0023: static cgBindIter    *ModelViewProjBind = NULL; // 行列
0024: static cgBindIter    *ColorBind         = NULL; // 頂点色
0025: 
0026: static char CGVertProg[] =
0027:  "\n"
0028:  "struct appdata\n"
0029:  " {\n"
0030:  "  float4 position : POSITION;\n"
0031:  "  float3 normal : NORMAL;\n"
0032:  "  float3 color : DIFFUSE;\n"
0033:  " };\n"
0034:  "\n"
0035:  "struct vfconn\n"
0036:  " {\n"
0037:  "  float4 HPOS : POSITION;\n"
0038:  "  float4 COL0 : COLOR0;\n"
0039:  " };\n"
0040:  "\n"
0041:  "vfconn main(appdata IN,\n"
0042:  "            uniform float4x4 ModelViewProj)\n"
0043:  " {\n"
0044:  "  vfconn OUT;\n"
0045:  "\n"
0046:  "  OUT.HPOS = mul(ModelViewProj, IN.position);\n"
0047:  "\n"
0048:  "  OUT.COL0.xyz = IN.color.xyz;\n"
0049:  "  OUT.COL0.w = 1.0;\n"
0050:  "\n"
0051:  "  return OUT;\n"
0052:  " } // main\n";
0053: 
0054: static float r = 0.0f;      // ポリゴンの回転角
0055: 
0056: // ---------------------------------------------------------------------------
0057: // 箱のオブジェクト
0058: // ---------------------------------------------------------------------------
0059: GLfloat CubeNormals[6][3] = 
0060:  {  
0061:   {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
0062:   {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0} 
0063:  };
0064: 
0065: GLint CubeFaces[6][4] = 
0066:  {  
0067:   {0, 1, 2, 3}, {3, 2, 6, 7}, {7, 6, 5, 4},
0068:   {4, 5, 1, 0}, {5, 6, 2, 1}, {7, 4, 0, 3} 
0069:  };
0070: 
0071: GLfloat CubeVertices[8][3];  
0072: 
0073: static void InitializeCube(GLfloat v[8][3])
0074: {
0075:     v[0][0] = v[1][0] = v[2][0] = v[3][0] = -1;
0076:     v[4][0] = v[5][0] = v[6][0] = v[7][0] = 1;
0077:     v[0][1] = v[1][1] = v[4][1] = v[5][1] = -1;
0078:     v[2][1] = v[3][1] = v[6][1] = v[7][1] = 1;
0079:     v[0][2] = v[3][2] = v[4][2] = v[7][2] = 1;
0080:     v[1][2] = v[2][2] = v[5][2] = v[6][2] = -1;
0081: }
0082: #define MATRIX_INDEX(i, j) (j + i * 4)
0083: 
0084: // ---------------------------------------------------------------------------
0085: // 箱の描画
0086: // ---------------------------------------------------------------------------
0087: static void DrawCube(void)
0088: {
0089:     int i;
0090:     cgError Ret;
0091:     
0092:     // イテレータへプログラムを結びつける
0093:     Ret = cgGLBindProgram(ProgramIter);
0094:     assert(Ret == cgNoError);
0095: 
0096:     // 行列を設定する
0097:     if(ModelViewProjBind != NULL) {
0098:         cgGLBindUniformStateMatrix(ProgramIter, 
0099:                                 ModelViewProjBind,
0100:                                 cgGLModelViewProjectionMatrix,
0101:                                 cgGLMatrixIdentity);
0102:     }
0103: 
0104:     // Cg による描画へ切り替え
0105:     cgGLEnableProgramType(cgVertexProfile);
0106: 
0107:     // 箱の描画
0108:     for(i = 0; i < 6; i++) {
0109:         glBegin(GL_QUADS);  // 四角形の描画
0110: 
0111:         glNormal3fv(&CubeNormals[i][0]);                            // 法線
0112:         cgGLBindVarying3f(ProgramIter, ColorBind, 1.0, 0.0, 0.0);   // 頂点色
0113:         glVertex3fv(&CubeVertices[CubeFaces[i][0]][0]);             // 座標
0114: 
0115:         cgGLBindVarying3f(ProgramIter, ColorBind, 0.0, 1.0, 0.0);
0116:         glVertex3fv(&CubeVertices[CubeFaces[i][1]][0]);
0117: 
0118:         cgGLBindVarying3f(ProgramIter, ColorBind, 0.0, 0.0, 1.0);
0119:         glVertex3fv(&CubeVertices[CubeFaces[i][2]][0]);
0120: 
0121:         cgGLBindVarying3f(ProgramIter, ColorBind, 1.0, 1.0, 1.0);
0122:         glVertex3fv(&CubeVertices[CubeFaces[i][3]][0]);
0123:     
0124:         glEnd();    // 四角形終わり
0125:     }
0126:     
0127:     // Cg による描画の終了
0128:     cgGLDisableProgramType(cgVertexProfile);
0129: }
0130: // ---------------------------------------------------------------------------
0131: // 画面描画
0132: // ---------------------------------------------------------------------------
0133: void display(void)
0134: {
0135:     // 画面のクリア
0136:     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
0137: 
0138:     // ビュー行列の設定
0139:     glMatrixMode(GL_MODELVIEW);
0140:     glLoadIdentity();
0141:     gluLookAt(  0.0, 0.0, 5.0,      // 視点
0142:                 0.0, 0.0, 0.0,      // 注目点
0143:                 0.0, 1.0, 0.0);     // 上方向
0144: 
0145:     glPushMatrix();                 // ビュー行列が他のポリゴンでも使えるよう退避
0146: 
0147:     // -----------------------------------------------------------------------
0148:     // 箱の描画
0149:     // -----------------------------------------------------------------------
0150:     glRotatef(  r, 0.0, 1.0, 0.0);  // 回転
0151:     glRotatef( 60, 1.0, 0.0, 0.0);  // 適当に傾ける
0152:     glRotatef(-20, 0.0, 0.0, 1.0);  // 適当に傾ける
0153: 
0154:     DrawCube();
0155: 
0156:     glPopMatrix();                  // ビュー行列に現在の行列を戻す
0157:     glutSwapBuffers();              // 画面の更新の終了
0158: }
0159: // ---------------------------------------------------------------------------
0160: // 画面がリサイズされたとき
0161: // ---------------------------------------------------------------------------
0162: void resize(int w, int h)
0163: {
0164:     // ビューポートの設定
0165:     glViewport(0, 0, w, h);
0166: 
0167:     // 射影行列の設定
0168:     glMatrixMode(GL_PROJECTION);
0169:     glLoadIdentity();
0170:     gluPerspective( 60.0,           // 画角
0171:                     1.0,            // アスペクト比
0172:                     1.0, 10.0);     // 前方面、後方面
0173: }
0174: // ---------------------------------------------------------------------------
0175: // ひまなときに実行される
0176: // ---------------------------------------------------------------------------
0177: void idle()
0178: {
0179:     // ポリゴンの回転
0180:     r = r + 3.0f;
0181:     while (360.0f < r) r -= 360.0f;
0182: 
0183:     glutPostRedisplay();            // 再描画リクエスト
0184: }
0185: // ---------------------------------------------------------------------------
0186: // OpenGL に関する初期化
0187: // ---------------------------------------------------------------------------
0188: static void InitializeGlut(int argc, char *argv[])
0189: {
0190:     // ウィンドウの作成
0191:     glutInitWindowPosition(100, 100);   // 表示位置
0192:     glutInitWindowSize(512, 512);       // サイズ
0193:     glutInit(&argc, argv);              // GLの初期化
0194:     glutInitDisplayMode(GLUT_DOUBLE     // 描画モード
0195:                      | GLUT_RGBA        // wバッファ+RGBA+深度バッファ
0196:                      | GLUT_DEPTH);
0197:     glutCreateWindow(argv[0]);          // ウィンドウの生成
0198: 
0199:     // コールバック関数の設定
0200:     glutDisplayFunc(display);   // 描画関数
0201:     glutReshapeFunc(resize);    // 画面が変形したとき
0202:     glutIdleFunc(idle);         // ひまなとき
0203: 
0204:     // 箱の初期化
0205:     InitializeCube(CubeVertices);
0206: 
0207:     // 一度だけすればいい設定
0208:     glClearColor(0.0, 0.0, 0.3, 0.0);   // 背景色の設定
0209:     glEnable(GL_DEPTH_TEST);            // 深度バッファの使用
0210: }
0211: // ---------------------------------------------------------------------------
0212: // Cgの初期化
0213: // ---------------------------------------------------------------------------
0214: static void InitializeCg()
0215: {
0216:     cgError Ret;
0217:     
0218:     // Cg の作成
0219:     Context = cgCreateContext();
0220:     assert(Context != NULL);
0221: 
0222:     // Cg の作成
0223:     Ret = cgAddProgram(Context, CGVertProg, cgVertexProfile, NULL);
0224:     fprintf(stderr, "LAST LISTING----%s----\n", cgGetLastListing(Context));
0225:     assert(Ret == cgNoError);
0226: 
0227:     // プログラム名でプログラムを結びつける
0228:     ProgramIter = cgProgramByName(Context, "main");
0229:     assert(ProgramIter != NULL);
0230:     
0231:     // ソースの表示
0232:     fprintf(stderr, "---- プログラム はじめ ----\n"
0233:                     "%s"
0234:                     "---- プログラム 終わり ----\n",
0235:     cgGetProgramObjectCode(ProgramIter));
0236: 
0237:     if(ProgramIter != NULL) {
0238:         GLuint ProgId = 1;
0239: 
0240:         Ret = cgGLLoadProgram(ProgramIter, ProgId);
0241:         assert(Ret == cgNoError);
0242:         // 変換行列を結びつける
0243:         ModelViewProjBind = cgGetBindByName(ProgramIter, "ModelViewProj");
0244:         assert(ModelViewProjBind != NULL);
0245:         // 頂点色
0246:         ColorBind = cgGetBindByName(ProgramIter, "IN.color");
0247:         assert(ColorBind != NULL);
0248:     }
0249: }
0250: // ---------------------------------------------------------------------------
0251: // Cg の後片付け
0252: // ---------------------------------------------------------------------------
0253: static void CleanupCg()
0254: {
0255:     if(ModelViewProjBind)cgFreeBindIter(ModelViewProjBind);
0256:     if(ColorBind)cgFreeBindIter(ColorBind);
0257:     cgFreeProgramIter(ProgramIter);
0258:     cgFreeContext(Context);
0259:     cgCleanup();
0260: }
0261: // ---------------------------------------------------------------------------
0262: // メイン関数
0263: // ---------------------------------------------------------------------------
0264: int main(int argc, char *argv[])
0265: {
0266:     InitializeGlut(argc, argv);
0267:     InitializeCg();
0268:   
0269:     glutMainLoop();                     // メインループ
0270: 
0271:     CleanupCg();
0272:     
0273:     return 0;
0274: }