2 #include <SDL_opengl.h>
12 //#define AA //anti-aliasing
14 void viewport(Display
*display
, GLsizei w
, GLsizei h
, GLsizei bpp
)
17 bpp
= display
->screen
->format
->BitsPerPixel
;
20 SDL_GL_SetAttribute( SDL_GL_RED_SIZE
, bpp
/3 );
21 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE
, bpp
/3 );
22 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE
, bpp
/3 );
23 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE
, 16 );
24 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER
, 1 );
26 SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS
, 1 );
27 SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES
, 4 );
29 display
->screen
= SDL_SetVideoMode(w
, h
, bpp
, SDL_HWSURFACE
|SDL_OPENGLBLIT
|SDL_RESIZABLE
);
30 if(display
->screen
== NULL
) goto error
;
31 //printf("%dx%dx%d\n", display->screen->w, display->screen->h, display->screen->format->BitsPerPixel);
35 SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS
, &arg
);
36 //printf("SDL_GL_MULTISAMPLEBUFFERS %d\n", arg);
37 SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES
, &arg
);
38 //printf("SDL_GL_MULTISAMPLESAMPLES %d\n", arg);
44 glMatrixMode(GL_PROJECTION
);
46 gluPerspective(45,-w
/(GLfloat
)h
,display
->near_plane
,display
->far_plane
);
50 glClearColor(0,0,0,0);
52 glDepthFunc(GL_LEQUAL
);
53 glEnable(GL_DEPTH_TEST
);
54 //glEnable(GL_CULL_FACE);
55 //glCullFace(GL_BACK);
56 glShadeModel(GL_SMOOTH
);
57 //glShadeModel(GL_FLAT);
58 glHint(GL_PERSPECTIVE_CORRECTION_HINT
, GL_NICEST
);
59 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
63 glFogi(GL_FOG_MODE
, GL_LINEAR
);
64 GLfloat fog_color
[] = {0,0,0,1};
65 glFogfv(GL_FOG_COLOR
, fog_color
);
66 glFogf(GL_FOG_START
, display
->near_plane
);
67 glFogf(GL_FOG_END
, display
->far_plane
);
73 #ifndef GL_ARB_multisample
74 glHint(GL_MULTISAMPLE_FILTER_HINT_NV
,GL_NICEST
);
76 glEnable(GL_MULTISAMPLE_ARB
);
81 fprintf(stderr
, "SDL ERROR: %s\n", SDL_GetError());
85 void cave_model(Display
*display
, Cave
*cave
)
92 for( j
= 0; j
< CAVE_DEPTH
-1; ++j
) {
93 int j0
= (cave
->i
+ j
)%CAVE_DEPTH
;
94 if( cave
->gl_list
[j0
] != 0 ) {
95 glCallList( cave
->gl_list
[j0
] );
98 cave
->gl_list
[j0
] = j0
+ display
->list_start
;
99 glNewList( cave
->gl_list
[j0
], GL_COMPILE_AND_EXECUTE
);
101 int j1
= (j0
+ 1)%CAVE_DEPTH
;
102 glBegin(GL_TRIANGLE_STRIP
);
103 for( i
= 0; i
<= N_SEGS
; ++i
) {
107 glColor4f(.4, .6*i0
/N_SEGS
, .9*j1
/CAVE_DEPTH
, 1);
108 glVertex3fv(cave
->segs
[j0
][i0
]);
110 glColor4f(.6, .6*i0
/N_SEGS
, .9*(1-j0
/CAVE_DEPTH
), 1);
111 glVertex3fv(cave
->segs
[j1
][i0
]);
113 if(cave
->segs
[j
][i0
][1] < cave
->ymin
)
114 cave
->ymin
= cave
->segs
[j
][i0
][1];
115 if(cave
->segs
[j
][i0
][1] > cave
->ymax
)
116 cave
->ymax
= cave
->segs
[j
][i0
][1];
127 void ship_model(Ship
*ship
)
131 void render_text(Display
*display
, const char *text
, float x
, float y
)
133 if(text
== NULL
|| text
[0] == '\0')
136 SDL_Color color
= {0xff,0xff,0xff,0xff};
137 SDL_Surface
*label
= TTF_RenderText_Blended(display
->font
, text
, color
);
138 assert(label
!= NULL
);
140 display
->rect
[display
->rect_n
].w
= label
->w
;
141 display
->rect
[display
->rect_n
].h
= label
->h
;
142 display
->rect
[display
->rect_n
].x
= (int)(x
*display
->screen
->w
- .5*label
->w
);
143 display
->rect
[display
->rect_n
].y
= (int)(y
*display
->screen
->h
- .5*label
->h
);
145 SDL_FillRect(display
->screen
, &display
->rect
[display
->rect_n
],
146 SDL_MapRGBA(display
->screen
->format
, 0x00,0x00,0x80,0xff));
147 SDL_BlitSurface(label
, NULL
, display
->screen
, &display
->rect
[display
->rect_n
]);
149 SDL_FreeSurface(label
);
154 void display_hud(Display
*display
, Ship
*player
)
156 #define HUD_TEXT_MAX 80
157 char buf
[HUD_TEXT_MAX
];
158 float wow_factor
= 20.0;
159 snprintf(buf
, HUD_TEXT_MAX
, "collision %.1f velocity %.2fKm/h score %.1f",
160 player
->dist
, wow_factor
*LEN(player
->vel
), player
->pos
[2]);
163 render_text(display
, buf
, .5, .95);
165 static Uint32 last_hud_print
= 0;
166 Uint32 now
= SDL_GetTicks();
167 if( now
- last_hud_print
>= 200 ) {
168 last_hud_print
= now
;
175 char display_message_buf
[256];
176 void display_message(Display
*display
, Cave
*cave
, Ship
*player
, const char *buf
)
178 strncpy(display_message_buf
, buf
, sizeof(display_message_buf
)-1);
179 display_message_buf
[sizeof(display_message_buf
)-1] = '\0';
181 display_frame(display
, cave
, player
);
183 printf("\n%s\n", display_message_buf
);
187 void display_start_frame(Display
*display
, Ship
*player
)
190 COPY(display
->cam
, player
->pos
);
191 SET(display
->target
, player
->pos
[0], player
->pos
[1], player
->pos
[2]+1);
192 //ADD2(display->target, player->pos, player->vel);
194 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
195 glMatrixMode(GL_MODELVIEW
);
199 display
->cam
[0], display
->cam
[1], display
->cam
[2],
200 display
->target
[0], display
->target
[1], display
->target
[2],
205 display
->cam
[0], display
->cam
[1], display
->cam
[2],
206 display
->target
[0], display
->target
[1], display
->target
[2],
212 void display_end_frame(Display
*display
)
216 SDL_UpdateRects(display
->screen
, display
->rect_n
, display
->rect
); // only update 2D
218 SDL_GL_SwapBuffers(); // update 3d
221 void display_frame(Display
*display
, Cave
*cave
, Ship
*player
)
223 display_start_frame(display
, player
);
224 cave_model(display
, cave
);
226 display_hud(display
, player
);
227 display_minimap(display
, cave
, player
);
228 render_text(display
, display_message_buf
, .5, .5);
229 display_end_frame(display
);
232 void display_init(Display
*display
)
235 if(SDL_Init(SDL_INIT_VIDEO
) != 0) {
236 fprintf(stderr
, "SDL_Init(): %s\n", SDL_GetError());
242 display
->near_plane
= SHIP_RADIUS
/2.; // was EPSILON;
243 display
->far_plane
= CAVE_DEPTH
* SEGMENT_LEN
;
244 SET(display
->cam
,0,0,0);
245 SET(display
->target
,0,0,1);
247 viewport(display
,640,480,16);
248 display
->list_start
= glGenLists( CAVE_DEPTH
);
251 if(TTF_Init() != 0) {
252 fprintf(stderr
, "TTF_Init(): %s\n", TTF_GetError());
257 char* font_filename
= "font.pcf";
259 display
->font
= TTF_OpenFont(font_filename
, font_size
); // FIXME path
260 if(display
->font
== NULL
) {
261 fprintf(stderr
, "TTF_OpenFont(%s): %s\n", font_filename
, TTF_GetError());
266 display
->minimap
= SDL_CreateRGBSurface( SDL_SWSURFACE
,
267 CAVE_DEPTH
*2, CAVE_DEPTH
*2,
268 display
->screen
->format
->BitsPerPixel
,
270 assert( display
->minimap
!= NULL
);
273 void display_minimap(Display
*display
, Cave
*cave
, Ship
*player
)
275 SDL_FillRect( display
->minimap
, 0, 0 );
279 for( i
= 0; i
< CAVE_DEPTH
; ++i
) {
280 int j
= ((i
+cave
->i
) % CAVE_DEPTH
);
281 float y1
= cave
->segs
[j
][1*N_SEGS
/4][1];
282 float y0
= cave
->segs
[j
][3*N_SEGS
/4][1];
286 rect
.y
= (int)(cave
->ymax
- y1
);
287 rect
.h
= (int)(y1
- y0
);
288 SDL_FillRect( display
->minimap
, &rect
, 0xffffffff );
293 rect
.x
= (int)(2*(player
->pos
[2] - cave
->segs
[cave
->i
][0][2]));
294 rect
.x
= 2; //HACK: smooth. TODO: properly smooth cave and ship.
296 rect
.y
= (int)(cave
->ymax
- player
->pos
[1]);
298 SDL_FillRect( display
->minimap
, &rect
, 0 );
302 // blit minimap to screen
305 rect
.w
= display
->minimap
->w
;
307 rect
.h
= (int)(cave
->ymax
- cave
->ymin
);
309 SDL_Rect
*d_rect
= &display
->rect
[display
->rect_n
++];
310 d_rect
->x
= display
->screen
->w
- display
->minimap
->w
;
311 d_rect
->w
= display
->minimap
->w
;
313 d_rect
->h
= (int)(cave
->ymax
- cave
->ymin
);
314 SDL_BlitSurface(display
->minimap
, &rect
, display
->screen
, d_rect
);
317 // vim600:fdm=syntax:fdn=1: