/**************************************************************************** * apps/graphics/traveler/trv_main.c * This file contains the main logic for the NuttX version of Traveler * * Copyright (C) 2014 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name NuttX nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include "trv_types.h" #include "trv_bitmaps.h" #include "trv_world.h" #include "trv_doors.h" #include "trv_pov.h" #include "trv_raycntl.h" #include "trv_rayrend.h" #include "trv_input.h" #include "trv_graphics.h" #include "trv_color.h" #include "trv_debug.h" #include "trv_main.h" #if defined(CONFIG_GRAPHICS_TRAVELER_PERFMON) || \ defined(CONFIG_GRAPHICS_TRAVELER_LIMITFPS) # include # include #endif /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ /* Configuration ************************************************************/ #ifndef CONFIG_GRAPHICS_TRAVELER_DEFPATH # define CONFIG_GRAPHICS_TRAVELER_DEFPATH "/mnt/world" #endif /* Frame rate governer */ #ifdef CONFIG_GRAPHICS_TRAVELER_MAXFPS # define CONFIG_GRAPHICS_TRAVELER_MAXFPS 30 #endif #define MIN_FRAME_TIME (1.0 / (double)CONFIG_GRAPHICS_TRAVELER_MAXFPS) /**************************************************************************** * Public Data *************************************************************************/ bool g_trv_terminate; /**************************************************************************** * Private Data *************************************************************************/ static const char g_default_worldfile[] = "transfrm.wld"; static const char g_default_worldpath[] = CONFIG_GRAPHICS_TRAVELER_DEFPATH; static FAR struct trv_graphics_info_s g_trv_ginfo; /**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** * Name: trv_exit * * Description: ****************************************************************************/ static void trv_exit(int exitcode) noreturn_function; static void trv_exit(int exitcode) { /* Release memory held by the ray casting engine */ trv_world_destroy(); /* Close off input */ trv_input_terminate(); trv_graphics_terminate(&g_trv_ginfo); exit(exitcode); } /**************************************************************************** * Name: trv_usage * * Description: ****************************************************************************/ static void trv_usage(char *execname) { fprintf(stderr, "Usage: %s [-b] [-p] [world]\n", execname); fprintf(stderr, "Where:\n"); fprintf(stderr, " -p Selects the path to the world data file\n"); fprintf(stderr, " world Selects the world file name\n"); exit(EXIT_FAILURE); } /**************************************************************************** * Name: trv_current_time * * Description: ****************************************************************************/ #if defined(CONFIG_GRAPHICS_TRAVELER_PERFMON) || \ defined(CONFIG_GRAPHICS_TRAVELER_LIMITFPS) static double trv_current_time(void) { struct timeval tv; gettimeofday(&tv, NULL); return (double) tv.tv_sec + (double) tv.tv_usec / 1000000.0; } #endif /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: main * * Description: ****************************************************************************/ #ifdef CONFIG_BUILD_KERNEL int main(int argc, FAR char *argv[]) #else int traveler_main(int argc, char *argv[]) #endif { FAR const char *wldpath; FAR const char *wldfile; #if defined(CONFIG_GRAPHICS_TRAVELER_PERFMON) || \ defined(CONFIG_GRAPHICS_TRAVELER_LIMITFPS) #ifdef CONFIG_GRAPHICS_TRAVELER_PERFMON int32_t frame_count = 0; double start_time; double now; #endif #ifdef CONFIG_GRAPHICS_TRAVELER_LIMITFPS double frame_start; #endif double elapsed; #endif int ret; int i; /* Defaults */ wldpath = g_default_worldpath; wldfile = g_default_worldfile; /* Check for command line arguments */ for (i = 1; i < argc; i++) { FAR char *ptr = argv[i]; if (*ptr == '-') { ptr++; switch (*ptr) { case 'p' : wldpath = ptr++; break; default: fprintf(stderr, "Invalid Switch\n"); trv_usage(argv[0]); break; } } else { wldfile = ptr; } } trv_debug("World data file: %s\n", wldfile); trv_debug("World data path: %s\n", wldpath); /* Initialize the graphics interface */ trv_graphics_initialize(&g_trv_ginfo); /* Load the word data structures */ ret = trv_world_create(wldpath, wldfile); if (ret < 0) { trv_abort("ERROR: Failed to load world file %s: %d\n", wldfile, ret); } /* Release color mapping tables */ trv_color_endmapping(); /* Set the player's POV in the new world */ trv_pov_reset(); /* Initialize the world's door */ trv_door_initialize(); /* Set up to receive input */ trv_input_initialize(); #ifdef CONFIG_GRAPHICS_TRAVELER_PERFMON /* Get the start time for performance monitoring */ start_time = trv_current_time(); #endif g_trv_terminate = false; while (!g_trv_terminate) { #ifdef CONFIG_GRAPHICS_TRAVELER_LIMITFPS /* Get the start time from frame rate limiting */ frame_start = trv_current_time(); #endif trv_input_read(); /* Select the POV to use on this viewing cycle */ trv_pov_new(); /* Process door animations */ trv_door_animate(); /* Paint the back drop */ trv_rend_backdrop(&g_player, &g_trv_ginfo); /* Render the 3-D view */ trv_raycaster(&g_player, &g_trv_ginfo); /* Display the world. */ trv_display_update(&g_trv_ginfo); #ifdef CONFIG_GRAPHICS_TRAVELER_LIMITFPS /* In the unlikely event that we are running "too" fast, we can delay * here to enforce a maixmum frame rate. */ elapsed = trv_current_time() - frame_start; if (elapsed < MIN_FRAME_TIME) { usleep(1000000 * (MIN_FRAME_TIME - elapsed)); } #endif #ifdef CONFIG_GRAPHICS_TRAVELER_PERFMON /* Show the realized frame rate */ frame_count++; if (frame_count >= 100) { now = trv_current_time(); elapsed = now - start_time; fprintf(stderr, "fps = %3.2f\n", (double)frame_count / elapsed); frame_count = 0; start_time = now; } #endif } trv_exit(EXIT_SUCCESS); return 0; } /**************************************************************************** * Name: trv_abort * * Description: ****************************************************************************/ void trv_abort(FAR char *message, ...) { va_list args; va_start(args, message); vfprintf(stderr, message, args); putc('\n', stderr); va_end(args); trv_exit(EXIT_FAILURE); }