nuclear@12: #include nuclear@9: #include nuclear@9: #include nuclear@9: #include "modeller.h" nuclear@9: #include "min3d.h" nuclear@9: #include "rayzor.h" nuclear@9: #include "scene.h" nuclear@12: #include "keyb.h" nuclear@14: #include "scrman.h" nuclear@14: #include "logger.h" nuclear@9: nuclear@9: struct ModellerImpl { nuclear@9: int mx, my; nuclear@9: float cam_theta, cam_phi, cam_dist; nuclear@9: nuclear@9: struct m3d_image rbuf; nuclear@9: nuclear@9: bool bnstate[8]; nuclear@9: int prev_x, prev_y; nuclear@9: }; nuclear@9: nuclear@9: static void draw_grid(float size, float spacing); nuclear@9: nuclear@9: Modeller::Modeller() nuclear@9: { nuclear@9: set_name("modeller"); nuclear@9: } nuclear@9: nuclear@9: Modeller::~Modeller() nuclear@9: { nuclear@9: shutdown(); nuclear@9: } nuclear@9: nuclear@9: bool Modeller::init() nuclear@9: { nuclear@9: mod = new ModellerImpl; nuclear@9: memset(mod, 0, sizeof *mod); nuclear@9: nuclear@9: mod->cam_phi = 25; nuclear@9: mod->cam_dist = 5; nuclear@9: nuclear@9: m3d_init(); nuclear@9: mod->rbuf.pixels = fb_pixels; nuclear@9: mod->rbuf.xsz = fb_width; nuclear@9: mod->rbuf.ysz = fb_height; nuclear@9: m3d_set_buffers(&mod->rbuf, 0); nuclear@9: nuclear@9: m3d_matrix_mode(M3D_PROJECTION); nuclear@9: m3d_load_identity(); nuclear@9: m3d_perspective(50.0, (float)fb_width / (float)fb_height, 0.5, 500.0); nuclear@9: nuclear@9: m3d_enable(M3D_CULL_FACE); nuclear@9: return true; nuclear@9: } nuclear@9: nuclear@9: void Modeller::shutdown() nuclear@9: { nuclear@9: if(mod) { nuclear@9: m3d_shutdown(); nuclear@9: nuclear@9: delete mod; nuclear@9: mod = 0; nuclear@9: } nuclear@9: } nuclear@9: nuclear@9: void Modeller::draw() const nuclear@9: { nuclear@9: m3d_clear(M3D_COLOR_BUFFER_BIT); nuclear@9: nuclear@9: m3d_matrix_mode(M3D_MODELVIEW); nuclear@9: m3d_load_identity(); nuclear@9: m3d_translate(0, 0, -mod->cam_dist); nuclear@9: m3d_rotate(mod->cam_phi, 1, 0, 0); nuclear@9: m3d_rotate(mod->cam_theta, 0, 1, 0); nuclear@9: nuclear@9: draw_grid(10.0, 1.0); nuclear@9: nuclear@9: scene->draw(); nuclear@9: } nuclear@9: nuclear@9: nuclear@9: static void draw_grid(float size, float spacing) nuclear@9: { nuclear@9: int num_lines = size / spacing; nuclear@9: float dist = size / 2.0; nuclear@9: nuclear@9: m3d_disable(M3D_LIGHTING); nuclear@9: nuclear@9: m3d_begin(M3D_LINES); nuclear@9: m3d_color(0.4, 0.4, 0.4); nuclear@9: nuclear@9: float x = -dist; nuclear@9: for(int i=0; i<=num_lines; i++) { nuclear@9: if(i != num_lines / 2) { nuclear@9: m3d_vertex(-dist, 0, x); nuclear@9: m3d_vertex(dist, 0, x); nuclear@9: m3d_vertex(x, 0, -dist); nuclear@9: m3d_vertex(x, 0, dist); nuclear@9: } nuclear@9: x += spacing; nuclear@9: } nuclear@9: m3d_end(); nuclear@9: nuclear@9: m3d_begin(M3D_LINES); nuclear@14: m3d_color(0.8, 0, 0); nuclear@9: m3d_vertex(-dist, 0, 0); nuclear@9: m3d_vertex(dist, 0, 0); nuclear@14: m3d_color(0.1, 0.3, 0.8); nuclear@9: m3d_vertex(0, 0, -dist); nuclear@9: m3d_vertex(0, 0, dist); nuclear@9: m3d_end(); nuclear@9: } nuclear@9: nuclear@9: nuclear@9: void Modeller::handle_keyboard(int key, bool press) nuclear@9: { nuclear@9: if(press) { nuclear@9: switch(key) { nuclear@12: case 'q': nuclear@12: quit_app(); nuclear@12: break; nuclear@12: nuclear@9: case 27: nuclear@12: scene->clear_selection(); nuclear@12: break; nuclear@12: nuclear@12: case '\t': nuclear@12: { nuclear@12: int s = scene->get_selection(); nuclear@12: if(s >= 0) { nuclear@12: s = (s + 1) % scene->get_node_count(); nuclear@12: scene->clear_selection(); nuclear@12: } else { nuclear@12: s = 0; nuclear@12: } nuclear@12: scene->select(s); nuclear@12: } nuclear@9: break; nuclear@9: nuclear@14: case 'r': nuclear@14: case 'R': nuclear@14: if(kb_isdown(KB_ALT) || kb_isdown(KB_CTRL)) { nuclear@14: Screen *rs = get_screen("renderer"); nuclear@14: if(rs) { nuclear@14: activate_screen(rs); nuclear@14: } else { nuclear@14: printlog("failed to find renderer screen!\n"); nuclear@14: } nuclear@14: } nuclear@14: break; nuclear@14: nuclear@9: default: nuclear@9: break; nuclear@9: } nuclear@9: } nuclear@9: } nuclear@9: nuclear@9: void Modeller::handle_mbutton(int bn, bool press, int x, int y) nuclear@9: { nuclear@9: mod->bnstate[bn] = press; nuclear@9: mod->prev_x = x; nuclear@9: mod->prev_y = y; nuclear@9: } nuclear@9: nuclear@9: void Modeller::handle_mmotion(int x, int y) nuclear@9: { nuclear@9: int dx = x - mod->prev_x; nuclear@9: int dy = y - mod->prev_y; nuclear@9: mod->prev_x = x; nuclear@9: mod->prev_y = y; nuclear@9: nuclear@12: if(kb_isdown(KB_ALT) || kb_isdown(KB_CTRL)) { nuclear@12: if(mod->bnstate[0]) { nuclear@12: mod->cam_theta += dx * 0.5; nuclear@12: mod->cam_phi += dy * 0.5; nuclear@9: nuclear@12: if(mod->cam_phi < -90) mod->cam_phi = -90; nuclear@12: if(mod->cam_phi > 90) mod->cam_phi = 90; nuclear@12: } nuclear@12: if(mod->bnstate[1]) { nuclear@12: mod->cam_dist += dy * 0.1; nuclear@12: if(mod->cam_dist < 0) mod->cam_dist = 0; nuclear@12: } nuclear@9: } nuclear@9: }