#include <math.h> #include <stdlib.h> #include <stdio.h> #include <time.h> #include <windows.h> #include <mmsystem.h> #include <gl/gl.h> #include <mmsystem.h> #pragma comment(lib, "OpenGL32.lib") #pragma comment(lib, "Winmm.lib") #define PI_OVER_180 0.01745329F #define DEG2RAD( a ) ( (a) * PI_OVER_180 ) #define ELEMENTS_PER_VERTEX 3 #define ELEMENTS_PER_NORMAL 3 #define BYTES_PER_CACHELINE 32 /* struct used to manage color ramps */ struct colorIndexState { GLfloat amb[3]; /* ambient color / bottom of ramp */ GLfloat diff[3]; /* diffuse color / middle of ramp */ GLfloat spec[3]; /* specular color / top of ramp */ GLfloat ratio; /* ratio of diffuse to specular in ramp */ GLint indexes[3]; /* where ramp was placed in palette */ }; #define NUM_COLORS (sizeof(s_colors) / sizeof(s_colors[0])) struct colorIndexState s_colors[] = { { { 0.0F, 0.0F, 0.0F }, { 1.0F, 0.0F, 0.0F }, { 1.0F, 1.0F, 1.0F }, 0.75F, { 0, 0, 0 }, }, { { 0.0F, 0.05F, 0.05F }, { 0.9F, 0.0F, 1.0F }, { 1.0F, 1.0F, 1.0F }, 1.0F, { 0, 0, 0 }, }, { { 0.0F, 0.0F, 0.0F }, { 1.0F, 0.9F, 0.1F }, { 1.0F, 1.0F, 1.0F }, 0.75F, { 0, 0, 0 }, }, { { 0.0F, 0.0F, 0.0F }, { 0.1F, 1.0F, 0.9F }, { 1.0F, 1.0F, 1.0F }, 0.75F, { 0, 0, 0 }, }, }; static void (APIENTRY *LockArraysSGI)(GLint first, GLsizei count); static void (APIENTRY *UnlockArraysSGI)(void); static void (APIENTRY *CullParameterfvSGI)( GLenum pname, GLfloat *params ); static GLint s_lit_tex_indexes[3]; static int s_num_rows = 16; static int s_num_cols = 16; static int s_winwidth = 320; static int s_winheight = 240; #define MS_TO_RENDER 5000 #define DRAW_VERTEX3FV 0 #define DRAW_DRAW_ELEMENTS 1 #define DRAW_DRAW_ARRAYS 2 #define DRAW_ARRAY_ELEMENT 3 static const char *s_class_name = "GL Sphere"; static const char *s_window_name = "GL Sphere"; static BOOL s_rgba = TRUE; static BOOL s_lighting = TRUE; static BOOL s_benchmark = FALSE; static BOOL s_remote = FALSE; static BOOL s_lock_arrays = TRUE; static BOOL s_vcull = TRUE; static HPALETTE s_hPalette = NULL; static HWND s_hWnd = NULL; static HGLRC s_hglrc = NULL; static HDC s_hDC = NULL; static int s_bpp = 8; static int s_draw_method = DRAW_VERTEX3FV; static unsigned long s_vertices_processed = 0L; static unsigned long s_triangles_processed = 0L; static float s_elapsed_time; static unsigned long s_start, s_stop; /* ** this maintains the data for drawing stuff via tristrips */ static float **s_sphere_points; static float **s_sphere_normals; /* ** this maintains the data for drawing stuff via vertex arrays and array elements */ static float *s_sphere_point_array; static float *s_sphere_normal_array; /* ** this stores the data for drawing stuff using interleaved arrays with ** draw elements */ static float *s_sphere_interleaved_array; static unsigned int **s_sphere_elements; /* ** this maintains the data for drawing stuff via vertex arrays and drawarrays */ static float **s_sphere_point_draw_array; static float **s_sphere_normal_draw_array; static BOOL SphereCreateGeometry( int rows, int cols, float scale ); static BOOL InitSphere( HINSTANCE hInstance, LPSTR lpszCmdLine ); static void ShutdownSphere( void ); static void SphereSetDefaults( void ); static void SphereNormalizeVector( float v[3] ); static void SphereHelp( void ); static void SphereSetupPalette( HDC hDC ); static void *AllocAlignedX( int num_bytes, int byte_alignment ); static void SphereRedraw( void ); static BOOL SphereSetupPixelFormat( HDC hDC ); static LRESULT APIENTRY WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow ) { MSG msg; if ( InitSphere( hInstance, lpszCmdLine ) ) { ShowWindow( s_hWnd, nCmdShow ); UpdateWindow( s_hWnd ); while ( 1 ) { if ( s_benchmark ) { int i; int vertices_to_render = 1000000; int frames_to_render = vertices_to_render / ( s_num_rows * ( s_num_cols * 2 + 2 ) ); if ( frames_to_render < 1 ) frames_to_render = 1; s_start = timeGetTime(); for ( i = 0; i < frames_to_render; i++ ) { SphereRedraw(); } glFinish(); s_stop = timeGetTime(); s_elapsed_time = ( s_stop - s_start ) / 1000.0F; ShutdownSphere(); return 0; } else { while ( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) == FALSE ) { SphereRedraw(); } if ( GetMessage( &msg, NULL, 0, 0 ) != TRUE ) { ShutdownSphere(); return msg.wParam; } TranslateMessage( &msg ); DispatchMessage( &msg ); } } } return 0; } static LRESULT APIENTRY WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch ( msg ) { case WM_CREATE: s_hDC = GetDC( hWnd ); if ( !SphereSetupPixelFormat( s_hDC ) ) exit( 1 ); SphereSetupPalette( s_hDC ); s_hglrc = wglCreateContext( s_hDC ); wglMakeCurrent( s_hDC, s_hglrc ); /* ** see what kind of extensions are supported */ if ( strstr( glGetString( GL_EXTENSIONS ), "GL_SGI_compiled_vertex_array " ) != 0 ) { LockArraysSGI = ( void (APIENTRY *)(GLint, GLint) ) wglGetProcAddress( "glLockArraysSGI" ); UnlockArraysSGI = ( void (APIENTRY *)( void ) ) wglGetProcAddress( "glUnlockArraysSGI" ); } #ifdef GL_SGI_cull_vertex if ( s_vcull ) { if ( strstr( glGetString( GL_EXTENSIONS ), "GL_SGI_cull_vertex" ) ) { if ( ( CullParameterfvSGI = ( void (APIENTRY *)(GLenum, GLfloat*) ) wglGetProcAddress( "glCullParameterfvSGI" ) ) == 0 ) { MessageBox( 0, "-vcull specified but wglGetProcAddress failed", "Sphere Warning", MB_OK | MB_ICONINFORMATION ); s_vcull = FALSE; } } else { s_vcull = FALSE; MessageBox( 0, "-vcull specified but no vcull extension exists", "Sphere Warning", MB_OK | MB_ICONINFORMATION ); } } #endif SphereSetDefaults(); /* ** set vertex and normal array pointers */ if ( s_draw_method == DRAW_ARRAY_ELEMENT ) { glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); glVertexPointer( ELEMENTS_PER_VERTEX, GL_FLOAT, 0, ( const GLvoid * ) s_sphere_point_array ); glNormalPointer( GL_FLOAT, ELEMENTS_PER_NORMAL * sizeof( float ) , ( const GLfloat * ) s_sphere_normal_array ); } else if ( s_draw_method == DRAW_DRAW_ARRAYS ) { glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); } else if ( s_draw_method == DRAW_DRAW_ELEMENTS ) { } { char buffer[1000], buf2[1000]; char *dummy; SearchPath( NULL, "opengl32.dll", NULL, 1000, buffer, &dummy ); sprintf( buf2, "GL Sphere (%s)", buffer ); SetWindowText( hWnd, buf2 ); } return 0; case WM_DESTROY: PostQuitMessage( 0 ); return 0; case WM_CHAR: switch ( wParam ) { case 'd': s_draw_method = DRAW_DRAW_ELEMENTS; glDisableClientState( GL_VERTEX_ARRAY ); glDisableClientState( GL_NORMAL_ARRAY ); break; case 'a': s_draw_method = DRAW_DRAW_ARRAYS; glEnableClientState( GL_VERTEX_ARRAY ); glEnableClientState( GL_NORMAL_ARRAY ); break; case 'l': s_lock_arrays = !s_lock_arrays; break; case 27: PostQuitMessage( 0 ); return 0; } break; case WM_SIZE: if ( s_hglrc ) { int winWidth = ( int ) LOWORD( lParam ); int winHeight = ( int ) HIWORD( lParam ); glViewport( 0, 0, winWidth, winHeight ); } return 0; case WM_PALETTECHANGED: if (s_hPalette != NULL && (HWND) wParam != hWnd) { UnrealizeObject( s_hPalette ); SelectPalette( s_hDC, s_hPalette, FALSE ); RealizePalette( s_hDC ); return 0; } break; case WM_QUERYNEWPALETTE: if ( s_hPalette != NULL ) { UnrealizeObject( s_hPalette ); SelectPalette( s_hDC, s_hPalette, FALSE ); RealizePalette( s_hDC ); return TRUE; } break; case WM_COMMAND: break; } return DefWindowProc( hWnd, msg, wParam, lParam); } static BOOL InitSphere( HINSTANCE hInstance, LPSTR lpszCmdLine ) { WNDCLASS wc; wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = GetStockObject(WHITE_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = s_class_name; RegisterClass( &wc ); { HDC hdc = GetDC( 0 ); s_bpp = GetDeviceCaps( hdc, BITSPIXEL ); #if NOTYET if ( ( s_bpp <= 8 ) && !strstr( lpszCmdLine, "-332" ) ) s_rgba = 0; else #endif s_rgba = 1; ReleaseDC( 0, hdc ); } /* ** check to see how to draw the sphere */ if ( strstr( lpszCmdLine, "-arrayelement" ) ) s_draw_method = DRAW_ARRAY_ELEMENT; else if ( strstr( lpszCmdLine, "-drawarrays" ) ) s_draw_method = DRAW_DRAW_ARRAYS; else if ( strstr( lpszCmdLine, "-drawelements" ) ) s_draw_method = DRAW_DRAW_ELEMENTS; else s_draw_method = DRAW_VERTEX3FV; if ( strstr( lpszCmdLine, "-benchmark" ) ) s_benchmark = TRUE; if ( strstr( lpszCmdLine, "-remote" ) ) s_remote = TRUE; if ( strstr( lpszCmdLine, "-rows:" ) ) { s_num_rows = atoi( strchr( strstr( lpszCmdLine, "-rows:" ), ':' ) + 1 ); } if ( strstr( lpszCmdLine, "-cols:" ) ) { s_num_cols = atoi( strchr( strstr( lpszCmdLine, "-cols:" ), ':' ) + 1 ); } if ( strstr( lpszCmdLine, "-nolockarrays" ) ) s_lock_arrays = FALSE; if ( strstr( lpszCmdLine, "-novcull" ) ) s_vcull = FALSE; if ( strstr( lpszCmdLine, "-?" ) || strstr( lpszCmdLine, "/?" ) ) { SphereHelp(); return FALSE; } if ( strstr( lpszCmdLine, "-width:" ) ) s_winwidth = atoi( strchr( strstr( lpszCmdLine, "-width:" ), ':' ) + 1 ); if ( strstr( lpszCmdLine, "-height:" ) ) s_winheight = atoi( strchr( strstr( lpszCmdLine, "-height:" ), ':' ) + 1 ); /* ** create geometry */ if ( !SphereCreateGeometry( s_num_rows, s_num_cols, 1.0F ) ) return FALSE; /* ** create a window of the previously defined class */ s_hWnd = CreateWindow( s_class_name, s_window_name, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 10, 10, s_winwidth, s_winheight, NULL, NULL, hInstance, NULL ); if ( s_hWnd != NULL ) return TRUE; return FALSE; } void ShutdownSphere( void ) { if ( s_benchmark && !s_remote ) { char buffer[1000]=""; char temp[100]; sprintf( temp, "Vendor: %s\n\n", glGetString( GL_VENDOR ) ); strcat( buffer, temp ); sprintf( temp, "%.2f vertices/second\n", s_vertices_processed / s_elapsed_time ); strcat( buffer, temp ); sprintf( temp, "%.2f triangles/second\n", s_triangles_processed / s_elapsed_time ); strcat( buffer, temp ); MessageBox( 0, buffer, "Performance", MB_OK | MB_ICONINFORMATION ); } if ( s_hglrc ) { wglMakeCurrent( NULL, NULL ); wglDeleteContext( s_hglrc ); } ReleaseDC( s_hWnd, s_hDC ); } static BOOL SphereSetupPixelFormat( HDC hDC ) { unsigned char pixelType = s_rgba ? PFD_TYPE_RGBA : PFD_TYPE_COLORINDEX; PIXELFORMATDESCRIPTOR pfd = { sizeof( PIXELFORMATDESCRIPTOR ), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, pixelType, s_bpp, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, // 16-bit depth buffer 0, // no stencil buffer 0, // no aux buffers PFD_MAIN_PLANE, /* main layer */ 0, 0, 0, 0 }; int selected_pf; if ( ( selected_pf = ChoosePixelFormat( hDC, &pfd ) ) == 0 ) { MessageBox( 0, "Failed to find acceptable pixel format", "GL Sphere Error", MB_ICONERROR | MB_OK ); return FALSE; } if ( !SetPixelFormat( hDC, selected_pf, &pfd) ) { MessageBox( 0, "Failed to SetPixelFormat", "GL Sphere Error", MB_ICONERROR | MB_OK ); return FALSE; } return TRUE; } static void SphereSetDefaults( void ) { // setup a default color glColor3f( 1.0F, 1.0F, 1.0F ); glClearColor( 0.0F, 0.0F, 1.0F, 1.0F ); #if 0 glClearDepth( 1.0F ); glDepthFunc( GL_LEQUAL ); glEnable( GL_DEPTH_TEST ); glDepthMask( GL_TRUE ); #endif // setup perspective glMatrixMode( GL_PROJECTION ); glFrustum( -0.5, 0.5, -0.5, 0.5, 1.0, 1000.0 ); // setup viewer glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.0F, 0.0F, -3.0F ); // setup Z-buffering // setup shade model glShadeModel( GL_SMOOTH ); // setup lighting if ( !s_lighting ) { glDisable( GL_LIGHTING ); glDisable( GL_LIGHT0 ); } else { GLfloat light0Pos[4] = { 0.70F, 0.70F, 1.25F, 0.00F }; GLfloat matAmb[4] = { 0.01F, 0.01F, 0.01F, 1.00F }; GLfloat matDiff[4] = { 0.65F, 0.05F, 0.20F, 0.60F }; GLfloat matSpec[4] = { 0.50F, 0.50F, 0.50F, 1.00F }; GLfloat matShine = 20.00F; glEnable( GL_LIGHTING ); glEnable( GL_LIGHT0 ); glLightfv(GL_LIGHT0, GL_POSITION, light0Pos); glMaterialfv(GL_FRONT, GL_AMBIENT, matAmb); glMaterialfv(GL_FRONT, GL_DIFFUSE, matDiff); glMaterialfv(GL_FRONT, GL_SPECULAR, matSpec); glMaterialf(GL_FRONT, GL_SHININESS, matShine); } // setup cull mode glEnable( GL_CULL_FACE ); #ifdef GL_SGI_cull_vertex if ( s_vcull ) { GLfloat eyeDir[] = { 0.0F, 0.0F, 1.0F, 0.0F }; glEnable(GL_CULL_VERTEX_SGI); if ( CullParameterfvSGI ) CullParameterfvSGI( GL_CULL_VERTEX_EYE_POSITION_SGI, eyeDir ); } else { glDisable(GL_CULL_VERTEX_SGI); } #endif // setup dither glEnable( GL_DITHER ); glClear( GL_COLOR_BUFFER_BIT ); SwapBuffers( s_hDC ); } static BOOL SphereCreateGeometry( int rows, int cols, float scale ) { float cap_offset = 10.0F; float x_delta = ( 360.0F - 2.0f * cap_offset ) / cols; float y_delta = ( 180.0F - 2.0f * cap_offset ) / rows; int row, col; int num_vertex_rows = rows + 1; int num_vertex_cols = cols; float *spa, *sna, *sia; s_sphere_points = ( float ** ) AllocAlignedX( sizeof( float ) * num_vertex_rows, BYTES_PER_CACHELINE ); s_sphere_normals = ( float ** ) AllocAlignedX( sizeof( float ) * num_vertex_rows, BYTES_PER_CACHELINE ); spa = s_sphere_point_array = ( float * ) AllocAlignedX( sizeof( float ) * ELEMENTS_PER_VERTEX * num_vertex_rows * num_vertex_cols, BYTES_PER_CACHELINE ); sna = s_sphere_normal_array = ( float * ) AllocAlignedX( sizeof( float ) * ELEMENTS_PER_NORMAL * num_vertex_rows * num_vertex_cols, BYTES_PER_CACHELINE ); if ( !s_sphere_points || !s_sphere_normals || !s_sphere_point_array || !s_sphere_normal_array ) return FALSE; for ( row = 0; row < num_vertex_rows; row++ ) { s_sphere_points[row] = ( float * ) AllocAlignedX( sizeof( float ) * num_vertex_cols * ELEMENTS_PER_VERTEX, BYTES_PER_CACHELINE ); s_sphere_normals[row] = ( float * ) AllocAlignedX( sizeof( float ) * num_vertex_cols * ELEMENTS_PER_NORMAL, BYTES_PER_CACHELINE ); } for ( row = 0; row < num_vertex_rows; row++ ) { float rowangle; rowangle = row*y_delta + cap_offset; for ( col = 0; col < num_vertex_cols; col++ ) { float colangle; colangle = col*x_delta; spa[0] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+0] = ( float ) ( sin( DEG2RAD( colangle ) ) * sin ( DEG2RAD( rowangle ) ) * scale ); spa[1] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+1] = ( float ) ( sin( DEG2RAD( rowangle + 270.0F ) ) * scale ); spa[2] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+2] = ( float ) ( sin( DEG2RAD( colangle + 270.0F ) ) * sin ( DEG2RAD( rowangle ) ) * scale ); #if ( ELEMENTS_PER_VERTEX == 4 ) spa[3] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+3] = 1.0F; #endif spa += ELEMENTS_PER_VERTEX; sna[0] = s_sphere_normals[row][col*ELEMENTS_PER_NORMAL+0] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+0]; sna[1] = s_sphere_normals[row][col*ELEMENTS_PER_NORMAL+1] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+1]; sna[2] = s_sphere_normals[row][col*ELEMENTS_PER_NORMAL+2] = s_sphere_points[row][col*ELEMENTS_PER_VERTEX+2]; #if ( ELEMENTS_PER_NORMAL == 4 ) sna[3] = s_sphere_normals[row][col*ELEMENTS_PER_NORMAL+3] = 1.0F; #endif SphereNormalizeVector( &s_sphere_normals[row][col*ELEMENTS_PER_NORMAL] ); SphereNormalizeVector( sna ); sna += ELEMENTS_PER_NORMAL; } } /* ** create the draw arrays data */ s_sphere_point_draw_array = ( float ** ) AllocAlignedX( sizeof( float * ) * s_num_rows, BYTES_PER_CACHELINE ); s_sphere_normal_draw_array = ( float ** ) AllocAlignedX( sizeof( float * ) * s_num_rows, BYTES_PER_CACHELINE ); for ( row = 0; row < s_num_rows; row++ ) { s_sphere_point_draw_array[row] = ( float * ) AllocAlignedX( sizeof( float ) * ELEMENTS_PER_VERTEX * ( s_num_cols + 1 ) * 2, BYTES_PER_CACHELINE ); s_sphere_normal_draw_array[row] = ( float * ) AllocAlignedX( sizeof( float ) * ELEMENTS_PER_NORMAL * ( s_num_cols + 1 ) * 2, BYTES_PER_CACHELINE ); } for ( row = 0; row < s_num_rows; row++ ) { for ( col = 0; col < s_num_cols; col++ ) { float *pdst, *psrc; pdst = &s_sphere_point_draw_array[row][col*2*ELEMENTS_PER_VERTEX]; psrc = &s_sphere_points[row][col*ELEMENTS_PER_VERTEX]; memcpy( pdst, psrc, sizeof( float ) * ELEMENTS_PER_VERTEX ); pdst = &s_sphere_point_draw_array[row][(col*2+1)*ELEMENTS_PER_VERTEX]; psrc = &s_sphere_points[row+1][col*ELEMENTS_PER_VERTEX]; memcpy( pdst, psrc, sizeof( float ) * ELEMENTS_PER_VERTEX ); pdst = &s_sphere_normal_draw_array[row][col*2*ELEMENTS_PER_NORMAL]; psrc = &s_sphere_normals[row][col*ELEMENTS_PER_NORMAL]; memcpy( pdst, psrc, sizeof( float ) * ELEMENTS_PER_NORMAL ); pdst = &s_sphere_normal_draw_array[row][(col*2+1)*ELEMENTS_PER_NORMAL]; psrc = &s_sphere_normals[row+1][col*ELEMENTS_PER_NORMAL]; memcpy( pdst, psrc, sizeof( float ) * ELEMENTS_PER_NORMAL ); } memcpy( &s_sphere_point_draw_array[row][s_num_cols*2*ELEMENTS_PER_VERTEX], &s_sphere_points[row][0], sizeof( float ) * ELEMENTS_PER_VERTEX ); memcpy( &s_sphere_point_draw_array[row][(s_num_cols*2+1)*ELEMENTS_PER_VERTEX], &s_sphere_points[row+1][0], sizeof( float ) * ELEMENTS_PER_VERTEX ); memcpy( &s_sphere_normal_draw_array[row][s_num_cols*2*ELEMENTS_PER_NORMAL], &s_sphere_normals[row][0], sizeof( float ) * ELEMENTS_PER_NORMAL ); memcpy( &s_sphere_normal_draw_array[row][(s_num_cols*2+1)*ELEMENTS_PER_NORMAL], &s_sphere_normals[row+1][0], sizeof( float ) * ELEMENTS_PER_NORMAL ); } /* ** create the draw elements data */ s_sphere_elements = ( unsigned int ** ) malloc( sizeof( unsigned int * ) * s_num_rows ); for ( row = 0; row < s_num_rows; row++ ) { s_sphere_elements[row] = ( unsigned int * ) malloc( sizeof( unsigned int ) * ( 2 * s_num_cols + 2 ) ); } for ( row = 0; row < s_num_rows; row++ ) { for ( col = 0; col < s_num_cols*2; col += 2 ) { s_sphere_elements[row][col] = row * s_num_cols + col/2; s_sphere_elements[row][col+1] = ( row + 1 ) * s_num_cols + col/2; } s_sphere_elements[row][s_num_cols*2] = row * s_num_cols; s_sphere_elements[row][s_num_cols*2+1] = ( row + 1 ) * s_num_cols; } sia = s_sphere_interleaved_array = ( float * ) malloc( sizeof( float ) * ELEMENTS_PER_VERTEX * ELEMENTS_PER_NORMAL * ( s_num_rows + 1 ) * ( s_num_cols + 1 ) ); memset( s_sphere_interleaved_array, 0, sizeof( float ) * ELEMENTS_PER_VERTEX * ELEMENTS_PER_NORMAL * ( s_num_rows + 1 ) * ( s_num_cols + 1 ) ); for ( row = 0; row < num_vertex_rows; row++ ) { for ( col = 0; col < s_num_cols; col++ ) { memcpy( sia, &s_sphere_normals[row][col*ELEMENTS_PER_NORMAL], sizeof( float ) * ELEMENTS_PER_NORMAL ); sia += ELEMENTS_PER_NORMAL; memcpy( sia, &s_sphere_points[row][col*ELEMENTS_PER_VERTEX], sizeof( float ) * ELEMENTS_PER_VERTEX ); sia += ELEMENTS_PER_VERTEX; } } return TRUE; } static void SphereRedraw( void ) { int row, col; if ( !s_benchmark ) glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); glRotatef( 1.0f, 0.0F, 1.0F, 0.0F ); glRotatef( 1.0f, 1.0F, 0.0F, 0.0F ); if ( s_draw_method == DRAW_VERTEX3FV ) { for ( row = 0; row < s_num_rows; row++ ) { glBegin( GL_TRIANGLE_STRIP ); for ( col = 0; col < s_num_cols; col++ ) { glNormal3fv( &s_sphere_normals[row][col*ELEMENTS_PER_NORMAL] ); glVertex3fv( &s_sphere_points[row][col*ELEMENTS_PER_VERTEX] ); glNormal3fv( &s_sphere_normals[row+1][col*ELEMENTS_PER_NORMAL] ); glVertex3fv( &s_sphere_points[row+1][col*ELEMENTS_PER_VERTEX] ); } glNormal3fv( &s_sphere_normals[row][0] ); glVertex3fv( &s_sphere_points[row][0] ); glNormal3fv( &s_sphere_normals[row+1][0] ); glVertex3fv( &s_sphere_points[row+1][0] ); glEnd(); } } else if ( s_draw_method == DRAW_DRAW_ARRAYS ) { for ( row = 0; row < s_num_rows; row++ ) { glVertexPointer( ELEMENTS_PER_VERTEX, GL_FLOAT, ELEMENTS_PER_VERTEX * sizeof( float ), ( const GLvoid * ) s_sphere_point_draw_array[row] ); glNormalPointer( GL_FLOAT, ELEMENTS_PER_NORMAL * sizeof( float ), ( const GLfloat * ) s_sphere_normal_draw_array[row] ); glDrawArrays( GL_TRIANGLE_STRIP, 0, (s_num_cols+1)*2 ); } } else if ( s_draw_method == DRAW_ARRAY_ELEMENT ) { for ( row = 0; row < s_num_rows; row++ ) { glBegin( GL_TRIANGLE_STRIP ); for ( col = 0; col < s_num_cols; col++ ) { glArrayElement( col + row*s_num_cols ); glArrayElement( col + (row+1)*s_num_cols ); } glArrayElement( row*s_num_cols ); glArrayElement( (row+1)*s_num_cols ); glEnd(); } } else if ( s_draw_method == DRAW_DRAW_ELEMENTS ) { glInterleavedArrays( GL_N3F_V3F, ( ELEMENTS_PER_VERTEX + ELEMENTS_PER_NORMAL ) * sizeof( float ), s_sphere_interleaved_array ); if ( LockArraysSGI && s_lock_arrays ) { LockArraysSGI( 0, ( s_num_rows + 1 ) * ( s_num_cols + 1 ) ); } for ( row = 0; row < s_num_rows; row++ ) { glDrawElements( GL_TRIANGLE_STRIP, (s_num_cols+1)*2, GL_UNSIGNED_INT, s_sphere_elements[row] ); } if ( UnlockArraysSGI && s_lock_arrays ) { UnlockArraysSGI(); } } s_vertices_processed += ( ( s_num_rows + 1 ) * ( s_num_cols ) ); s_triangles_processed += ( s_num_rows * s_num_cols ); if ( !s_benchmark ) SwapBuffers( s_hDC ); } static void SphereNormalizeVector( float v[3] ) { float m = 1.0F / ( float ) ( sqrt( v[0] * v[0] + v[1] * v[1] + v[2] * v[2] ) ); v[0] *= m; v[1] *= m; v[2] *= m; } static void *AllocAlignedX( int num_bytes, int byte_alignment ) { void *buf = malloc( num_bytes + byte_alignment ); unsigned long q = ( unsigned long ) buf; q += byte_alignment; q &= ~( byte_alignment - 1 ); return ( void * ) q; } static void SphereHelp( void ) { char superbuffer[1000]= "-?\t\tthis help screen\n" "-arrayelements\tuse glArrayElement\n" "-drawelements\tuse glDrawElements\n" "-drawarrays\tuse glDrawArrays\n" "-tristrip\t\tuse triangle strips w/ glVertex3fv\n" "-vcull\t\tuse SGI's vertex culling extension\n" "-lockarrays\tuse SGI's lock arrays extension when doing drawelements\n\n" "-cols:val\t\tspecify number of vertical (longitudinal) bands in sphere\n" "-rows:val\t\tspecify number of horizontal (latitudinal) bands in sphere\n\n" "-width:val\t\twidth of window, in pixels (default is 320)\n" "-height:val\t\theight of window, in pixels (default is 240)\n\n" "-benchmark\trun as benchmark and immediately quit when done\n" "-remote\t\tdon't print performance data\n"; MessageBox( 0, superbuffer, "Sphere, Copyright (C) 1997 Silicon Graphics, Inc.", MB_OK | MB_ICONINFORMATION ); } static void SphereSetupPalette( HDC hDC ) { PIXELFORMATDESCRIPTOR pfd; LOGPALETTE *pPal; int paletteSize; int pixelFormat = GetPixelFormat(hDC); DescribePixelFormat( hDC, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); if (!(pfd.dwFlags & PFD_NEED_PALETTE || pfd.iPixelType == PFD_TYPE_COLORINDEX)) return; paletteSize = 1 << pfd.cColorBits; pPal = (LOGPALETTE * ) malloc( sizeof(LOGPALETTE) + paletteSize * sizeof(PALETTEENTRY) ); pPal->palVersion = 0x300; pPal->palNumEntries = paletteSize; /* start with a copy of the current system palette */ GetSystemPaletteEntries( hDC, 0, paletteSize, &pPal->palPalEntry[0] ); if ( pfd.iPixelType == PFD_TYPE_RGBA ) { /* fill in an RGBA color palette */ int redMask = (1 << pfd.cRedBits) - 1; int greenMask = (1 << pfd.cGreenBits) - 1; int blueMask = (1 << pfd.cBlueBits) - 1; int i; for (i=0; i<paletteSize; ++i) { pPal->palPalEntry[i].peRed = (((i >> pfd.cRedShift) & redMask) * 255) / redMask; pPal->palPalEntry[i].peGreen = (((i >> pfd.cGreenShift) & greenMask) * 255) / greenMask; pPal->palPalEntry[i].peBlue = (((i >> pfd.cBlueShift) & blueMask) * 255) / blueMask; pPal->palPalEntry[i].peFlags = 0; } } else { /* fill in a Color Index ramp color palette */ int numRamps = NUM_COLORS; int rampSize = (paletteSize - 20) / numRamps; int extra = (paletteSize - 20) - (numRamps * rampSize); int i, r; for (r=0; r<numRamps; ++r) { int rampBase = r * rampSize + 10; PALETTEENTRY *pe = &pPal->palPalEntry[rampBase]; int diffSize = (int) (rampSize * s_colors[r].ratio); int specSize = rampSize - diffSize; for (i=0; i<rampSize; ++i) { GLfloat *c0, *c1; GLint a; if (i < diffSize) { c0 = s_colors[r].amb; c1 = s_colors[r].diff; a = (i * 255) / (diffSize - 1); } else { c0 = s_colors[r].diff; c1 = s_colors[r].spec; a = ((i - diffSize) * 255) / (specSize - 1); } pe[i].peRed = (BYTE) (a * (c1[0] - c0[0]) + 255 * c0[0]); pe[i].peGreen = (BYTE) (a * (c1[1] - c0[1]) + 255 * c0[1]); pe[i].peBlue = (BYTE) (a * (c1[2] - c0[2]) + 255 * c0[2]); pe[i].peFlags = PC_NOCOLLAPSE; } s_colors[r].indexes[0] = rampBase; s_colors[r].indexes[1] = rampBase + (diffSize-1); s_colors[r].indexes[2] = rampBase + (rampSize-1); } s_lit_tex_indexes[0] = 0; s_lit_tex_indexes[1] = (GLint)(rampSize*s_colors[0].ratio)-1; s_lit_tex_indexes[2] = rampSize-1; for (i=0; i<extra; ++i) { int index = numRamps*rampSize+10+i; PALETTEENTRY *pe = &pPal->palPalEntry[index]; pe->peRed = (BYTE) 0; pe->peGreen = (BYTE) 0; pe->peBlue = (BYTE) 0; pe->peFlags = PC_NOCOLLAPSE; } } s_hPalette = CreatePalette( pPal ); free( pPal ); if ( s_hPalette ) { SelectPalette( hDC, s_hPalette, FALSE ); RealizePalette( hDC ); } }