added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / dsys / dsys.cpp
diff --git a/src/3dengfx/src/dsys/dsys.cpp b/src/3dengfx/src/dsys/dsys.cpp
new file mode 100644 (file)
index 0000000..0490bb6
--- /dev/null
@@ -0,0 +1,285 @@
+/*
+This file is part of 3dengfx demosystem.
+
+Copyright (c) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "3dengfx_config.h"
+
+#include <iostream>
+#include <algorithm>
+#include <string>
+#include <map>
+#include "dsys.hpp"
+#include "part.hpp"
+#include "fx.hpp"
+#include "cmd.hpp"
+#include "script.h"
+#include "3dengfx/3dengfx.hpp"
+#include "n3dmath2/n3dmath2.hpp"
+#include "common/timer.h"
+#include "common/err_msg.h"
+
+#if defined(__unix__) || defined(unix)
+#include <unistd.h>
+#include <sys/stat.h>
+#endif // unix
+
+using namespace dsys;
+using namespace std;
+
+static int execute_script(DemoScript *ds, unsigned long time);
+
+Texture *dsys::tex[4];
+unsigned int dsys::rtex_size_x, dsys::rtex_size_y;
+Matrix4x4 dsys::tex_mat[4];
+
+typedef map<string, Part*> PartTree;
+static PartTree parts;
+static PartTree running;
+
+static ntimer timer;
+
+static char script_fname[256];
+static DemoScript *ds;
+
+static bool demo_running = false;
+static bool seq_render = false;
+static unsigned long seq_time, seq_dt;
+
+static int best_tex_size(int n) {
+       int i;
+       for(i=64; i<2048; i*=2) {
+               if(i*2 > n) return i;
+       }
+
+       return 2048;
+}
+
+bool dsys::init() {
+       int scrx = get_graphics_init_parameters()->x;
+       int scry = get_graphics_init_parameters()->y;
+
+       int next_size_x, next_size_y;
+       
+       rtex_size_x = best_tex_size(scrx - 1);
+       rtex_size_y = best_tex_size(scry - 1);
+       
+       next_size_x = rtex_size_x * 2;
+       next_size_y = rtex_size_y * 2;
+               
+       info("allocating dsys render targets:");
+
+       //if (!engfx_state::sys_caps.non_power_of_two_textures)
+       //{
+               // make a high-res texture and 3 low-res
+               for(int i=0; i<4; i++) {
+                       int x = (i > 1) ? rtex_size_x : next_size_x;
+                       int y = (i > 1) ? rtex_size_y : next_size_y;
+                       tex[i] = new Texture(x, y);
+                       info("  %d - %dx%d", i, x, y);
+               }
+
+               tex_mat[0].set_scaling(Vector3((float)scrx / (float)next_size_x, (float)scry / (float)next_size_y, 1));
+               tex_mat[1].set_scaling(Vector3((float)scrx / (float)next_size_x, (float)scry / (float)next_size_y, 1));
+
+               tex_mat[2] = Matrix4x4::identity_matrix;
+               tex_mat[3] = Matrix4x4::identity_matrix;
+       /*}
+       else
+       {
+               for (int i=0; i<4; i++)
+               {
+                       tex[i] = new Texture(scrx, scry);
+                       info("  %d - %dx%d", i, scrx, scry);
+                       tex_mat[i] = Matrix4x4::identity_matrix;
+               }
+       }*/
+
+       strcpy(script_fname, "demoscript");
+
+       cmd::register_commands();
+       
+       return true;
+}
+
+void dsys::clean_up() {
+       for(int i=0; i<4; i++) {
+               if(tex[i]) delete tex[i];
+               tex[i] = 0;
+       }
+}
+
+void dsys::use_rt_tex(RenderTarget rt) {
+       set_texture(0, tex[rt]);
+       set_matrix(XFORM_TEXTURE, tex_mat[rt]);
+}
+
+void dsys::set_demo_script(const char *fname) {
+       strcpy(script_fname, fname);
+}
+
+
+unsigned long dsys::get_demo_time() {
+       return seq_render ? seq_time : timer_getmsec(&timer);
+}
+
+
+void dsys::add_part(Part *part) {
+       if(!part->get_name()) {
+               error("dsys::add_part - trying to add a nameless part...");
+               return;
+       }
+       parts[string(part->get_name())] = part;
+}
+
+void dsys::remove_part(Part *part) {
+       PartTree::iterator iter = parts.find(part->get_name());
+       parts.erase(iter);
+}
+
+void dsys::start_part(Part *part) {
+       running[part->get_name()] = part;
+       part->start();
+}
+
+void dsys::stop_part(Part *part) {
+       part->stop();
+       PartTree::iterator iter = running.find(part->get_name());
+       if(iter != running.end()) {
+               running.erase(iter);
+       } else {
+               error("stop_part() called for unknown part: %s\n", part->get_name());
+       }
+}
+
+Part *dsys::get_part(const char *pname) {
+       PartTree::iterator iter = parts.find(pname);
+       return iter != parts.end() ? iter->second : 0;
+}
+
+Part *dsys::get_running(const char *pname) {
+       PartTree::iterator iter = running.find(pname);
+       return iter != running.end() ? iter->second : 0;
+}
+
+
+bool dsys::start_demo() {
+       if(!(ds = open_script(script_fname))) {
+               return false;
+       }
+       demo_running = true;
+       timer_reset(&timer);
+       timer_start(&timer);
+       return true;
+}
+
+#define PATH_MAX 2048
+static char curr_dir[PATH_MAX];
+
+bool dsys::render_demo(int fps, const char *out_dir) {
+       if(!(ds = open_script(script_fname))) {
+               return false;
+       }
+       
+#if defined(__unix__) || defined(unix)
+       // change to the specified directory
+       getcwd(curr_dir, PATH_MAX);
+
+       struct stat sbuf;
+       if(stat(out_dir, &sbuf) == -1) {
+               mkdir(out_dir, 0770);
+       }       
+       
+       chdir(out_dir);
+#endif // __unix__
+
+       demo_running = true;
+       seq_render = true;
+       seq_time = 0;
+       seq_dt = 1000 / fps;
+
+       return true;
+}
+
+void dsys::end_demo() {
+#if defined(__unix__) || defined(unix)
+       if(seq_render) {
+               chdir(curr_dir);
+       }
+#endif // unix
+       
+       if(demo_running) {
+               close_script(ds);
+               demo_running = false;
+       }
+}
+
+
+static void update_node(const pair<string, Part*> &p) {
+       p.second->update_graphics();
+}
+
+int dsys::update_graphics() {
+       if(!demo_running) {
+               return 1;
+       }
+
+       unsigned long time = get_demo_time();
+
+       int res;
+       while((res = execute_script(ds, time)) != 1) {
+               if(res == EOF) {
+                       end_demo();
+                       return -1;
+               }
+       }
+
+       // update graphics
+       clear(Color(0.0f, 0.0f, 0.0f));
+       clear_zbuffer_stencil(1.0f, 0);
+       
+       for_each(running.begin(), running.end(), update_node);
+
+       // apply any post effects
+       apply_image_fx(time);
+
+       if(seq_render) {
+               screen_capture();
+               seq_time += seq_dt;
+       }
+               
+       flip();
+       return 0;
+}
+
+static int execute_script(DemoScript *ds, unsigned long time) {
+       DemoCommand command;
+       
+       int res = get_next_command(ds, &command, time);
+       if(res == EOF || res == 1) {
+               return res;
+       }
+
+       if(!cmd::command(command.type, command.argv[0], command.argv + 1)) {
+               error("error in demoscript command execution!");
+       }
+       free_command(&command);
+
+       return demo_running ? 0 : -1;
+}
+