merge pixmap handling from sampler, material.h and ccdemos's image module to new Pixmap class
add check for PNG library, allow writing PNG file from a Pixmap
simplify demos using new methods from Sampler and Pixmap
#include <SDL.h>
Uint32 fp10s_acc = 0;
Uint32 fp10s_acc_samples = 0;
int w = 512;
int h = 384;
void update(Raytracer &rt, SDL_Surface *screen, Float *render_buffer)
{
static Uint32 t = 0;
Uint32 tnow = SDL_GetTicks();
int fp10s = 10000/(int)(tnow - t);
if (t != 0)
{
fp10s_acc += fp10s;
++fp10s_acc_samples;
}
t = tnow;
char s[40];
sprintf(s, "fps:%3d.%1d", fp10s/10, fp10s%10);
SDL_WM_SetCaption(s, NULL);
rt.render();
if (SDL_MUSTLOCK(screen))
if (SDL_LockSurface(screen) < 0)
return;
Uint32 *bufp = (Uint32 *)screen->pixels;
unsigned char c[3];
for (Float *fd = render_buffer; fd != render_buffer + w*h*3; fd += 3)
{
for (int i = 0; i < 3; i++)
{
if (fd[i] > 1.0)
c[i] = 255;
else
c[i] = (unsigned char)(fd[i] * 255.0);
}
*bufp = SDL_MapRGB(screen->format, c[0], c[1], c[2]);
bufp++;
}
if (SDL_MUSTLOCK(screen))
SDL_UnlockSurface(screen);
if (screen->flags & SDL_DOUBLEBUF)
SDL_Flip(screen);
else
SDL_UpdateRect(screen, 0, 0, w, h);
}
void loop_sdl(Raytracer &rt, Camera &cam,
void (*update_callback)(Float*) = NULL, void (*key_callback)(int, int) = NULL)
{
SDL_Surface *screen;
Float *render_buffer;
pyrit_verbosity = 0;
render_buffer = (Float *) malloc(w*h*3*sizeof(Float));
DefaultSampler sampler(render_buffer, w, h);
rt.setSampler(&sampler);
if( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
exit(1);
}
screen = SDL_SetVideoMode(w, h, 32, SDL_SWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE);
if ( screen == NULL ) {
fprintf(stderr, "Unable to set video mode: %s\n", SDL_GetError());
exit(1);
}
SDL_Event event;
bool quit = false;
Float roty = 0.0, rotx = 0.0, move = 0.0;
while (!quit)
{
while (SDL_PollEvent(&event))
{
switch (event.type) {
case SDL_VIDEORESIZE:
w = (event.resize.w-1) / 8 * 8 + 8;
h = (event.resize.h-1) / 8 * 8 + 8;
render_buffer = (Float *) realloc(render_buffer, w*h*3*sizeof(Float));
sampler.resetBuffer(render_buffer, w, h);
screen = SDL_SetVideoMode(w, h, 32, SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_RESIZABLE);
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) {
quit = true;
break;
}
if (event.key.keysym.sym == SDLK_LEFT) {
roty = +0.01;
break;
}
if (event.key.keysym.sym == SDLK_RIGHT) {
roty = -0.01;
break;
}
if (event.key.keysym.sym == SDLK_DOWN) {
rotx = +0.01;
break;
}
if (event.key.keysym.sym == SDLK_UP) {
rotx = -0.01;
break;
}
if (event.key.keysym.sym == SDLK_w) {
move = +0.5;
break;
}
if (event.key.keysym.sym == SDLK_s) {
move = -0.5;
break;
}
if (event.key.keysym.sym == SDLK_c) {
// print camera coordinates
cout << "Camera: eye=" << cam.eye
<< ", p=" << cam.p
<< ", u=" << cam.u
<< ", v=" << cam.v
<< endl;
break;
}
if (key_callback != NULL)
key_callback(event.key.keysym.sym, 1);
break;
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_LEFT || event.key.keysym.sym == SDLK_RIGHT) {
roty = 0.0;
break;
}
if (event.key.keysym.sym == SDLK_UP || event.key.keysym.sym == SDLK_DOWN) {
rotx = 0.0;
break;
}
if (event.key.keysym.sym == SDLK_w || event.key.keysym.sym == SDLK_s) {
move = 0.0;
break;
}
if (key_callback != NULL)
key_callback(event.key.keysym.sym, 0);
break;
case SDL_QUIT:
quit = true;
}
}
cam.rotate(Quaternion(cos(roty),0,sin(roty),0).normalize());
cam.rotate(Quaternion(cos(rotx),cam.u[0]*sin(rotx),0,cam.u[2]*sin(rotx)).normalize());
cam.u.y = 0;
cam.u.normalize();
if (move != 0.0)
cam.move(move,0,0);
if (update_callback != NULL)
update_callback(render_buffer);
update(rt, screen, render_buffer);
}
free(render_buffer);
Uint32 fp100s_aver = fp10s_acc*10/fp10s_acc_samples;
printf("averlage fps: %3d.%2d\n\n", fp100s_aver/100, fp100s_aver%100);
SDL_Quit();
}