home *** CD-ROM | disk | FTP | other *** search
/ Game Programming in C++ - Start to Finish / GameProgrammingS.iso / tools_install / gDEBugger-2_1_book.msi / GRTeapotApplication.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-09-15  |  60.2 KB  |  1,883 lines

  1. //------------------------------ GRTeapotApplication.cpp ------------------------------
  2.  
  3. // --------------------------------------------------------
  4. //  ⌐ 2004-2005 Graphic Remedy. All Rights Reserved.
  5. // --------------------------------------------------------
  6.  
  7.  
  8. // Standard C:
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12.  
  13. // Win32:
  14. #include <Windows.h>
  15.  
  16. // OpenGL:
  17. #include <GL/gl.h>
  18. #include <GL/glext.h>
  19.  
  20. // Free image:
  21. #include <FreeImage.h>
  22.  
  23. // Local:
  24. #include <res/resource.h>
  25.  
  26.  
  27. // --- Strings definitions --- 
  28.  
  29. #define TP_HEADS_UP_DISPLAY_MESSAGE "Press H for help"
  30. #define TP_DRAWING_TEAPOT_MARKER_STR "Drawing a teapot: grid = %d, scale = %d"
  31. #define TP_SETTING_UP_MATERIAL_MARKER_STR "Setting up material"
  32. #define TP_SETTING_UP_LIGHTS_MARKER_STR "Setting up lights"
  33. #define TP_GENERAL_INIT_MARKER_STR "Performing general OpenGL intializations"
  34. #define TO_CREATION_GLSL_OBJECTS_MARKER_STR "Creating GLSL programs and shaders"
  35. #define TP_DRAWING_SCENE_MARKER_STR "Drawing scene objects"
  36. #define TP_MAIN_WINDOW_CAPTION_STR " Graphic Remedy teapot"
  37. #define TP_MAIN_WINDOW_CLASS_NAME_STR "GRTeapotApplication main window class name";
  38. #define TP_HELP_DIALOG_CAPTION_STR "Graphic Remedy teapot help"
  39. #define TP_OPEN_GL_ERROR_EXAMPLE_STR "Example of an OpenGL error"
  40. #define TP_CRASH_EXAMPLE_STR "Example of an application crash"
  41. #define TP_BREAK_POINT_EXAMPLE_STR "Example of a breakpoint exception"
  42. #define TP_DEBUG_STRING_EXAMPLE_STR "A sample output debug string"
  43. #define TP_ERROR_SRT "Error"
  44. #define TP_CHOOSE_PIXEL_FORMAT_ERR_SRT "ChoosePixelFormat failed"
  45. #define TP_SET_PIXEL_FORMAT_ERR_SRT "SetPixelFormat failed"
  46. #define TP_CREATE_WINDOW_ERR_SRT "Failed to create the application window"
  47. #define TP_CREATE_RENDER_CONTEXT_ERR_SRT "Failed to create the OpenGL render context"
  48. #define TP_HELP_MESSAGE_STR \
  49. "Press the mouse left button and drag to rotate the image.\n\n\
  50. Available keyboard commands are:  \n\n\
  51. b - Toggle background color\n\
  52. c - Make this application crash\n\
  53. d - Output a sample debug string\n\
  54. e - Generate an OpenGL Error\n\
  55. h - Display this help message\n\
  56. p - Generate a break point event\n\
  57. s - Toggle shading program use (on / off)\n\
  58. t - Generate a detected error\n\
  59. w - Toggle wire-frame mode.\n\
  60. - / + - Increases / decrease texture influence\n\
  61. esc - Exit the application"
  62.  
  63. // Vertex and fragment shader code file paths:
  64. #define TP_VETEX_SHADER_CODE_FILE_PATH "./tpVertexShader.glsl"
  65. #define TP_FRAGMENT_SHADER_CODE_FILE_PATH "./tpFragmentShader.glsl"
  66.  
  67. // Texture file path:
  68. #define TP_TEXTURE_FILE_PATH "./tpLogo-white.png"
  69.  
  70. // The amount of glyphs in the system font:
  71. #define TP_SYSTEM_FONT_SIZE 256
  72.  
  73. // The continues movement timer interval (ms):
  74. #define TP_TIMER_INTERVAL 10
  75.  
  76. // --- Global static variables --- 
  77.  
  78. // Window position and size:
  79. static int stat_windowXPosition = 0;
  80. static int stat_windowYPosition = 0;
  81. static int stat_windowWidth = 400;
  82. static int stat_windowHeight = 400 + 30; // 30 is the height of the windows application bar.
  83.  
  84. // Graphics view-port:
  85. static int stat_viewPortX = 0;
  86. static int stat_viewPortY = 0;
  87. static int stat_viewWidth = 0;
  88. static int stat_viewHeight = 0;
  89.  
  90. // Heads up message raster position:
  91. static float stat_headsUpRasterPosX = 0.0f;
  92. static float stat_headsUpRasterPosY = 0.0f;
  93.  
  94. // Window name and window class name:
  95. static char *stat_windowName = TP_MAIN_WINDOW_CAPTION_STR;
  96. static char *stat_windowClassName = TP_MAIN_WINDOW_CLASS_NAME_STR;
  97.  
  98. // Device context and render context handle:
  99. static HDC stat_hWindowDC = NULL;
  100. static HGLRC stat_hWindowGLRC = NULL;
  101.  
  102. // The initial mouse position:
  103. static GLint stat_mouseInitialPosX = 0; 
  104. static GLint stat_mouseInitialPosY = 0;
  105.  
  106. // The difference in mouse position from the last observed mouse position:
  107. GLint stat_mouseDeltaY = 0;
  108. GLint stat_mouseDeltaX = 1;
  109.  
  110. // Contains true iff we are in viewing mode:
  111. // (when the user manipulates the object using the mouse)
  112. static bool stat_isInViewingMode = false;
  113.  
  114. // The object rotation (degrees around the X Y and Z axis):
  115. static GLfloat stat_objectXRot = 45.0f;
  116. static GLfloat stat_objectYRot = 45.0f;
  117. static GLfloat stat_objectZRot = 0.0f;
  118.  
  119. // The object translation:
  120. static GLfloat stat_objectXTran = 0.0f;
  121. static GLfloat stat_objectYTran = 0.0f;
  122. static GLfloat stat_objectZTran = 0.0f;
  123.  
  124. // The id of a timer used for the continues movement:
  125. UINT stat_timerId = 0;
  126.  
  127. // The background color index:
  128. static int stat_backgroundColorIndex = 1;
  129.  
  130. // Set object material:
  131. GLfloat stat_ambient[4] = {1.0f, 0.0f, 0.0f ,1.0f };
  132. GLfloat stat_diffuse[4] = { 0.8f, 0.0f, 0.0f, 1.0f };
  133. GLfloat stat_specular[4] = { 0.8f, 0.8f, 0.8f, 1.0f };
  134. GLfloat stat_shininess = 20.0F;
  135.  
  136. // Display lists indices:
  137. static GLuint stat_teaPotDisplayListIndex = 0;
  138. static GLuint stat_systemFontFirstDisplayList = 0;
  139.  
  140. // The name of the used texture object:
  141. static GLuint stat_textureObjName = 0;
  142.  
  143. // Average system font glyph width:
  144. static int stat_systemFontGlyphWidth = 8;
  145.  
  146. // The used raster mode:
  147. static GLenum stat_rasterMode = GL_FILL;
  148.  
  149. // Shaders and Programs names:
  150. GLhandleARB stat_vertexShaderName = 0;
  151. GLhandleARB stat_fragmentShaderName = 0;
  152. GLhandleARB stat_shadingProgramName = 0;
  153.  
  154. // Controls texture influence [0,10]:
  155. int stat_textureInfluenceAsInt = 7;
  156.  
  157. // textureInfluence uniform location in stat_shadingProgramName:
  158. GLint stat_textureInfluenceUniformLocation = -1;
  159.  
  160. // Contains true iff the shading program was created successfully:
  161. bool stat_shadingProgramExists = false;
  162.  
  163. // Contains true iff the shading program is currently used:
  164. bool stat_shadingProgramInUse = false;
  165.  
  166. // String marker extension function pointer:
  167. PFNGLSTRINGMARKERGREMEDYPROC glStringMarkerGREMEDY = NULL;
  168.  
  169. // GL_ARB_shader_objects extension functions:
  170. static bool stat_isGL_ARB_shader_objectsSupported = false;
  171. PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
  172. PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
  173. PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
  174. PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
  175. PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
  176. PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
  177. PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
  178. PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
  179. PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
  180. PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
  181. PFNGLUNIFORM1FARBPROC glUniform1fARB = NULL;
  182. PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
  183. PFNGLDETACHOBJECTARBPROC glDetachObjectARB = NULL;
  184.  
  185. // OpenGL 1.3 extension functions:
  186. PFNGLACTIVETEXTUREPROC glActiveTexture = NULL;
  187.  
  188. // --- The teapot patch data ---
  189.  
  190. static int stat_teaPotPatchData[][16] =
  191. {
  192.     // Rim:
  193.     {102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
  194.         
  195.     // Body:
  196.     {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
  197.     {24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
  198.     
  199.     // Lid:
  200.     {96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,},
  201.     {0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117},
  202.     
  203.     // Bottom:
  204.     {118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37},
  205.     
  206.     // Handle:
  207.     {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56},
  208.     {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67},
  209.     
  210.     // Spout:
  211.     {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83},
  212.     {80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95}
  213. };
  214.  
  215.  
  216. static float stat_teaPotCPData[][3] =
  217. {
  218.     {0.2f, 0.0f, 2.7f}, {0.2f, -0.112f, 2.7f}, {0.112f, -0.2f, 2.7f}, 
  219.     {0.0f, -0.2f, 2.7f}, {1.3375f, 0.0f, 2.53125f}, {1.3375f, -0.749f, 2.53125f},
  220.     {0.749f, -1.3375f, 2.53125f}, {0.0f, -1.3375f, 2.53125f}, {1.4375f, 0.0f, 2.53125f}, 
  221.     {1.4375f, -0.805f, 2.53125f}, {0.805f, -1.4375f, 2.53125f}, {0.0f, -1.4375f, 2.53125f}, 
  222.     {1.5f, 0.0f, 2.4f}, {1.5f, -0.84f, 2.4f}, {0.84f, -1.5f, 2.4f}, 
  223.     {0.0f, -1.5f, 2.4f}, {1.75f, 0.0f, 1.875f}, {1.75f, -0.98f, 1.875f}, 
  224.     {0.98f, -1.75f, 1.875f}, {0.0f, -1.75f, 1.875f}, {2.0f, 0.0f, 1.35f}, 
  225.     {2.0f, -1.12f, 1.35f}, {1.12f, -2.0f, 1.35f}, {0.0f, -2.0f, 1.35f}, 
  226.     {2.0f, 0.0f, 0.9f}, {2.0f, -1.12f, 0.9f}, {1.12f, -2.0f, 0.9f}, 
  227.     {0.0f, -2.0f, 0.9f}, {-2.0f, 0.0f, 0.9f}, {2.0f, 0.0f, 0.45f}, 
  228.     {2.0f, -1.12f, 0.45f}, {1.12f, -2.0f, 0.45f}, {0.0f, -2.0f, 0.45f}, 
  229.     {1.5f, 0.0f, 0.225f}, {1.5f, -0.84f, 0.225f}, {0.84f, -1.5f, 0.225f}, 
  230.     {0.0f, -1.5f, 0.225f}, {1.5f, 0.0f, 0.15f}, {1.5f, -0.84f, 0.15f}, 
  231.     {0.84f, -1.5f, 0.15f}, {0.0f,-1.5f, 0.15f}, {-1.6f, 0.0f, 2.025f}, 
  232.     {-1.6f, -0.3f, 2.025f}, {-1.5f, -0.3f, 2.25f}, {-1.5f, 0.0f, 2.25f}, 
  233.     {-2.3f, 0.0f, 2.025f}, {-2.3f, -0.3f, 2.025f}, {-2.5f, -0.3f, 2.25f}, 
  234.     {-2.5f, 0.0f, 2.25f}, {-2.7f, 0.0f, 2.025f}, {-2.7f, -0.3f, 2.025f}, 
  235.     {-3.0f, -0.3f, 2.25f}, {-3.0f, 0.0f, 2.25f}, {-2.7f, 0.0f, 1.8f}, 
  236.     {-2.7f, -0.3f, 1.8f}, {-3.0f, -0.3f, 1.8f},{-3.0f, 0.0f, 1.8f}, 
  237.     {-2.7f, 0.0f, 1.575f}, {-2.7f, -0.3f, 1.575f}, {-3.0f, -0.3f, 1.35f}, 
  238.     {-3.0f, 0.0f, 1.35f}, {-2.5f, 0.0f, 1.125f}, {-2.5f, -0.3f, 1.125f}, 
  239.     {-2.65f, -0.3f, 0.9375f}, {-2.65f, 0.0f, 0.9375f}, {-2.0f, -0.3f, 0.9f}, 
  240.     {-1.9f, -0.3f, 0.6f}, {-1.9f, 0.0f, 0.6f}, {1.7f, 0.0f, 1.425f}, 
  241.     {1.7f, -0.66f, 1.425f}, {1.7f, -0.66f, 0.6f}, {1.7f, 0.0f, 0.6f}, 
  242.     {2.6f, 0.0f, 1.425f}, {2.6f, -0.66f, 1.425f}, {3.1f, -0.66f, 0.825f}, 
  243.     {3.1f, 0.0f, 0.825f}, {2.3f, 0.0f, 2.1f}, {2.3f, -0.25f, 2.1f},
  244.     {2.4f, -0.25f, 2.025f}, {2.4f, 0.0f, 2.025f}, {2.7f, 0.0f, 2.4f}, 
  245.     {2.7f, -0.25f, 2.4f}, {3.3f, -0.25f, 2.4f}, {3.3f, 0.0f, 2.4f}, 
  246.     {2.8f, 0.0f, 2.475f}, {2.8f, -0.25f, 2.475f}, {3.525f, -0.25f, 2.49375f},
  247.     {3.525f, 0.0f, 2.49375f}, {2.9f, 0.0f, 2.475f}, {2.9f, -0.15f, 2.475f},
  248.     {3.45f, -0.15f, 2.5125f}, {3.45f, 0.0f, 2.5125f}, {2.8f, 0.0f, 2.4f},
  249.     {2.8f, -0.15f, 2.4f}, {3.2f, -0.15f, 2.4f}, {3.2f, 0.0f, 2.4f}, 
  250.     {0.0f, 0.0f, 3.15f}, {0.8f, 0.0f, 3.15f}, {0.8f, -0.45f, 3.15f}, 
  251.     {0.45f, -0.8f, 3.15f}, {0.0f, -0.8f, 3.15f}, {0.0f, 0.0f, 2.85f}, 
  252.     {1.4f, 0.0f, 2.4f}, {1.4f,-0.784f, 2.4f}, {0.784f, -1.4f, 2.4f}, 
  253.     {0.0f, -1.4f, 2.4f}, {0.4f, 0.0f, 2.55f}, {0.4f, -0.224f, 2.55f}, 
  254.     {0.224f, -0.4f, 2.55f}, {0.0f, -0.4f, 2.55f}, {1.3f, 0.0f, 2.55f}, 
  255.     {1.3f, -0.728f, 2.55f}, {0.728f, -1.3f, 2.55f}, {0.0f, -1.3f, 2.55f}, 
  256.     {1.3f, 0.0f, 2.4f}, {1.3f, -0.728f, 2.4f}, {0.728f, -1.3f, 2.4f}, 
  257.     {0.0f, -1.3f, 2.4f}, {0.0f, 0.0f, 0.0f}, {1.425f, -0.798f, 0.0f}, 
  258.     {1.5f, 0.0f, 0.075f}, {1.425f, 0.0f, 0.0f}, {0.798f, -1.425f, 0.0f}, 
  259.     {0.0f, -1.5f, 0.075f}, {0.0f, -1.425f, 0.0f}, {1.5f, -0.84f, 0.075f},
  260.     {0.84f, -1.5f, 0.075f}
  261. };
  262.  
  263. static float tex[2][2][2] =
  264. {
  265.   { {0, 0}, {1, 0}},
  266.   { {0, 1}, {1, 1}}
  267. };
  268.  
  269.  
  270. // ---------------------------------------------------------------------------
  271. // Name:        tpCycleRasterModes
  272. // Description: Replace the raster mode to the next raster mode.
  273. // ---------------------------------------------------------------------------
  274. void tpCycleRasterModes()
  275. {
  276.     if (stat_rasterMode == GL_FILL)
  277.     {
  278.         stat_rasterMode = GL_LINE;
  279.     }
  280.     else
  281.     {
  282.         stat_rasterMode = GL_FILL;
  283.     }
  284. }
  285.  
  286.  
  287. // ---------------------------------------------------------------------------
  288. // Name:        tpCycleBackgroundColor
  289. // Description: Replace the background color with the next background color 
  290. //              in the background colors cycle.
  291. // ---------------------------------------------------------------------------
  292. void tpCycleBackgroundColor()
  293. {
  294.     if (stat_backgroundColorIndex == 0)
  295.     {
  296.         stat_backgroundColorIndex = 1;
  297.     }
  298.     else
  299.     {
  300.         stat_backgroundColorIndex = 0;
  301.     }
  302. }
  303.  
  304.  
  305. // ---------------------------------------------------------------------------
  306. // Name:        tpIncreaseTextureInfluence
  307. // Description: Increases texture influence (over the shaded material color)
  308. // ---------------------------------------------------------------------------
  309. void tpIncreaseTextureInfluence()
  310. {
  311.     if (stat_shadingProgramInUse)
  312.     {
  313.         if (stat_textureInfluenceAsInt < 10)
  314.         {
  315.             stat_textureInfluenceAsInt += 1;
  316.             GLfloat textureInfluence = ((float)stat_textureInfluenceAsInt / 10.0f);
  317.             glUniform1fARB(stat_textureInfluenceUniformLocation, textureInfluence);
  318.         }
  319.     }
  320. }
  321.  
  322.  
  323. // ---------------------------------------------------------------------------
  324. // Name:        tpDecreaseTextureInfluence
  325. // Description: Decreases texture influence (over the shaded material color)
  326. // ---------------------------------------------------------------------------
  327. void tpDecreaseTextureInfluence()
  328. {
  329.     if (stat_shadingProgramInUse)
  330.     {
  331.         if (stat_textureInfluenceAsInt > 0)
  332.         {
  333.             stat_textureInfluenceAsInt -= 1;
  334.             GLfloat textureInfluence = ((float)stat_textureInfluenceAsInt / 10.0f);
  335.             glUniform1fARB(stat_textureInfluenceUniformLocation, textureInfluence);
  336.         }
  337.     }
  338. }
  339.  
  340.  
  341. // ---------------------------------------------------------------------------
  342. // Name:        tpGenerateOpenGLError
  343. // Description: Generates an OpenGL error 
  344. // ---------------------------------------------------------------------------
  345. void tpGenerateOpenGLError()
  346. {
  347.     // Send a debug string into the debugger:
  348.     OutputDebugString(TP_OPEN_GL_ERROR_EXAMPLE_STR);
  349.     
  350.     // Generate an OpenGL error:
  351.     //(Calling glEnable with NULL results with a GL_INVALID_ENUM error):
  352.     glEnable(NULL);
  353. }
  354.  
  355.  
  356. // ---------------------------------------------------------------------------
  357. // Name:        tpGenerateDetectedError
  358. // Description: Generates a detected error.
  359. // ---------------------------------------------------------------------------
  360. void tpGenerateDetectedError()
  361. {
  362.     if (glActiveTexture)
  363.     {
  364.         // Generate a detected error:
  365.         // (Valid active textures are GL_TEXTURE0, GL_TEXTURE1, ...)
  366.         glActiveTexture(GL_TEXTURE0 - 10);
  367.     }
  368. }
  369.  
  370. // ---------------------------------------------------------------------------
  371. // Name:        tpCrashThisApplication
  372. // Description: Crashes this application.
  373. // ---------------------------------------------------------------------------
  374. void tpCrashThisApplication()
  375. {
  376.     // Send a debug string into the debugger:
  377.     OutputDebugString(TP_CRASH_EXAMPLE_STR);
  378.  
  379.     // Crash this application (by causing an access violation exception):
  380.     int* i = NULL;
  381.     *i = 3;
  382. }
  383.  
  384.  
  385. // ---------------------------------------------------------------------------
  386. // Name:        tpThrowBreakPointException
  387. // Description: Throws a breakpoint exception.
  388. // ---------------------------------------------------------------------------
  389. void tpThrowBreakPointException()
  390. {
  391.     // Send a debug string into the debugger:
  392.     OutputDebugString(TP_BREAK_POINT_EXAMPLE_STR);
  393.  
  394.     // Throw a breakpoint exception:
  395.     DebugBreak();
  396. }
  397.  
  398.  
  399. // ---------------------------------------------------------------------------
  400. // Name:        tpChangeObjectShininess
  401. // Description:    
  402. //   Odd calls to this function makes the object shininess wrong.
  403. //   Even calls to this function restores the object shininess.
  404. // ---------------------------------------------------------------------------
  405. void tpChangeObjectShininess()
  406. {
  407.     static bool shouldChangeShininess = true;
  408.     if (shouldChangeShininess)
  409.     {
  410.         stat_shininess = 0.1f;
  411.     }
  412.     else
  413.     {
  414.         stat_shininess = 20.0f;
  415.     }
  416.  
  417.     shouldChangeShininess = !shouldChangeShininess;
  418. }
  419.  
  420.  
  421. // ---------------------------------------------------------------------------
  422. // Name:        tpOutputDebugStringExample
  423. // Description: Send a debug string to the debugger that debugs this application.
  424. // ---------------------------------------------------------------------------
  425. void tpOutputDebugStringExample()
  426. {
  427.     OutputDebugString(TP_DEBUG_STRING_EXAMPLE_STR);
  428. }
  429.  
  430.  
  431. // ---------------------------------------------------------------------------
  432. // Name:        tpDisplayHelpMessage
  433. // Description: Displays the GRTeapotApplication help message in a message box.
  434. // Arguments:   hWnd - The message parent window handle.
  435. // ---------------------------------------------------------------------------
  436. void tpDisplayHelpMessage(HWND hWnd)
  437. {
  438.     MessageBox(hWnd, TP_HELP_MESSAGE_STR, TP_HELP_DIALOG_CAPTION_STR, MB_OK | MB_ICONINFORMATION);
  439. }
  440.  
  441.  
  442. // ---------------------------------------------------------------------------
  443. // Name:        tpMoveObjectOutOfView
  444. // Description:    
  445. //   Odd calls to this function makes the model view matrix render the 
  446. //   teapot out of the graphic view.
  447. //   Even calls to this function restores the model view matrix.
  448. // ---------------------------------------------------------------------------
  449. void tpMoveObjectOutOfView()
  450. {
  451.     static bool shouldChangeMatrix = true;
  452.     if (shouldChangeMatrix)
  453.     {
  454.         stat_objectXTran = 99999.0;
  455.     }
  456.     else
  457.     {
  458.         stat_objectXTran = 0.0;
  459.     }
  460.  
  461.     shouldChangeMatrix = !shouldChangeMatrix;
  462. }
  463.  
  464.  
  465. // ---------------------------------------------------------------------------
  466. // Name:        tpDrawTeaPot
  467. // Description: Draws a teapot.
  468. // Arguments:   grid - The number of partitions in the grid.
  469. //              scale - Scaling (size) of the teapot.
  470. //              type - OpenGL draw style (GL_FILL  / GL_LINE / etc).
  471. // ---------------------------------------------------------------------------
  472. void tpDrawTeaPot(GLint grid, GLfloat scale, GLenum type)
  473. {
  474.     float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
  475.     long i, j, k, l;
  476.  
  477.     // Add a string marker: 
  478.     if (glStringMarkerGREMEDY != NULL)
  479.     {
  480.         char buff[512];
  481.         sprintf(buff, TP_DRAWING_TEAPOT_MARKER_STR, grid, scale);
  482.         glStringMarkerGREMEDY(0, buff);
  483.     }
  484.     
  485.     glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
  486.     
  487.     // Enable automatic normals calculations:
  488.     glEnable(GL_AUTO_NORMAL);
  489.     glEnable(GL_NORMALIZE);
  490.     
  491.  
  492.     // Use a two-dimensional evaluator to generate the teapot vertices, normals
  493.     // and texture coordinates:
  494.     glEnable(GL_MAP2_VERTEX_3);
  495.     glEnable(GL_MAP2_TEXTURE_COORD_2);
  496.     glPushMatrix();
  497.     glRotatef(270.0, 1.0, 0.0, 0.0);
  498.     glScalef(0.5f * scale, 0.5f * scale, 0.5f * scale);
  499.     glTranslatef(0.0, 0.0, -1.5);
  500.     for (i = 0; i < 10; i++) 
  501.     {
  502.         for (j = 0; j < 4; j++) 
  503.         {
  504.             for (k = 0; k < 4; k++) 
  505.             {
  506.                 for (l = 0; l < 3; l++) 
  507.                 {
  508.                     p[j][k][l] = stat_teaPotCPData[stat_teaPotPatchData[i][j * 4 + k]][l];
  509.                     q[j][k][l] = stat_teaPotCPData[stat_teaPotPatchData[i][j * 4 + (3 - k)]][l];
  510.                     
  511.                     if (l == 1)
  512.                     {
  513.                         q[j][k][l] *= -1.0;
  514.                     }
  515.                     
  516.                     if (i < 6) 
  517.                     {
  518.                         r[j][k][l] = stat_teaPotCPData[stat_teaPotPatchData[i][j * 4 + (3 - k)]][l];
  519.                         
  520.                         if (l == 0)
  521.                         {
  522.                             r[j][k][l] *= -1.0;
  523.                         }
  524.                         
  525.                         s[j][k][l] = stat_teaPotCPData[stat_teaPotPatchData[i][j * 4 + k]][l];
  526.                         
  527.                         if (l == 0)
  528.                         {
  529.                             s[j][k][l] *= -1.0;
  530.                         }
  531.                         
  532.                         if (l == 1)
  533.                         {
  534.                             s[j][k][l] *= -1.0;
  535.                         }
  536.                     }
  537.                 }
  538.             }
  539.         }
  540.         
  541.         glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, &tex[0][0][0]);
  542.  
  543.         glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &p[0][0][0]);
  544.         glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0);
  545.         glEvalMesh2(type, 0, grid, 0, grid);
  546.         glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &q[0][0][0]);
  547.         glEvalMesh2(type, 0, grid, 0, grid);
  548.         
  549.         if (i < 6)
  550.         {
  551.             glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &r[0][0][0]);
  552.             glEvalMesh2(type, 0, grid, 0, grid);
  553.             glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &s[0][0][0]);
  554.             glEvalMesh2(type, 0, grid, 0, grid);
  555.         }
  556.     }
  557.  
  558.     glPopMatrix();
  559.     glPopAttrib();
  560. }
  561.  
  562.  
  563. // ---------------------------------------------------------------------------
  564. // Name:        tpSetMaterial
  565. // Description: Sets the current OpenGL material
  566. // ---------------------------------------------------------------------------
  567. void tpSetMaterial()
  568. {
  569.     // Add a string marker: 
  570.     if (glStringMarkerGREMEDY != NULL)
  571.     {
  572.         glStringMarkerGREMEDY(0, TP_SETTING_UP_MATERIAL_MARKER_STR);
  573.     }
  574.  
  575.     glShadeModel(GL_SMOOTH);
  576.  
  577.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, stat_ambient);
  578.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, stat_diffuse);
  579.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, stat_specular);
  580.     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stat_shininess);
  581.  
  582.     // Set the polygon raster mode:
  583.     glPolygonMode(GL_FRONT_AND_BACK, stat_rasterMode);
  584. }
  585.  
  586.  
  587. // ---------------------------------------------------------------------------
  588. // Name:        tpSetupLights
  589. // Description: Setups a single OpenGL directional white light.
  590. // ---------------------------------------------------------------------------
  591. void tpSetupLights()
  592. {
  593.     // Add a string marker: 
  594.     if (glStringMarkerGREMEDY != NULL)
  595.     {
  596.         glStringMarkerGREMEDY(0, TP_SETTING_UP_LIGHTS_MARKER_STR);
  597.     }
  598.     
  599.     GLfloat ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
  600.     GLfloat position[] = {0.0f, 0.0f, 1.0f, 1.0f};
  601.     
  602.     glEnable(GL_LIGHTING);
  603.     glEnable(GL_LIGHT0);
  604.     
  605.     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
  606.     glLightfv(GL_LIGHT0, GL_POSITION, position);
  607. }
  608.  
  609.  
  610. // ---------------------------------------------------------------------------
  611. // Name:        tpCreateFontDisplayLists
  612. // Description: 
  613. //   Creates TP_SYSTEM_FONT_SIZE display lists, each containing a bitmap that 
  614. //   represents a glyph of the system font.
  615. // ---------------------------------------------------------------------------
  616. void tpCreateFontDisplayLists()
  617. {
  618.     // Make the system font the device context's selected font: 
  619.     SelectObject(stat_hWindowDC, GetStockObject(SYSTEM_FONT)); 
  620.  
  621.     // Create TP_SYSTEM_FONT_SIZE display lists:
  622.     stat_systemFontFirstDisplayList = glGenLists(256);
  623.  
  624.     // Fill the display lists with bitmaps that will represent the system font 
  625.     // glyphs 0 .. TP_SYSTEM_FONT_SIZE - 1:
  626.     wglUseFontBitmaps(stat_hWindowDC, 0, (TP_SYSTEM_FONT_SIZE - 1), stat_systemFontFirstDisplayList); 
  627. }
  628.  
  629.  
  630. // ---------------------------------------------------------------------------
  631. // Name:        tpConvertBitmapFromBGRAToRGBA
  632. // Description: 
  633. //  Converts a BGRA image to an RGBA image.
  634. //  We currently support only 32 bit pixels images.
  635. // ---------------------------------------------------------------------------
  636. bool tpConvertBitmapFromBGRAToRGBA(FIBITMAP* pFreeImageBitmap)
  637. {
  638.     bool retVal = false;
  639.  
  640.     // Sanity check:
  641.     if (pFreeImageBitmap)
  642.     {
  643.         // We currently support only 32 bit pixels images:
  644.         int bitsPerPixel = FreeImage_GetBPP(pFreeImageBitmap);
  645.         if (bitsPerPixel == 32)
  646.         {
  647.             retVal = true;
  648.  
  649.             // Get the image attributes:
  650.             int imageHeight = FreeImage_GetHeight(pFreeImageBitmap);
  651.             int imageWidth = FreeImage_GetWidth(pFreeImageBitmap);
  652.             int bytesPerPixel = bitsPerPixel / 8;
  653.  
  654.             // Iterate the image lines:
  655.             for(int y=0; y<imageHeight; y++) 
  656.             {
  657.                 // Iterate the current line pixels:
  658.                 BYTE* pLineData = FreeImage_GetScanLine(pFreeImageBitmap, y);
  659.                 for(int x = 0; x < imageWidth; x++) 
  660.                 {
  661.                     // Replace the Red and blue pixels:
  662.                     BYTE redValue = pLineData[2];
  663.                     pLineData[2] = pLineData[0];
  664.                     pLineData[0] = redValue;
  665.  
  666.                     // pLineData[3] = 125;
  667.                                         
  668.                     // jump to next pixel
  669.                     pLineData += bytesPerPixel;
  670.                 }
  671.             }
  672.         }
  673.     }
  674.  
  675.     return retVal;
  676. }
  677.  
  678.  
  679. // ---------------------------------------------------------------------------
  680. // Name:        tpCreateAndLoadTexture
  681. // Description: Creates a texture object and loads the image into it.
  682. // ---------------------------------------------------------------------------
  683. void tpCreateAndLoadTexture()
  684. {
  685.     // Load the texture image from a file into a free image bitmap:
  686.     FIBITMAP* pFreeImageBitmap = pFreeImageBitmap = FreeImage_Load(FIF_PNG, TP_TEXTURE_FILE_PATH, PNG_DEFAULT);
  687.     if (pFreeImageBitmap) 
  688.     {
  689.         // Convert the image into 32 bit image:
  690.         FIBITMAP* pFreeImage32BitsBitmap = FreeImage_ConvertTo32Bits(pFreeImageBitmap);
  691.         FreeImage_Unload(pFreeImageBitmap);
  692.         pFreeImageBitmap = NULL;
  693.  
  694.         // Flip it horizontally:
  695.         FreeImage_FlipHorizontal(pFreeImage32BitsBitmap);
  696.  
  697.         // On Win32 - we need to convert from BGRA to RGBA pixels:
  698.         #if OS_BUILD_TARGET == OS_WIN32
  699.             tpConvertBitmapFromBGRAToRGBA(pFreeImage32BitsBitmap);
  700.         #endif
  701.  
  702.         // Get the image attributes:
  703.         int width = FreeImage_GetWidth(pFreeImage32BitsBitmap);
  704.         int height = FreeImage_GetHeight(pFreeImage32BitsBitmap);
  705.         int scan_width = FreeImage_GetPitch(pFreeImage32BitsBitmap);
  706.  
  707.         // Allocate a memory buffer that will hold the pixels as OpenGL expects them to be:
  708.         BYTE* pImageBuffer = (BYTE*)malloc(height * scan_width);
  709.  
  710.         // Convert the free image bitmap to "OpenGL pixels":
  711.         FreeImage_ConvertToRawBits(pImageBuffer, pFreeImage32BitsBitmap, scan_width, 32,
  712.                                    FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, FALSE);
  713.         FreeImage_Unload(pFreeImage32BitsBitmap);
  714.         pFreeImage32BitsBitmap = NULL;
  715.  
  716.         // Create a texture object and make it the bound texture:
  717.         glGenTextures(1, &stat_textureObjName);
  718.         glBindTexture(GL_TEXTURE_2D, stat_textureObjName);
  719.  
  720.         // Load the image into it:
  721.         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  722.         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pImageBuffer);
  723.  
  724.         // Delete the raw memory buffer:
  725.         free(pImageBuffer);
  726.  
  727.         // Set the texture parameters:
  728.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
  729.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
  730.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  731.         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  732.     }
  733. }
  734.  
  735.  
  736. // ---------------------------------------------------------------------------
  737. // Name:        tpReadStringFromFile
  738. // Description: Reads a string from a file into a buffer.
  739. // Arguments:   
  740. //  filePath - The input file path.
  741. //  bufferLength - The buffer length.
  742. //  pBuffer - The buffer that will receive the string.
  743. // Return Val:  bool - Success / failure.
  744. // ---------------------------------------------------------------------------
  745. bool tpReadStringFromFile(const char* filePath, int bufferLength, char* pBuffer)
  746. {
  747.     bool retVal = false;
  748.  
  749.     // Sanity check:
  750.     if (bufferLength > 0)
  751.     {
  752.         // Open the text input file for reading:
  753.         FILE* fileHandle = fopen(filePath,"rt");
  754.         if (fileHandle != NULL) 
  755.         {
  756.             // Read the file content into the buffer:
  757.             int amountOfCharsRead = fread(pBuffer, sizeof(char), bufferLength - 1, fileHandle);
  758.  
  759.             // NULL terminate the read string:
  760.             pBuffer[amountOfCharsRead] = '\0';
  761.  
  762.             // Close the file:
  763.             fclose(fileHandle);
  764.  
  765.             retVal = true;
  766.         }
  767.     }
  768.  
  769.     return retVal;
  770. }
  771.  
  772.  
  773. // ---------------------------------------------------------------------------
  774. // Name:        tpIsExtensionSupported
  775. // Description: Inputs an extension name and returns true iff the extension is 
  776. //              supported in the render context that is the current context of 
  777. //              the calling thread. 
  778. // ---------------------------------------------------------------------------
  779. bool tpIsExtensionSupported(char* extensionName, const char* extensionsString)
  780. {
  781.     bool retVal = false;
  782.     
  783.     // Search for extensionName in the extensions string. Use of strstr()
  784.     // is not sufficient because extension names can be prefixes of
  785.     // other extension names. Could use strtok() but the constant
  786.     // string returned by glGetString can be in read-only memory.
  787.     char* pCurrentPos = (char*)extensionsString;
  788.     char* pEndPos;
  789.     int extensionNameLen = strlen(extensionName);
  790.     pEndPos = pCurrentPos + strlen(pCurrentPos);
  791.     
  792.     while (pCurrentPos < pEndPos) 
  793.     {
  794.         int n = strcspn(pCurrentPos, " ");
  795.         if ((extensionNameLen == n) && (strncmp(extensionName, pCurrentPos, n) == 0)) 
  796.         {
  797.             retVal = true;
  798.             break;
  799.         }
  800.         
  801.         pCurrentPos += (n + 1);
  802.     }
  803.     
  804.     return retVal;
  805. }
  806.  
  807.  
  808. // ---------------------------------------------------------------------------
  809. // Name:        tpInitializeExtensions
  810. // Description: Initialized pointers to OpenGL extension functions that will
  811. //              be used.
  812. // ---------------------------------------------------------------------------
  813. void tpInitializeExtensions()
  814. {    
  815.     // Get the extensions string of the this thread current render context:
  816.     const char* extensionsString = (const char*)glGetString(GL_EXTENSIONS);
  817.  
  818.     // If the string marker extension is supported:
  819.     if (tpIsExtensionSupported("GL_GREMEDY_string_marker", extensionsString))
  820.     {
  821.         // Get a pointer to the glStringMarkerGREMEDY function:
  822.         glStringMarkerGREMEDY = (PFNGLSTRINGMARKERGREMEDYPROC)wglGetProcAddress("glStringMarkerGREMEDY");
  823.     }
  824.  
  825.     // If GL_ARB_shader_objects is supported:
  826.     if (tpIsExtensionSupported("GL_ARB_shader_objects", extensionsString))
  827.     {
  828.         glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
  829.         glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
  830.         glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
  831.         glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
  832.         glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
  833.         glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
  834.         glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
  835.         glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
  836.         glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
  837.         glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
  838.         glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
  839.         glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
  840.         glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC)wglGetProcAddress("glDetachObjectARB");
  841.  
  842.         // We consider the extension as supported only when we managed to get all its
  843.         // function pointers:
  844.         stat_isGL_ARB_shader_objectsSupported = 
  845.             ((glCreateShaderObjectARB != NULL) && (glShaderSourceARB != NULL) &&
  846.             (glCompileShaderARB != NULL) && (glGetObjectParameterivARB != NULL) &&
  847.             (glCreateProgramObjectARB != NULL) && (glAttachObjectARB != NULL) &&
  848.             (glLinkProgramARB != NULL) && (glUseProgramObjectARB != NULL) &&
  849.             (glGetInfoLogARB != NULL) && (glGetUniformLocationARB != NULL) &&
  850.             (glUniform1fARB != NULL) && (glDeleteObjectARB != NULL) &&
  851.             (glDetachObjectARB != NULL));
  852.     }
  853.  
  854.     // Get OpenGL 1.3 function pointers:
  855.     glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");
  856. }
  857.  
  858.  
  859. // ---------------------------------------------------------------------------
  860. // Name:        tpSetShadersSourceCodes
  861. // Description: Sets the fragment and vertex shaders source codes.
  862. // Return Val:  bool - Success / failure.
  863. // ---------------------------------------------------------------------------
  864. bool tpSetShadersSourceCodes(GLhandleARB vertexShaderName, GLhandleARB fragmentShaderName)
  865. {
  866.     bool retVal = false;
  867.  
  868.     // Allocate space for the shaders source codes:
  869.     int sourceCodeBuffLength = 16384;
  870.     char* vertexShaderCode = new char[sourceCodeBuffLength];
  871.     char* fragmentShaderCode = new char[sourceCodeBuffLength];
  872.     if ((vertexShaderCode != NULL) && (fragmentShaderCode != NULL))
  873.     {
  874.         // Read the shaders source codes:
  875.         bool vsSourceRead = tpReadStringFromFile(TP_VETEX_SHADER_CODE_FILE_PATH, sourceCodeBuffLength, vertexShaderCode);
  876.         bool fsSourceRead = tpReadStringFromFile(TP_FRAGMENT_SHADER_CODE_FILE_PATH, sourceCodeBuffLength, fragmentShaderCode);
  877.         
  878.         if (vsSourceRead && fsSourceRead)
  879.         {
  880.             // Load the source code into the OpenGL shaders:
  881.             glShaderSourceARB(stat_vertexShaderName, 1, (const char**)(&vertexShaderCode), NULL);
  882.             glShaderSourceARB(stat_fragmentShaderName, 1, (const char**)(&fragmentShaderCode), NULL);
  883.  
  884.             retVal = true;
  885.         }
  886.  
  887.         // Clean up:
  888.         delete[] vertexShaderCode;
  889.         delete[] fragmentShaderCode;
  890.     }
  891.  
  892.     return retVal;
  893. }
  894.  
  895.  
  896. // ---------------------------------------------------------------------------
  897. // Name:        tpCreateProgramsAndShaders
  898. // Description: Creates the required shading programs and shaders.
  899. // ---------------------------------------------------------------------------
  900. bool tpCreateProgramsAndShaders()
  901. {
  902.     bool retVal = false;
  903.  
  904.     // If the GL_ARB_shader_objects extension is supported:
  905.     if (stat_isGL_ARB_shader_objectsSupported)
  906.     {
  907.         // Add a string marker: 
  908.         if (glStringMarkerGREMEDY != NULL)
  909.         {
  910.             glStringMarkerGREMEDY(0, TO_CREATION_GLSL_OBJECTS_MARKER_STR);
  911.         }
  912.  
  913.         // Create the vertex and fragment shaders:
  914.         stat_vertexShaderName = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
  915.         stat_fragmentShaderName = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
  916.  
  917.         // Set their source code:
  918.         bool rc = tpSetShadersSourceCodes(stat_vertexShaderName, stat_fragmentShaderName);
  919.         
  920.         if (rc)
  921.         {
  922.             // Compile the shaders:
  923.             glCompileShaderARB(stat_vertexShaderName);
  924.             glCompileShaderARB(stat_fragmentShaderName);
  925.  
  926.             // Verify successful compilation:
  927.             GLint wasVSCompilationSuccessful = false;
  928.             GLint wasFSCompilationSuccessful = false;
  929.             glGetObjectParameterivARB(stat_vertexShaderName, GL_OBJECT_COMPILE_STATUS_ARB, &wasVSCompilationSuccessful);
  930.             glGetObjectParameterivARB(stat_fragmentShaderName, GL_OBJECT_COMPILE_STATUS_ARB, &wasFSCompilationSuccessful);
  931.  
  932.             if ((wasVSCompilationSuccessful == 1) && (wasFSCompilationSuccessful == 1))
  933.             {
  934.                 // Create the program object:
  935.                 stat_shadingProgramName = glCreateProgramObjectARB();
  936.                 
  937.                 // Attach the shaders to the program:
  938.                 glAttachObjectARB(stat_shadingProgramName, stat_vertexShaderName);
  939.                 glAttachObjectARB(stat_shadingProgramName, stat_fragmentShaderName);
  940.  
  941.                 // Link the program:
  942.                 glLinkProgramARB(stat_shadingProgramName);
  943.  
  944.                 // Verify that the link succeeded:
  945.                 GLint wasLinkSuccesful = 0;
  946.                 glGetObjectParameterivARB(stat_shadingProgramName, GL_OBJECT_LINK_STATUS_ARB, &wasLinkSuccesful);
  947.                 if (wasLinkSuccesful == 1)
  948.                 {
  949.                     // Get the textureInfluence uniform location:
  950.                     stat_textureInfluenceUniformLocation = glGetUniformLocationARB(stat_shadingProgramName, "textureInfluence");
  951.                     if (stat_textureInfluenceUniformLocation != -1)
  952.                     {
  953.                         retVal = true;
  954.                     }
  955.                 }
  956.             }
  957.         }
  958.     }
  959.  
  960.     return retVal;
  961. }
  962.  
  963.  
  964. // ---------------------------------------------------------------------------
  965. // Name:        tpUseShadingProgram
  966. // Description: Use / don't use the shading program (if exists).
  967. // ---------------------------------------------------------------------------
  968. void tpUseShadingProgram(bool isShadingProgramUsed)
  969. {
  970.     // If the shading program does not exist:
  971.     if (!stat_shadingProgramExists)
  972.     {
  973.         stat_shadingProgramInUse = false;
  974.     }
  975.     else
  976.     {
  977.         if (isShadingProgramUsed)
  978.         {
  979.             // Use the shading program (install it into the pipeline):
  980.             glUseProgramObjectARB(stat_shadingProgramName);
  981.  
  982.             // Set the textureInfluence uniform value:
  983.             GLfloat textureInfluence = ((float)stat_textureInfluenceAsInt / 10.0f);
  984.             glUniform1fARB(stat_textureInfluenceUniformLocation, textureInfluence);
  985.         }
  986.         else
  987.         {
  988.             // Un-install the program (use the fixed OpenGL pipeline):
  989.             glUseProgramObjectARB(0);
  990.         }
  991.  
  992.         // Log the use of the shading program:
  993.         stat_shadingProgramInUse = isShadingProgramUsed;
  994.     }
  995. }
  996.  
  997.  
  998. // ---------------------------------------------------------------------------
  999. // Name:        tpPerformGeneralOpenGLInitializations
  1000. // Description: Performs general initializations.
  1001. // ---------------------------------------------------------------------------
  1002. void tpPerformGeneralOpenGLInitializations()
  1003. {
  1004.     // Initialize the OpenGL extensions that will be used:
  1005.     tpInitializeExtensions();
  1006.  
  1007.     // Add a string marker: 
  1008.     if (glStringMarkerGREMEDY != NULL)
  1009.     {
  1010.         glStringMarkerGREMEDY(0, TP_GENERAL_INIT_MARKER_STR);
  1011.     }
  1012.  
  1013.     // Set the projection transformation:
  1014.     glMatrixMode(GL_PROJECTION);
  1015.     glFrustum(-0.5F, 0.5F, -0.5F, 0.5F, 1.0F, 3.0F);
  1016.  
  1017.     // Set the viewing transformation:
  1018.     glMatrixMode(GL_MODELVIEW);
  1019.     glTranslatef(0.0F, 0.0F, -2.0F);
  1020.  
  1021.     // Enable depth test:
  1022.     glEnable(GL_DEPTH_TEST);
  1023.  
  1024.     // Create a display list that will contains the tea pot geometry:
  1025.     stat_teaPotDisplayListIndex = glGenLists(1);
  1026.  
  1027.     // Fill the display list with a solid (raster filled) tea pot:
  1028.     glNewList(stat_teaPotDisplayListIndex, GL_COMPILE);
  1029.     tpDrawTeaPot(7, 0.5, GL_FILL);
  1030.     glEndList();
  1031.  
  1032.     // Create display lists that represent the system font:
  1033.     tpCreateFontDisplayLists();
  1034.  
  1035.     // Generate the used texture:
  1036.     tpCreateAndLoadTexture();
  1037.  
  1038.     // Create the shading programs and shaders:
  1039.     stat_shadingProgramExists = tpCreateProgramsAndShaders();
  1040.  
  1041.     // If the shading program was created successfully:
  1042.     if (stat_shadingProgramExists)
  1043.     {
  1044.         // Use the shading program (install it into the pipeline):
  1045.         tpUseShadingProgram(true);
  1046.     }
  1047. }
  1048.  
  1049.  
  1050. // ---------------------------------------------------------------------------
  1051. // Name:        tpPerformGeneralOpenCleanups
  1052. // Description: Performs general OpenGL cleanups (delete allocated objects, etc).
  1053. // ---------------------------------------------------------------------------
  1054. void tpPerformGeneralOpenCleanups()
  1055. {
  1056.     // Delete the display list that contains the tea pot geometry:
  1057.     if (stat_teaPotDisplayListIndex != 0)
  1058.     {
  1059.         glDeleteLists(stat_teaPotDisplayListIndex, 1);
  1060.     }
  1061.  
  1062.     // Delete the display lists that contains the system font glyphs:
  1063.     if (stat_systemFontFirstDisplayList)
  1064.     {
  1065.         glDeleteLists(stat_systemFontFirstDisplayList, TP_SYSTEM_FONT_SIZE);
  1066.     }
  1067.     
  1068.     // Delete the teapot texture:
  1069.     if (stat_textureObjName != 0)
  1070.     {
  1071.         glDeleteTextures(1, &stat_textureObjName);
  1072.     }
  1073.         
  1074.     if (stat_shadingProgramExists && stat_isGL_ARB_shader_objectsSupported)
  1075.     {
  1076.         // Remove the used program (if any):
  1077.         glUseProgramObjectARB(0);
  1078.         
  1079.         // Detach shaders from the shading program:
  1080.         glDetachObjectARB(stat_shadingProgramName, stat_vertexShaderName);
  1081.         glDetachObjectARB(stat_shadingProgramName, stat_fragmentShaderName);
  1082.  
  1083.         // Delete shaders:
  1084.         glDeleteObjectARB(stat_vertexShaderName);
  1085.         glDeleteObjectARB(stat_fragmentShaderName);
  1086.  
  1087.         // Delete the shading program:
  1088.         glDeleteObjectARB(stat_shadingProgramName);
  1089.     }
  1090.  
  1091.     // Delete the OpenGL render context:
  1092.     wglMakeCurrent(NULL, NULL);
  1093.     wglDeleteContext(stat_hWindowGLRC);
  1094. }
  1095.  
  1096.  
  1097. // ---------------------------------------------------------------------------
  1098. // Name:        tpOnWindowSizeChanged
  1099. // Description: Is called when the window size is changed.
  1100. //              Adjusts the view port to the new window size.
  1101. // Arguments: 
  1102. //   width, height - The new window width and height.
  1103. // ---------------------------------------------------------------------------
  1104. void tpOnWindowSizeChanged(int width, int height)
  1105. {
  1106.     // Save the new window size in the static global variables:
  1107.     stat_windowWidth = width;
  1108.     stat_windowHeight = height;
  1109.  
  1110.     // Make sure that the view port is always a rectangle:
  1111.     GLsizei minValue = stat_windowWidth;
  1112.     if (stat_windowHeight < stat_windowWidth)
  1113.     {
  1114.         minValue = minValue = stat_windowHeight;
  1115.     }
  1116.  
  1117.     // Set the view port:
  1118.     stat_viewPortX = 0;
  1119.     stat_viewPortY = 0;
  1120.     stat_viewWidth = minValue;
  1121.     stat_viewHeight = minValue;
  1122.     glViewport(stat_viewPortX, stat_viewPortY, stat_viewWidth, stat_viewHeight);
  1123.  
  1124.     // Calculate the heads up display raster position:
  1125.     int headsUpMessageLength = strlen(TP_HEADS_UP_DISPLAY_MESSAGE);
  1126.     float headsUpMessageWidth = float(stat_systemFontGlyphWidth * headsUpMessageLength);
  1127.     float leftWidth = stat_viewWidth - headsUpMessageWidth;
  1128.     if (leftWidth < 0)
  1129.     {
  1130.         leftWidth = 0;
  1131.     }
  1132.     stat_headsUpRasterPosX = ((leftWidth / 2.0f) / stat_viewWidth);
  1133.     stat_headsUpRasterPosY = 0.05f;
  1134. }    
  1135.  
  1136.  
  1137. // ---------------------------------------------------------------------------
  1138. // Name:        tpClearGraphicBuffers
  1139. // Description: Clears the color and depth buffers
  1140. // ---------------------------------------------------------------------------
  1141. void tpClearGraphicBuffers()
  1142. {
  1143.     // Set the background color;
  1144.     if (stat_backgroundColorIndex == 0)
  1145.     {
  1146.         glClearColor(1,1,1,1);
  1147.     }
  1148.     else
  1149.     {
  1150.         glClearColor(0,0,0,1);
  1151.     }
  1152.  
  1153.     // Clear the background (using the above color):
  1154.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  1155. }
  1156.  
  1157.  
  1158. // ---------------------------------------------------------------------------
  1159. // Name:        tpDrawScene
  1160. // Description: Draws the graphic scene.
  1161. // ---------------------------------------------------------------------------
  1162. void tpDrawScene()
  1163. {
  1164.     // Set the current material:
  1165.     tpSetMaterial();
  1166.  
  1167.     // Set the current lights:
  1168.     tpSetupLights();
  1169.  
  1170.     // Add a string marker: 
  1171.     if (glStringMarkerGREMEDY != NULL)
  1172.     {
  1173.         glStringMarkerGREMEDY(0, TP_DRAWING_SCENE_MARKER_STR);
  1174.     }
  1175.  
  1176.     // Set the used texture:
  1177.     glBindTexture(GL_TEXTURE_2D, stat_textureObjName);
  1178.  
  1179.     // Set textures environment parameters:
  1180.     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
  1181.     
  1182.     // Enable 2D textures:
  1183.     glEnable(GL_TEXTURE_2D);
  1184.  
  1185.     // Place the object to be drawn (model transformation):
  1186.     glPushMatrix();
  1187.     glTranslatef(stat_objectXTran, stat_objectYTran, stat_objectZTran);
  1188.     glRotatef(stat_objectXRot, 1.0F, 0.0F, 0.0F);
  1189.     glRotatef(stat_objectYRot, 0.0F, 1.0F, 0.0F);
  1190.     glRotatef(stat_objectZRot, 0.0F, 0.0F, 1.0F);
  1191.  
  1192.     // Draw the object:
  1193.     glCallList(stat_teaPotDisplayListIndex);
  1194.  
  1195.     // Clean up - remove the model transformation and disable 2D texturing:
  1196.     glPopMatrix();
  1197.     glDisable(GL_TEXTURE_2D);
  1198. }
  1199.  
  1200.  
  1201. // ---------------------------------------------------------------------------
  1202. // Name:        tpSetupOpenGLForHeadsUpDraw
  1203. // Description: Setup OpenGL states for heads up 2D drawing
  1204. // ---------------------------------------------------------------------------
  1205. void tpSetupOpenGLForHeadsUpDraw()
  1206. {
  1207.     // Setup a simple projection matrix:
  1208.     glMatrixMode(GL_PROJECTION);
  1209.     glPushMatrix();
  1210.     glLoadIdentity();
  1211.     glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0, 1.0);
  1212.  
  1213.     // Setup identity model view matrix:
  1214.     glMatrixMode(GL_MODELVIEW);
  1215.     glPushMatrix();
  1216.     glLoadIdentity();
  1217.  
  1218.     // Disable the "Z" buffer test (gain an "always on top" effect):
  1219.     glDisable(GL_DEPTH_TEST);
  1220.  
  1221.     // Disable the use of the shading program:
  1222.     if (stat_shadingProgramExists && stat_shadingProgramInUse)
  1223.     {
  1224.         glUseProgramObjectARB(0);
  1225.     }
  1226. }
  1227.  
  1228.  
  1229. // ---------------------------------------------------------------------------
  1230. // Name:        tpRestoreOpenGLFromHeadsUpDraw
  1231. // Description: 
  1232. //   Restores OpenGL states to the state they were before the heads up 2D drawing
  1233. // ---------------------------------------------------------------------------
  1234. void tpRestoreOpenGLFromHeadsUpDraw()
  1235. {
  1236.     // Restore OpenGL states:
  1237.     glMatrixMode(GL_PROJECTION);
  1238.     glPopMatrix();
  1239.     glMatrixMode(GL_MODELVIEW);
  1240.     glPopMatrix();
  1241.  
  1242.     // Restore the "Z" buffer test:
  1243.     glEnable(GL_DEPTH_TEST);
  1244.  
  1245.     // Restore the used of shading program:
  1246.     if (stat_shadingProgramExists && stat_shadingProgramInUse)
  1247.     {
  1248.         glUseProgramObjectARB(stat_shadingProgramName);
  1249.     }
  1250. }
  1251.  
  1252.  
  1253. // ---------------------------------------------------------------------------
  1254. // Name:        tpDrawHeadsUpMessage
  1255. // Description: Draw an heads up message on the screen.
  1256. // ---------------------------------------------------------------------------
  1257. void tpDrawHeadsUpMessage()
  1258. {
  1259.     // Setup OpenGL for heads up 2D drawing:
  1260.     tpSetupOpenGLForHeadsUpDraw();
  1261.  
  1262.     // Set current color to yellow:
  1263.     GLfloat stat_HeadsUpTextAmbient[4] = {1.0f, 1.0f, 0.0f ,1.0f };
  1264.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, stat_HeadsUpTextAmbient);
  1265.  
  1266.     // Set the raster position:
  1267.     glRasterPos2f(stat_headsUpRasterPosX, stat_headsUpRasterPosY);
  1268.  
  1269.     // Set the display lists base to the first system font display list:
  1270.     glListBase(stat_systemFontFirstDisplayList);
  1271.  
  1272.     // Draw the text message: 
  1273.     glCallLists(16, GL_UNSIGNED_BYTE, TP_HEADS_UP_DISPLAY_MESSAGE); 
  1274.  
  1275.     // Restore OpenGL states:
  1276.     tpRestoreOpenGLFromHeadsUpDraw();
  1277. }
  1278.  
  1279.  
  1280. // ---------------------------------------------------------------------------
  1281. // Name:        tpSwapBuffers
  1282. // Description: Swaps the back and the front buffer.
  1283. // ---------------------------------------------------------------------------
  1284. void tpSwapBuffers()
  1285. {
  1286.     SwapBuffers(stat_hWindowDC);
  1287. }
  1288.  
  1289.  
  1290. // ---------------------------------------------------------------------------
  1291. // Name:        tpPaintWindow
  1292. // Description: Paint the graphic window (redraw it).
  1293. // ---------------------------------------------------------------------------
  1294. void tpPaintWindow()
  1295. {
  1296.     // Clear the graphic buffers:
  1297.     tpClearGraphicBuffers();
  1298.  
  1299.     // Draw the scene into the back buffer:
  1300.     tpDrawScene();
  1301.     
  1302.     // Draw the heads up message:
  1303.     tpDrawHeadsUpMessage();
  1304.  
  1305.     // Swap the back and the front buffer:
  1306.     tpSwapBuffers();
  1307. }
  1308.  
  1309.  
  1310. // ---------------------------------------------------------------------------
  1311. // Name:        tpSetupPixelFormat
  1312. // Description: Sets up a given device context pixel format to be a double
  1313. //              buffer RGBA pixel format.
  1314. // Arguments:   hWindowDC - The input device context handle.
  1315. // ---------------------------------------------------------------------------
  1316. void tpSetupPixelFormat(HDC hWindowDC)
  1317. {
  1318.     // Get the device context window:
  1319.     HWND hWindow = WindowFromDC(hWindowDC);
  1320.  
  1321.     // Define the requested pixel format descriptor:
  1322.     PIXELFORMATDESCRIPTOR pfd = 
  1323.     {
  1324.         sizeof(PIXELFORMATDESCRIPTOR),    // This struct size.
  1325.             1,                            // Struct version.
  1326.             PFD_SUPPORT_OPENGL |        // OpenGL Double buffer support.
  1327.             PFD_DRAW_TO_WINDOW |
  1328.             PFD_DOUBLEBUFFER,        
  1329.             PFD_TYPE_RGBA,                // RGBA pixel format.
  1330.             16,                            // Requested color depth.
  1331.             0, 0, 0, 0, 0, 0,            // Color bits (ignored).
  1332.             0,                            // No alpha buffer.
  1333.             0,                            // Alpha bits (ignored).
  1334.             0,                            // No accumulation buffer.
  1335.             0, 0, 0, 0,                    // Accumulation buffer bits (ignored).
  1336.             16,                            // Depth buffer bits.
  1337.             0,                            // No stencil buffer.
  1338.             0,                            // No auxiliary buffers.
  1339.             PFD_MAIN_PLANE,                // Main layer (ignored).
  1340.             0,                            // Number of overlay and underlay planes.
  1341.             0,                          // No Layer mask.
  1342.             0,                          // No visibility mask.
  1343.             0                            // No damage masks.
  1344.     };
  1345.  
  1346.     // Choose the pixel format that best match the above requested pixel format:
  1347.     int pixelFormat = ChoosePixelFormat(hWindowDC, &pfd);
  1348.     
  1349.     // If we failed to find a matching pixel format:
  1350.     if (pixelFormat == 0) 
  1351.     {
  1352.         // Display an error message and exit the application:
  1353.         MessageBox(hWindow, TP_CHOOSE_PIXEL_FORMAT_ERR_SRT, TP_ERROR_SRT, MB_ICONERROR | MB_OK);
  1354.         exit(1);
  1355.     }
  1356.     
  1357.     // Set the chosen pixel format to be the active pixel format:
  1358.     BOOL rc = SetPixelFormat(hWindowDC, pixelFormat, &pfd);
  1359.  
  1360.     // If we failed to set the active pixel format:
  1361.     if (rc != TRUE)
  1362.     {
  1363.         // Display an error message and exit the application:
  1364.         MessageBox(hWindow, TP_SET_PIXEL_FORMAT_ERR_SRT, TP_ERROR_SRT, MB_ICONERROR | MB_OK);
  1365.         exit(1);
  1366.     }
  1367. }
  1368.  
  1369.  
  1370. // ---------------------------------------------------------------------------
  1371. // Name:        tpCreateOpenGLRenderContext
  1372. // Description: 
  1373. //   Inputs a device context and creates an OpenGL render context that can 
  1374. //   draw into it.
  1375. //
  1376. // Arguments:   
  1377. //   hDeviceContext - The input device context handle.
  1378. //
  1379. // Return Val:  
  1380. //   HGLRC - A handle to the created OpenGL render context.
  1381. // ---------------------------------------------------------------------------
  1382. HGLRC tpCreateOpenGLRenderContext(HDC hDeviceContext)
  1383. {
  1384.     // Create an OpenGL render context for the application window device context:
  1385.     HGLRC retVal = wglCreateContext(stat_hWindowDC);
  1386.  
  1387.     if (retVal == NULL)
  1388.     {
  1389.         // Display an error message and exit the application:
  1390.         HWND hWindow = WindowFromDC(hDeviceContext);
  1391.         MessageBox(hWindow, TP_CREATE_RENDER_CONTEXT_ERR_SRT, TP_ERROR_SRT, MB_ICONERROR | MB_OK);
  1392.         exit(1);
  1393.     }
  1394.  
  1395.     // Make it the current render context:
  1396.     wglMakeCurrent(stat_hWindowDC, retVal);
  1397.  
  1398.     return retVal;
  1399. }
  1400.  
  1401.  
  1402. // ---------------------------------------------------------------------------
  1403. // Name:        tpTimerProc
  1404. // Description: Is called by the timer on each timer interval end.
  1405. // Arguments:   hwnd - The window associated with the timer.
  1406. //              uMsg - WM_TIMER message.
  1407. //              idEvent - The timer id.
  1408. //              dwTime - The number of milliseconds that have elapsed since the system was started
  1409. // ---------------------------------------------------------------------------
  1410. void tpTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  1411. {
  1412.     // If we are not in viewing mode:
  1413.     if (!stat_isInViewingMode)
  1414.     {
  1415.         // Calculate the rotation that needs to be performed on the displayed object:
  1416.         stat_objectXRot += 360.0F * stat_mouseDeltaY / stat_windowHeight;
  1417.         stat_objectYRot += 360.0F * stat_mouseDeltaX / stat_windowWidth;
  1418.     
  1419.         // Repaint the window:
  1420.         tpPaintWindow();
  1421.     }
  1422. }
  1423.  
  1424.  
  1425. // ---------------------------------------------------------------------------
  1426. // Name:        tpOnKeyPressed
  1427. // Description: Is called when the user press a keyboard key.
  1428. // Arguments:   hWindow - The window in which the key was pressed.
  1429. //              pressedKey - The pressed key.
  1430. //              shouldCallDefaultWinProc - Will get true iff the default win procedure 
  1431. //                                         should be called after the call to this function.
  1432. // Return Val:  LRESULT - The result of the message processing.
  1433. // ---------------------------------------------------------------------------
  1434. LRESULT tpOnKeyPressed(HWND hWindow, int pressedKey, bool& shouldCallDefaultWinProc)
  1435. {
  1436.     // Will get the return value of this function:
  1437.     LRESULT retVal = 0;
  1438.  
  1439.     // Unless specified otherwise - pass the key press handling also to the windows
  1440.     // default procedure:
  1441.     shouldCallDefaultWinProc = true;
  1442.  
  1443.     switch (pressedKey) 
  1444.     {
  1445.     case VK_ESCAPE:
  1446.         {
  1447.             // Destroy the window:
  1448.             // (If this is the main window - the application will exit)
  1449.             DestroyWindow(hWindow);
  1450.  
  1451.             // Do not call the windows default procedure:
  1452.             shouldCallDefaultWinProc = false;
  1453.         }
  1454.         break;
  1455.         
  1456.     case 'b':
  1457.         {
  1458.             // Set the next background color to be the active one:
  1459.             tpCycleBackgroundColor();
  1460.         }
  1461.         break;
  1462.         
  1463.     case 'c':
  1464.         {
  1465.             // Crash the application:
  1466.             tpCrashThisApplication();
  1467.         }
  1468.         break;
  1469.         
  1470.     case 'd':
  1471.         {
  1472.             // Output a debug string to the debugged that debugs this
  1473.             // program:
  1474.             tpOutputDebugStringExample();
  1475.         }
  1476.         break;
  1477.         
  1478.     case 'e':
  1479.         {
  1480.             // Generate an OpenGL error:
  1481.             tpGenerateOpenGLError();
  1482.         }
  1483.         break;
  1484.     
  1485.     case 't':
  1486.         {
  1487.             // Generate a detected error:
  1488.             tpGenerateDetectedError();
  1489.         }
  1490.         break;
  1491.         
  1492.     case 'h':
  1493.         {
  1494.             // Display the help message in a dialog:
  1495.             tpDisplayHelpMessage(hWindow);
  1496.         }
  1497.         break;
  1498.         
  1499.     case 'm':
  1500.         {
  1501.             // Make the teapot disappear from the screen:
  1502.             tpMoveObjectOutOfView();
  1503.         }
  1504.         break;
  1505.  
  1506.     case 'o':
  1507.         {
  1508.             // Change the object shininess:
  1509.             tpChangeObjectShininess();
  1510.         }
  1511.         break;
  1512.  
  1513.     case 'p':
  1514.         {
  1515.             // Generate a breakpoint exception:
  1516.             tpThrowBreakPointException();
  1517.         }
  1518.         break;
  1519.         
  1520.     case 's':
  1521.         {
  1522.             if (stat_shadingProgramExists)
  1523.             {
  1524.                 // Toggle shading program use on / off:
  1525.                 if (!stat_shadingProgramInUse)
  1526.                 {
  1527.                     tpUseShadingProgram(true);
  1528.                 }
  1529.                 else
  1530.                 {
  1531.                     tpUseShadingProgram(false);
  1532.                 }
  1533.             }
  1534.         }
  1535.         break;
  1536.  
  1537.     case 'w':
  1538.         {
  1539.             // Set the next drawn object to be the active one:
  1540.             tpCycleRasterModes();
  1541.         }
  1542.         break;
  1543.  
  1544.     case '+':
  1545.         {
  1546.             // Increase texture influence:
  1547.             tpIncreaseTextureInfluence();
  1548.         }
  1549.         break;
  1550.  
  1551.     case '-':
  1552.         {
  1553.             // Decrease texture influence:
  1554.             tpDecreaseTextureInfluence();
  1555.         }
  1556.         break;
  1557.     }
  1558.  
  1559.     return retVal;
  1560. }
  1561.  
  1562.  
  1563. // ---------------------------------------------------------------------------
  1564. // Name:        tpWindowsMessagesHandlingProcedure
  1565. // Description: 
  1566. //  Receives and handles the application windows messages.
  1567. //
  1568. // Arguments:   
  1569. //  hWnd - A handle to the window to which the message was sent.
  1570. //  message - The id of the sent message.
  1571. //  wParam, lParam - Message parameters (depends on the message sent).
  1572. //
  1573. // Return Val: 
  1574. //  The result of the message processing (depends on the message sent).
  1575. // ---------------------------------------------------------------------------
  1576. LRESULT APIENTRY tpWindowsMessagesHandlingProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  1577. {
  1578.     // Will get the return value of this function:
  1579.     LRESULT retVal = 0;
  1580.  
  1581.     // Contains true iff we should call the default window procedure for the input message:
  1582.     bool shouldCallDefaultWinProc = false;
  1583.  
  1584.     switch (message) 
  1585.     {
  1586.     case WM_CREATE: // Window is created:
  1587.         {
  1588.             // Create a timer that will call tpTimerProc every TP_TIMER_INTERVAL ms:
  1589.             stat_timerId = ::SetTimer(NULL, 1, TP_TIMER_INTERVAL, (TIMERPROC)tpTimerProc);
  1590.         }
  1591.         break;
  1592.  
  1593.     case WM_DESTROY: // Window is destroyed:
  1594.         {
  1595.             // Delete the timer:
  1596.             ::KillTimer(NULL, stat_timerId);
  1597.  
  1598.             // Notity the system that this thread is about to terminate:
  1599.             PostQuitMessage(0);
  1600.         }
  1601.         break;
  1602.  
  1603.     case WM_SIZE: // Window size is changed:
  1604.         {
  1605.             // Do we have a render context?
  1606.             if (stat_hWindowGLRC != NULL) 
  1607.             {
  1608.                 // Get the window new size:
  1609.                 int windowWidth = (int) LOWORD(lParam);
  1610.                 int windowHeight = (int) HIWORD(lParam);
  1611.  
  1612.                 // Adjust the view port to the new window size:
  1613.                 tpOnWindowSizeChanged(windowWidth, windowHeight);
  1614.             }
  1615.             else
  1616.             {
  1617.                 // We don't have a render context - use the default behavior:
  1618.                 shouldCallDefaultWinProc = true;
  1619.             }
  1620.         }
  1621.         break;
  1622.  
  1623.     case WM_PAINT: // Window needs to be repainted:
  1624.         {
  1625.             // Prepare the window for painting:
  1626.             PAINTSTRUCT ps;
  1627.             BeginPaint(hWnd, &ps);
  1628.             
  1629.             // Sanity test - do we have a render context?
  1630.             if (stat_hWindowGLRC != NULL) 
  1631.             {
  1632.                 // Repaint the window:
  1633.                 tpPaintWindow();
  1634.             }
  1635.         
  1636.             // Window painting was ended:
  1637.             EndPaint(hWnd, &ps);
  1638.         }
  1639.         break;
  1640.  
  1641.     case WM_CHAR: // Keyboard key was pressed:
  1642.         {
  1643.             // Get the pressed key (as a char)
  1644.             int pressedKey = wParam;
  1645.             
  1646.             // Handle the key event:
  1647.             retVal = tpOnKeyPressed(hWnd, pressedKey, shouldCallDefaultWinProc);
  1648.         }
  1649.         break;
  1650.         
  1651.         case WM_LBUTTONDOWN: // Mouse left button was pressed:
  1652.             {
  1653.                 // If we are not in viewing mode (if the button was not already pressed):
  1654.                 if (!stat_isInViewingMode) 
  1655.                 {
  1656.                     // Capture mouse events while the mouse is over the input window:
  1657.                     SetCapture(hWnd);
  1658.  
  1659.                     // Get into viewing mode:
  1660.                     stat_isInViewingMode = true;
  1661.  
  1662.                     // Store the mouse initial position:
  1663.                     stat_mouseInitialPosX = ((int) LOWORD(lParam) << 16) >> 16;
  1664.                     stat_mouseInitialPosY = ((int) HIWORD(lParam) << 16) >> 16;
  1665.  
  1666.                     // Initialize the mouse delta recording:
  1667.                     stat_mouseDeltaX = 0;
  1668.                     stat_mouseDeltaY = 0;
  1669.                 }
  1670.  
  1671.                 shouldCallDefaultWinProc = true;
  1672.             }
  1673.             break;
  1674.  
  1675.         case WM_RBUTTONDOWN: // Mouse right button was pressed:
  1676.             {
  1677.                 shouldCallDefaultWinProc = true;
  1678.             }
  1679.             break;
  1680.  
  1681.         case WM_LBUTTONUP: // Mouse left button was released:
  1682.             {
  1683.                 // If we are in viewing mode:
  1684.                 if (stat_isInViewingMode) 
  1685.                 {
  1686.                     // Release the mouse events capture:
  1687.                     ReleaseCapture();
  1688.  
  1689.                     // Exit viewing mode:
  1690.                     stat_isInViewingMode = false;
  1691.                 }
  1692.  
  1693.                 shouldCallDefaultWinProc = true;
  1694.             }
  1695.             break;
  1696.  
  1697.         case WM_RBUTTONUP: // Mouse right button was released:
  1698.             {
  1699.                 shouldCallDefaultWinProc = true;
  1700.             }
  1701.             break;
  1702.  
  1703.         case WM_MOUSEMOVE: // The mouse was moved:
  1704.             {
  1705.                 // If we are in viewing mode:
  1706.                 if (stat_isInViewingMode) 
  1707.                 {
  1708.                     // Get the mouse current position (after the movement):
  1709.                     GLint mouseCurrentPosX = ((int) LOWORD(lParam) << 16) >> 16;
  1710.                     GLint mouseCurrentPosY = ((int) HIWORD(lParam) << 16) >> 16;
  1711.                 
  1712.                     // Calculate the delta in mouse position from the place where
  1713.                     // it was observed last:
  1714.                     stat_mouseDeltaY = mouseCurrentPosY - stat_mouseInitialPosY;
  1715.                     stat_mouseDeltaX = mouseCurrentPosX - stat_mouseInitialPosX;
  1716.  
  1717.                     // Calculate the rotation that needs to be performed on the 
  1718.                     // displayed object:
  1719.                     stat_objectXRot += 360.0F * stat_mouseDeltaY / stat_windowHeight;
  1720.                     stat_objectYRot += 360.0F * stat_mouseDeltaX / stat_windowWidth;
  1721.  
  1722.                     // Update the mouse "last observed" position to contain the current position:
  1723.                     stat_mouseInitialPosX = mouseCurrentPosX;
  1724.                     stat_mouseInitialPosY = mouseCurrentPosY;
  1725.  
  1726.                     // Repaint the window:
  1727.                     tpPaintWindow();
  1728.                 }
  1729.  
  1730.                 shouldCallDefaultWinProc = true;
  1731.             }
  1732.             break;
  1733.  
  1734.         default:
  1735.             {
  1736.                 shouldCallDefaultWinProc = true;
  1737.             }
  1738.             break;
  1739.         }
  1740.  
  1741.     if (shouldCallDefaultWinProc)
  1742.     {
  1743.         // Call the default window procedure:
  1744.         retVal = DefWindowProc(hWnd, message, wParam, lParam);
  1745.     }
  1746.  
  1747.     return retVal;
  1748. }
  1749.  
  1750.  
  1751. // ---------------------------------------------------------------------------
  1752. // Name:        tpCreateApplicationWindow
  1753. // Description: Creates the application window.
  1754. // Arguments:   hCurrentApplicationInst - The current application instance handle.
  1755. // Return Val:  HWND - The created window handle.
  1756. // ---------------------------------------------------------------------------
  1757. HWND tpCreateApplicationWindow(HINSTANCE hCurrentApplicationInst)
  1758. {
  1759.     HWND retVal = NULL;
  1760.  
  1761.     HINSTANCE hInstance = GetModuleHandle(NULL);
  1762.  
  1763.     // Register the application window class:
  1764.     WNDCLASSEX wndClass;
  1765.     
  1766.     wndClass.cbSize = sizeof(WNDCLASSEX); 
  1767.     wndClass.style = CS_HREDRAW | CS_VREDRAW;
  1768.     wndClass.lpfnWndProc = tpWindowsMessagesHandlingProcedure;
  1769.     wndClass.cbClsExtra = 0;
  1770.     wndClass.cbWndExtra = 0;
  1771.     wndClass.hInstance = hCurrentApplicationInst;
  1772.     wndClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_TP_APPLICATION_ICON_32);
  1773.     wndClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_TP_APPLICATION_ICON);
  1774.     wndClass.hCursor = LoadCursor(NULL, IDC_HAND);
  1775.     wndClass.hbrBackground = NULL;
  1776.     wndClass.lpszMenuName = NULL;
  1777.     wndClass.lpszClassName = stat_windowClassName;
  1778.     RegisterClassEx(&wndClass);
  1779.     
  1780.     // Create the application window:
  1781.     retVal = CreateWindow(stat_windowClassName, stat_windowName, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  1782.                           stat_windowXPosition, stat_windowYPosition, stat_windowWidth, stat_windowHeight,
  1783.                           NULL, NULL, hCurrentApplicationInst, NULL);
  1784.  
  1785.     if (retVal == NULL)
  1786.     {
  1787.         // Display an error message and exit the application:
  1788.         MessageBox(retVal, TP_CREATE_WINDOW_ERR_SRT, TP_ERROR_SRT, MB_ICONERROR | MB_OK);
  1789.         exit(1);
  1790.     }
  1791.  
  1792.     return retVal;
  1793. }
  1794.  
  1795.  
  1796. // ---------------------------------------------------------------------------
  1797. // Name:        tpApplicationMessageLoop
  1798. // Description: 
  1799. //   Performs the application message loop - Wait for windows messages and
  1800. //   handles them.
  1801. //
  1802. // Return Val:  
  1803. //   int - The last message parameter (usually the WM_QUIT message param.
  1804. // ---------------------------------------------------------------------------
  1805. int tpApplicationMessageLoop()
  1806. {
  1807.     // An infinite loop that process windows messages:
  1808.     MSG msg;
  1809.     while (1) 
  1810.     {
  1811.         // Wait for messages that are posted into this thread message queue:
  1812.         if (::GetMessage(&msg, NULL, 0, 0) == TRUE) 
  1813.         {
  1814.             // Translate and dispatch the message into the window messages handling procedure
  1815.             // (tpWindowsMessagesHandlingProcedure):
  1816.             TranslateMessage(&msg);
  1817.             DispatchMessage(&msg);
  1818.         }
  1819.         else
  1820.         {
  1821.             // We got a WM_QUIT message. Exit the main loop:
  1822.             break;
  1823.         }
  1824.     }
  1825.  
  1826.     return msg.wParam;
  1827. }
  1828.  
  1829.  
  1830. // ---------------------------------------------------------------------------
  1831. // Name:        WinMain
  1832. // Description: 
  1833. //   The "main" function. Is considered by the OS as the program entry point.
  1834. //
  1835. // Arguments:   
  1836. //   hCurrentInst - Handle to the current instance of the application.
  1837. //   hPreviousInst - Always NULL.
  1838. //   lpszCmdLine - The application command line arguments.
  1839. //   nCmdShow - Specifies how the window is to be shown.
  1840. //
  1841. // Return Val:  
  1842. //   int - Application exit code.
  1843. // ---------------------------------------------------------------------------
  1844. int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst, LPSTR lpszCmdLine, int nCmdShow)
  1845. {
  1846.     int retVal = 0;
  1847.  
  1848.     // Create the application window:
  1849.     HWND hWnd = tpCreateApplicationWindow(hCurrentInst);
  1850.     
  1851.     // Save the application window device context:
  1852.     stat_hWindowDC = GetDC(hWnd);
  1853.  
  1854.     // Show the application window:
  1855.     ShowWindow(hWnd, SW_SHOWNORMAL);
  1856.     UpdateWindow(hWnd);
  1857.     
  1858.     // Set the device context pixel format:
  1859.     tpSetupPixelFormat(stat_hWindowDC);
  1860.     
  1861.     // Create the OpenGL render context:
  1862.     stat_hWindowGLRC = tpCreateOpenGLRenderContext(stat_hWindowDC);
  1863.  
  1864.     // Perform general OpenGL initializations:
  1865.     tpPerformGeneralOpenGLInitializations();
  1866.  
  1867.     // Perform calculations (setting view port, etc) that are related with the 
  1868.     // window initial size:
  1869.     tpOnWindowSizeChanged(stat_windowWidth, stat_windowHeight);
  1870.     
  1871.     // Do the application message loop:
  1872.     retVal = tpApplicationMessageLoop();
  1873.     
  1874.     // Perform OpenGL cleanups:
  1875.     tpPerformGeneralOpenCleanups();
  1876.  
  1877.     // Clean up:
  1878.     ReleaseDC(hWnd, stat_hWindowDC);
  1879.     
  1880.     return retVal;
  1881. }
  1882.  
  1883.