/*
**  wt -- a 3d game engine
**
**  Copyright (C) 1994 by Chris Laurel
**  email:  claurel@mr.net
**  snail mail:  Chris Laurel, 5700 W Lake St #208,  St. Louis Park, MN  55416
**
**  This program is free software; you can redistribute it and/or modify
**  it under the terms of the GNU General Public License as published by
**  the Free Software Foundation; either version 2 of the License, or
**  (at your option) any later version.
**
**  This program is distributed in the hope that it will be useful,
**  but WITHOUT ANY WARRANTY; without even the implied warranty of
**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**  GNU General Public License for more details.
**
**  You should have received a copy of the GNU General Public License
**  along with this program; if not, write to the Free Software
**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "wt.h"
#include "error.h"
#include "fixed.h"
#include "view.h"
#include "framebuf.h"
#include "texture.h"
#include "table.h"
#include "world.h"
#include "worldfile.h"
#include "render.h"
#include "graphics.h"
#include "input.h"
#include "object.h"

#define PROFILE 1
#if PROFILE
#include "timer.h"
#endif

static void usage(char *execname);

View *view;
fixed start_x = 0, start_y = 0;


int main(int argc, char *argv[])
{
     World *w;
     FILE *fp;
     Boolean quit = False;
     Intent *intent;
     Graphics_info *ginfo;
     Object *me;
     Boolean blocky = False;
#if PROFILE
     int fps_count = 0;
     double total_time = 0.0;
     double start_time;
#endif

     
     if (argc < 2 || argc > 3)
	  usage(argv[0]);

     if (argc == 3)
	  if (strcmp(argv[1], "-b") == 0)
	       blocky = True;
	  else
	       usage(argv[0]);

     ginfo = init_graphics(320, 200, blocky);

#ifdef TRUECOLOR
     set_texture_trans(32, ginfo->palette.color_lookup);
#else
     set_texture_trans(ginfo->palette.rgb_cube_size,
		       ginfo->palette.color_lookup);
#endif
     init_renderer(ginfo->width, ginfo->height);
     init_input_devices();

     if ((fp = fopen(argv[argc - 1], "r")) == NULL) {
	  perror(argv[1]);
	  exit(EXIT_FAILURE);
     }
     
     w = read_world_file(fp);
     fclose(fp);

     me = new_object(70.0, 1.0, 1.0, 1.0, 0.6);
     /* setup view */
     view = new_view(FLOAT_TO_FIXED(3.14159265 / 2.0));
     
     me->x = FIXED_TO_FLOAT(start_x);
     me->y = FIXED_TO_FLOAT(start_y);
     me->z = 0.0;
     me->angle = 0.0;
     me->dx = me->dy = me->dz = 0.0;
     me->angular_v = 0.0;

     while (!quit) {
	  double sin_facing, cos_facing;
	  double fx, fy, fz, torque;
	  Framebuffer *fb;

#if PROFILE
	  start_time = current_time();
#endif
	  intent = read_input_devices();

	  while (intent->n_special--) {
	       if (intent->special[intent->n_special] == INTENT_END_GAME)
		    quit = True;
	       else
		    object_apply_force(me, 0.0, 0.0, 50.0);
	  }

	  /* Determine forces on viewer. */
	  sin_facing = sin(me->angle);
	  cos_facing = cos(me->angle);
	  fx = cos_facing * intent->force_x - sin_facing * intent->force_y;
	  fy = sin_facing * intent->force_x + cos_facing * intent->force_y;
 	  fz = -0.05 * me->mass;  /* gravity */
	  torque = intent->force_rotate;

	  /* Apply the forces. */
	  object_apply_force(me, fx, fy, fz);
	  object_apply_torque(me, torque);
	  object_update(me);
	  if (me->z <= 0.0 && me->dz <= 0.0) {
	       me->z = 0.0;
	       me->dz = 0.0;
	  }

	  /* Determine the view. */
	  object_view(me, view);

	  /* Display the world. */
	  fb = render(w, view);
	  update_screen(fb);
#if PROFILE
	  fps_count++;
	  total_time += current_time() - start_time;
	  if (fps_count == 100) {
	       printf("fps = %3.2f\n", (double) fps_count / total_time);
	       fps_count = 0;
	       total_time = 0.0;
	  }
#endif
     }

     end_input_devices();
     end_graphics();

     return EXIT_SUCCESS;
}


static void usage(char *execname)
{
     fprintf(stderr, "Usage: %s [-b] <world file>\n", execname);
     exit(EXIT_FAILURE);
}
