libgoatvr

annotate example/src/main.c @ 5:e63cb28fc644

working on the linux side a bit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 18 Sep 2014 10:56:45 +0300
parents
children b71314e80654
rev   line source
nuclear@5 1 #include <stdio.h>
nuclear@5 2 #include <stdlib.h>
nuclear@5 3 #include <assert.h>
nuclear@5 4 #include <SDL2/SDL.h>
nuclear@5 5 #include <GL/glew.h>
nuclear@5 6 #include "vr.h"
nuclear@5 7
nuclear@5 8 int init(void);
nuclear@5 9 void cleanup(void);
nuclear@5 10 void toggle_hmd_fullscreen(void);
nuclear@5 11 void display(void);
nuclear@5 12 void draw_scene(void);
nuclear@5 13 void draw_box(float xsz, float ysz, float zsz, float norm_sign);
nuclear@5 14 void update_rtarg(int width, int height);
nuclear@5 15 int handle_event(SDL_Event *ev);
nuclear@5 16 int key_event(int key, int state);
nuclear@5 17 void reshape(int x, int y);
nuclear@5 18 unsigned int next_pow2(unsigned int x);
nuclear@5 19 void quat_to_matrix(const float *quat, float *mat);
nuclear@5 20 unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1);
nuclear@5 21
nuclear@5 22 static SDL_Window *win;
nuclear@5 23 static SDL_GLContext ctx;
nuclear@5 24 static int win_width, win_height;
nuclear@5 25
nuclear@5 26 static unsigned int fbo, fb_tex, fb_depth;
nuclear@5 27 static int fb_width, fb_height;
nuclear@5 28 static int fb_tex_width, fb_tex_height;
nuclear@5 29
nuclear@5 30 static unsigned int chess_tex;
nuclear@5 31
nuclear@5 32
nuclear@5 33 int main(int argc, char **argv)
nuclear@5 34 {
nuclear@5 35 if(init() == -1) {
nuclear@5 36 return 1;
nuclear@5 37 }
nuclear@5 38
nuclear@5 39 for(;;) {
nuclear@5 40 SDL_Event ev;
nuclear@5 41 while(SDL_PollEvent(&ev)) {
nuclear@5 42 if(handle_event(&ev) == -1) {
nuclear@5 43 goto done;
nuclear@5 44 }
nuclear@5 45 }
nuclear@5 46 display();
nuclear@5 47 }
nuclear@5 48
nuclear@5 49 done:
nuclear@5 50 cleanup();
nuclear@5 51 return 0;
nuclear@5 52 }
nuclear@5 53
nuclear@5 54
nuclear@5 55 int init(void)
nuclear@5 56 {
nuclear@5 57 int x, y;
nuclear@5 58 unsigned int flags;
nuclear@5 59
nuclear@5 60 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
nuclear@5 61
nuclear@5 62 x = y = SDL_WINDOWPOS_UNDEFINED;
nuclear@5 63 flags = SDL_WINDOW_OPENGL;
nuclear@5 64 if(!(win = SDL_CreateWindow("press 'f' to move to the HMD", x, y, 1280, 800, flags))) {
nuclear@5 65 fprintf(stderr, "failed to create window\n");
nuclear@5 66 return -1;
nuclear@5 67 }
nuclear@5 68 if(!(ctx = SDL_GL_CreateContext(win))) {
nuclear@5 69 fprintf(stderr, "failed to create OpenGL context\n");
nuclear@5 70 return -1;
nuclear@5 71 }
nuclear@5 72
nuclear@5 73 glewInit();
nuclear@5 74
nuclear@5 75 if(vr_init() == -1) {
nuclear@5 76 return -1;
nuclear@5 77 }
nuclear@5 78
nuclear@5 79 /* resize our window to match the HMD resolution */
nuclear@5 80 win_width = vr_get_opti(VR_OPT_DISPLAY_WIDTH);
nuclear@5 81 win_height = vr_get_opti(VR_OPT_DISPLAY_HEIGHT);
nuclear@5 82 if(!win_width || !win_height) {
nuclear@5 83 SDL_GetWindowSize(win, &win_width, &win_height);
nuclear@5 84 } else {
nuclear@5 85 SDL_SetWindowSize(win, win_width, win_height);
nuclear@5 86 SDL_SetWindowPosition(win, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
nuclear@5 87 }
nuclear@5 88
nuclear@5 89 /* and create a single render target texture to encompass both eyes */
nuclear@5 90 fb_width = vr_get_opti(VR_OPT_LEYE_XRES) + vr_get_opti(VR_OPT_REYE_XRES);
nuclear@5 91 fb_height = vr_get_opti(VR_OPT_LEYE_YRES); /* assuming both are the same */
nuclear@5 92 if(!fb_width || !fb_height) {
nuclear@5 93 fb_width = win_width;
nuclear@5 94 fb_height = win_height;
nuclear@5 95 }
nuclear@5 96 update_rtarg(fb_width, fb_height);
nuclear@5 97
nuclear@5 98 /* set our render texture and its active area */
nuclear@5 99 vr_output_texture(fb_tex, 0, (float)(fb_tex_height - fb_height) / (float)fb_tex_height,
nuclear@5 100 (float)fb_width / (float)fb_tex_width, 1.0);
nuclear@5 101
nuclear@5 102 glEnable(GL_DEPTH_TEST);
nuclear@5 103 glEnable(GL_CULL_FACE);
nuclear@5 104 glEnable(GL_LIGHTING);
nuclear@5 105 glEnable(GL_LIGHT0);
nuclear@5 106 glEnable(GL_LIGHT1);
nuclear@5 107 glEnable(GL_NORMALIZE);
nuclear@5 108
nuclear@5 109 glClearColor(0.5, 0.1, 0.1, 1);
nuclear@5 110
nuclear@5 111 chess_tex = gen_chess_tex(1.0, 0.7, 0.4, 0.4, 0.7, 1.0);
nuclear@5 112 return 0;
nuclear@5 113 }
nuclear@5 114
nuclear@5 115 void cleanup(void)
nuclear@5 116 {
nuclear@5 117 vr_shutdown();
nuclear@5 118 SDL_Quit();
nuclear@5 119 }
nuclear@5 120
nuclear@5 121 void toggle_hmd_fullscreen(void)
nuclear@5 122 {
nuclear@5 123 static int fullscr, prev_x, prev_y;
nuclear@5 124 fullscr = !fullscr;
nuclear@5 125
nuclear@5 126 if(fullscr) {
nuclear@5 127 /* going fullscreen on the rift. save current window position, and move it
nuclear@5 128 * to the rift's part of the desktop before going fullscreen
nuclear@5 129 */
nuclear@5 130 SDL_GetWindowPosition(win, &prev_x, &prev_y);
nuclear@5 131 SDL_SetWindowPosition(win, vr_get_opti(VR_OPT_WIN_XOFFS), vr_get_opti(VR_OPT_WIN_YOFFS));
nuclear@5 132 SDL_SetWindowFullscreen(win, SDL_WINDOW_FULLSCREEN_DESKTOP);
nuclear@5 133 } else {
nuclear@5 134 /* return to windowed mode and move the window back to its original position */
nuclear@5 135 SDL_SetWindowFullscreen(win, 0);
nuclear@5 136 SDL_SetWindowPosition(win, prev_x, prev_y);
nuclear@5 137 }
nuclear@5 138 }
nuclear@5 139
nuclear@5 140 void display(void)
nuclear@5 141 {
nuclear@5 142 int i;
nuclear@5 143 float proj_mat[16];
nuclear@5 144 float rot_mat[16], view_mat[16];
nuclear@5 145
nuclear@5 146 /* start drawing onto our texture render target */
nuclear@5 147 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@5 148 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@5 149
nuclear@5 150 /* for each eye ... */
nuclear@5 151 for(i=0; i<2; i++) {
nuclear@5 152 vr_begin(i);
nuclear@5 153
nuclear@5 154 /* -- viewport transformation --
nuclear@5 155 * setup the viewport to draw in the left half of the framebuffer when we're
nuclear@5 156 * rendering the left eye's view (0, 0, width/2, height), and in the right half
nuclear@5 157 * of the framebuffer for the right eye's view (width/2, 0, width/2, height)
nuclear@5 158 */
nuclear@5 159 glViewport(i == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height);
nuclear@5 160
nuclear@5 161 glMatrixMode(GL_PROJECTION);
nuclear@5 162 /* -- projection transformation --
nuclear@5 163 * we'll just have to use the projection matrix supplied by the oculus SDK for this eye
nuclear@5 164 * note that libovr matrices are the transpose of what OpenGL expects, so we have to
nuclear@5 165 * use glLoadTransposeMatrixf instead of glLoadMatrixf to load it.
nuclear@5 166 */
nuclear@5 167 if(vr_proj_matrix(i, 0.5, 500.0, proj_mat)) {
nuclear@5 168 glLoadTransposeMatrixf(proj_mat);
nuclear@5 169 } else {
nuclear@5 170 glLoadIdentity();
nuclear@5 171 gluPerspective(50.0, (float)fb_width / 2.0 / (float)fb_height, 0.5, 500.0);
nuclear@5 172 }
nuclear@5 173
nuclear@5 174 /* -- view/camera transformation --
nuclear@5 175 * we need to construct a view matrix by combining all the information provided by the oculus
nuclear@5 176 * SDK, about the position and orientation of the user's head in the world.
nuclear@5 177 */
nuclear@5 178 glMatrixMode(GL_MODELVIEW);
nuclear@5 179 vr_view_matrix(i, view_mat);
nuclear@5 180 glLoadTransposeMatrixf(view_mat);
nuclear@5 181 /* move the camera to the eye level of the user */
nuclear@5 182 glTranslatef(0, -vr_get_optf(VR_OPT_EYE_HEIGHT), 0);
nuclear@5 183
nuclear@5 184 /* finally draw the scene for this eye */
nuclear@5 185 draw_scene();
nuclear@5 186
nuclear@5 187 vr_end();
nuclear@5 188 }
nuclear@5 189
nuclear@5 190 /* after drawing both eyes into the texture render target, revert to drawing directly to the
nuclear@5 191 * display, and we call ovrHmd_EndFrame, to let the Oculus SDK draw both images properly
nuclear@5 192 * compensated for lens distortion and chromatic abberation onto the HMD screen.
nuclear@5 193 */
nuclear@5 194 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@5 195 glViewport(0, 0, win_width, win_height);
nuclear@5 196
nuclear@5 197 vr_swap_buffers();
nuclear@5 198
nuclear@5 199 assert(glGetError() == GL_NO_ERROR);
nuclear@5 200 }
nuclear@5 201
nuclear@5 202 void draw_scene(void)
nuclear@5 203 {
nuclear@5 204 int i;
nuclear@5 205 float grey[] = {0.8, 0.8, 0.8, 1};
nuclear@5 206 float col[] = {0, 0, 0, 1};
nuclear@5 207 float lpos[][4] = {
nuclear@5 208 {-8, 2, 10, 1},
nuclear@5 209 {0, 15, 0, 1}
nuclear@5 210 };
nuclear@5 211 float lcol[][4] = {
nuclear@5 212 {0.8, 0.8, 0.8, 1},
nuclear@5 213 {0.4, 0.3, 0.3, 1}
nuclear@5 214 };
nuclear@5 215
nuclear@5 216 for(i=0; i<2; i++) {
nuclear@5 217 glLightfv(GL_LIGHT0 + i, GL_POSITION, lpos[i]);
nuclear@5 218 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, lcol[i]);
nuclear@5 219 }
nuclear@5 220
nuclear@5 221 glMatrixMode(GL_MODELVIEW);
nuclear@5 222
nuclear@5 223 glPushMatrix();
nuclear@5 224 glTranslatef(0, 10, 0);
nuclear@5 225 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey);
nuclear@5 226 glBindTexture(GL_TEXTURE_2D, chess_tex);
nuclear@5 227 glEnable(GL_TEXTURE_2D);
nuclear@5 228 draw_box(30, 20, 30, -1.0);
nuclear@5 229 glDisable(GL_TEXTURE_2D);
nuclear@5 230 glPopMatrix();
nuclear@5 231
nuclear@5 232 for(i=0; i<4; i++) {
nuclear@5 233 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, grey);
nuclear@5 234 glPushMatrix();
nuclear@5 235 glTranslatef(i & 1 ? 5 : -5, 1, i & 2 ? -5 : 5);
nuclear@5 236 draw_box(0.5, 2, 0.5, 1.0);
nuclear@5 237 glPopMatrix();
nuclear@5 238
nuclear@5 239 col[0] = i & 1 ? 1.0 : 0.3;
nuclear@5 240 col[1] = i == 0 ? 1.0 : 0.3;
nuclear@5 241 col[2] = i & 2 ? 1.0 : 0.3;
nuclear@5 242 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, col);
nuclear@5 243
nuclear@5 244 glPushMatrix();
nuclear@5 245 if(i & 1) {
nuclear@5 246 glTranslatef(0, 0.25, i & 2 ? 2 : -2);
nuclear@5 247 } else {
nuclear@5 248 glTranslatef(i & 2 ? 2 : -2, 0.25, 0);
nuclear@5 249 }
nuclear@5 250 draw_box(0.5, 0.5, 0.5, 1.0);
nuclear@5 251 glPopMatrix();
nuclear@5 252 }
nuclear@5 253 }
nuclear@5 254
nuclear@5 255 void draw_box(float xsz, float ysz, float zsz, float norm_sign)
nuclear@5 256 {
nuclear@5 257 glMatrixMode(GL_MODELVIEW);
nuclear@5 258 glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5);
nuclear@5 259
nuclear@5 260 if(norm_sign < 0.0) {
nuclear@5 261 glFrontFace(GL_CW);
nuclear@5 262 }
nuclear@5 263
nuclear@5 264 glBegin(GL_QUADS);
nuclear@5 265 glNormal3f(0, 0, 1 * norm_sign);
nuclear@5 266 glTexCoord2f(0, 0); glVertex3f(-1, -1, 1);
nuclear@5 267 glTexCoord2f(1, 0); glVertex3f(1, -1, 1);
nuclear@5 268 glTexCoord2f(1, 1); glVertex3f(1, 1, 1);
nuclear@5 269 glTexCoord2f(0, 1); glVertex3f(-1, 1, 1);
nuclear@5 270 glNormal3f(1 * norm_sign, 0, 0);
nuclear@5 271 glTexCoord2f(0, 0); glVertex3f(1, -1, 1);
nuclear@5 272 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
nuclear@5 273 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
nuclear@5 274 glTexCoord2f(0, 1); glVertex3f(1, 1, 1);
nuclear@5 275 glNormal3f(0, 0, -1 * norm_sign);
nuclear@5 276 glTexCoord2f(0, 0); glVertex3f(1, -1, -1);
nuclear@5 277 glTexCoord2f(1, 0); glVertex3f(-1, -1, -1);
nuclear@5 278 glTexCoord2f(1, 1); glVertex3f(-1, 1, -1);
nuclear@5 279 glTexCoord2f(0, 1); glVertex3f(1, 1, -1);
nuclear@5 280 glNormal3f(-1 * norm_sign, 0, 0);
nuclear@5 281 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
nuclear@5 282 glTexCoord2f(1, 0); glVertex3f(-1, -1, 1);
nuclear@5 283 glTexCoord2f(1, 1); glVertex3f(-1, 1, 1);
nuclear@5 284 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
nuclear@5 285 glEnd();
nuclear@5 286 glBegin(GL_TRIANGLE_FAN);
nuclear@5 287 glNormal3f(0, 1 * norm_sign, 0);
nuclear@5 288 glTexCoord2f(0.5, 0.5); glVertex3f(0, 1, 0);
nuclear@5 289 glTexCoord2f(0, 0); glVertex3f(-1, 1, 1);
nuclear@5 290 glTexCoord2f(1, 0); glVertex3f(1, 1, 1);
nuclear@5 291 glTexCoord2f(1, 1); glVertex3f(1, 1, -1);
nuclear@5 292 glTexCoord2f(0, 1); glVertex3f(-1, 1, -1);
nuclear@5 293 glTexCoord2f(0, 0); glVertex3f(-1, 1, 1);
nuclear@5 294 glEnd();
nuclear@5 295 glBegin(GL_TRIANGLE_FAN);
nuclear@5 296 glNormal3f(0, -1 * norm_sign, 0);
nuclear@5 297 glTexCoord2f(0.5, 0.5); glVertex3f(0, -1, 0);
nuclear@5 298 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
nuclear@5 299 glTexCoord2f(1, 0); glVertex3f(1, -1, -1);
nuclear@5 300 glTexCoord2f(1, 1); glVertex3f(1, -1, 1);
nuclear@5 301 glTexCoord2f(0, 1); glVertex3f(-1, -1, 1);
nuclear@5 302 glTexCoord2f(0, 0); glVertex3f(-1, -1, -1);
nuclear@5 303 glEnd();
nuclear@5 304
nuclear@5 305 glFrontFace(GL_CCW);
nuclear@5 306 }
nuclear@5 307
nuclear@5 308 /* update_rtarg creates (and/or resizes) the render target used to draw the two stero views */
nuclear@5 309 void update_rtarg(int width, int height)
nuclear@5 310 {
nuclear@5 311 if(!fbo) {
nuclear@5 312 /* if fbo does not exist, then nothing does... create every opengl object */
nuclear@5 313 glGenFramebuffers(1, &fbo);
nuclear@5 314 glGenTextures(1, &fb_tex);
nuclear@5 315 glGenRenderbuffers(1, &fb_depth);
nuclear@5 316
nuclear@5 317 glBindTexture(GL_TEXTURE_2D, fb_tex);
nuclear@5 318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
nuclear@5 319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
nuclear@5 320 }
nuclear@5 321
nuclear@5 322 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
nuclear@5 323
nuclear@5 324 /* calculate the next power of two in both dimensions and use that as a texture size */
nuclear@5 325 fb_tex_width = next_pow2(width);
nuclear@5 326 fb_tex_height = next_pow2(height);
nuclear@5 327
nuclear@5 328 /* create and attach the texture that will be used as a color buffer */
nuclear@5 329 glBindTexture(GL_TEXTURE_2D, fb_tex);
nuclear@5 330 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_tex_width, fb_tex_height, 0,
nuclear@5 331 GL_RGBA, GL_UNSIGNED_BYTE, 0);
nuclear@5 332 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fb_tex, 0);
nuclear@5 333
nuclear@5 334 /* create and attach the renderbuffer that will serve as our z-buffer */
nuclear@5 335 glBindRenderbuffer(GL_RENDERBUFFER, fb_depth);
nuclear@5 336 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, fb_tex_width, fb_tex_height);
nuclear@5 337 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb_depth);
nuclear@5 338
nuclear@5 339 if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
nuclear@5 340 fprintf(stderr, "incomplete framebuffer!\n");
nuclear@5 341 }
nuclear@5 342
nuclear@5 343 glBindFramebuffer(GL_FRAMEBUFFER, 0);
nuclear@5 344 printf("created render target: %dx%d (texture size: %dx%d)\n", width, height, fb_tex_width, fb_tex_height);
nuclear@5 345 }
nuclear@5 346
nuclear@5 347 int handle_event(SDL_Event *ev)
nuclear@5 348 {
nuclear@5 349 switch(ev->type) {
nuclear@5 350 case SDL_QUIT:
nuclear@5 351 return -1;
nuclear@5 352
nuclear@5 353 case SDL_KEYDOWN:
nuclear@5 354 case SDL_KEYUP:
nuclear@5 355 if(key_event(ev->key.keysym.sym, ev->key.state == SDL_PRESSED) == -1) {
nuclear@5 356 return -1;
nuclear@5 357 }
nuclear@5 358 break;
nuclear@5 359
nuclear@5 360 default:
nuclear@5 361 break;
nuclear@5 362 }
nuclear@5 363
nuclear@5 364 return 0;
nuclear@5 365 }
nuclear@5 366
nuclear@5 367 int key_event(int key, int state)
nuclear@5 368 {
nuclear@5 369 if(state) {
nuclear@5 370 switch(key) {
nuclear@5 371 case 27:
nuclear@5 372 return -1;
nuclear@5 373
nuclear@5 374 case ' ':
nuclear@5 375 /* allow the user to recenter by pressing space */
nuclear@5 376 vr_recenter();
nuclear@5 377 break;
nuclear@5 378
nuclear@5 379 case 'f':
nuclear@5 380 /* press f to move the window to the HMD */
nuclear@5 381 toggle_hmd_fullscreen();
nuclear@5 382 break;
nuclear@5 383
nuclear@5 384 default:
nuclear@5 385 break;
nuclear@5 386 }
nuclear@5 387 }
nuclear@5 388 return 0;
nuclear@5 389 }
nuclear@5 390
nuclear@5 391 unsigned int next_pow2(unsigned int x)
nuclear@5 392 {
nuclear@5 393 x -= 1;
nuclear@5 394 x |= x >> 1;
nuclear@5 395 x |= x >> 2;
nuclear@5 396 x |= x >> 4;
nuclear@5 397 x |= x >> 8;
nuclear@5 398 x |= x >> 16;
nuclear@5 399 return x + 1;
nuclear@5 400 }
nuclear@5 401
nuclear@5 402 /* convert a quaternion to a rotation matrix */
nuclear@5 403 void quat_to_matrix(const float *quat, float *mat)
nuclear@5 404 {
nuclear@5 405 mat[0] = 1.0 - 2.0 * quat[1] * quat[1] - 2.0 * quat[2] * quat[2];
nuclear@5 406 mat[4] = 2.0 * quat[0] * quat[1] + 2.0 * quat[3] * quat[2];
nuclear@5 407 mat[8] = 2.0 * quat[2] * quat[0] - 2.0 * quat[3] * quat[1];
nuclear@5 408 mat[12] = 0.0f;
nuclear@5 409
nuclear@5 410 mat[1] = 2.0 * quat[0] * quat[1] - 2.0 * quat[3] * quat[2];
nuclear@5 411 mat[5] = 1.0 - 2.0 * quat[0]*quat[0] - 2.0 * quat[2]*quat[2];
nuclear@5 412 mat[9] = 2.0 * quat[1] * quat[2] + 2.0 * quat[3] * quat[0];
nuclear@5 413 mat[13] = 0.0f;
nuclear@5 414
nuclear@5 415 mat[2] = 2.0 * quat[2] * quat[0] + 2.0 * quat[3] * quat[1];
nuclear@5 416 mat[6] = 2.0 * quat[1] * quat[2] - 2.0 * quat[3] * quat[0];
nuclear@5 417 mat[10] = 1.0 - 2.0 * quat[0]*quat[0] - 2.0 * quat[1]*quat[1];
nuclear@5 418 mat[14] = 0.0f;
nuclear@5 419
nuclear@5 420 mat[3] = mat[7] = mat[11] = 0.0f;
nuclear@5 421 mat[15] = 1.0f;
nuclear@5 422 }
nuclear@5 423
nuclear@5 424 /* generate a chessboard texture with tiles colored (r0, g0, b0) and (r1, g1, b1) */
nuclear@5 425 unsigned int gen_chess_tex(float r0, float g0, float b0, float r1, float g1, float b1)
nuclear@5 426 {
nuclear@5 427 int i, j;
nuclear@5 428 unsigned int tex;
nuclear@5 429 unsigned char img[8 * 8 * 3];
nuclear@5 430 unsigned char *pix = img;
nuclear@5 431
nuclear@5 432 for(i=0; i<8; i++) {
nuclear@5 433 for(j=0; j<8; j++) {
nuclear@5 434 int black = (i & 1) == (j & 1);
nuclear@5 435 pix[0] = (black ? r0 : r1) * 255;
nuclear@5 436 pix[1] = (black ? g0 : g1) * 255;
nuclear@5 437 pix[2] = (black ? b0 : b1) * 255;
nuclear@5 438 pix += 3;
nuclear@5 439 }
nuclear@5 440 }
nuclear@5 441
nuclear@5 442 glGenTextures(1, &tex);
nuclear@5 443 glBindTexture(GL_TEXTURE_2D, tex);
nuclear@5 444 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
nuclear@5 445 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
nuclear@5 446 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, GL_UNSIGNED_BYTE, img);
nuclear@5 447
nuclear@5 448 return tex;
nuclear@5 449 }