goat3d
diff goatview/src/goatview.cc @ 82:70b7c41a4f17
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 11 May 2014 22:04:54 +0300 |
parents | c5e997e8fd62 |
children | 57e745dd13c2 |
line diff
1.1 --- a/goatview/src/goatview.cc Thu May 08 23:05:29 2014 +0300 1.2 +++ b/goatview/src/goatview.cc Sun May 11 22:04:54 2014 +0300 1.3 @@ -1,20 +1,47 @@ 1.4 #include <stdio.h> 1.5 +#include "opengl.h" 1.6 #include <QtOpenGL/QtOpenGL> 1.7 -#include "opengl.h" 1.8 #include <vmath/vmath.h> 1.9 #include "goatview.h" 1.10 #include "goat3d.h" 1.11 1.12 +static void update_tree(QTreeWidget *tree); 1.13 +static void add_tree(QTreeWidget *tree, goat3d_node *node, QTreeWidgetItem *parent); 1.14 + 1.15 static void draw_node(goat3d_node *node); 1.16 +static void draw_mesh(goat3d_mesh *mesh); 1.17 1.18 goat3d *scene; 1.19 -QSettings *settings; 1.20 1.21 static long anim_time; 1.22 static float cam_theta, cam_phi, cam_dist = 8; 1.23 static float fov = 60.0; 1.24 +static bool use_nodes = true; 1.25 1.26 -bool load_scene(const char *fname) 1.27 + 1.28 +GoatView::GoatView() 1.29 +{ 1.30 + glview = 0; 1.31 + 1.32 + make_menu(); 1.33 + make_dock(); 1.34 + make_center(); 1.35 + 1.36 + statusBar(); 1.37 + 1.38 + setWindowTitle("GoatView"); 1.39 + 1.40 + QSettings *settings = new QSettings; 1.41 + resize(settings->value("main/size", QSize(1024, 768)).toSize()); 1.42 + move(settings->value("main/pos", QPoint(100, 100)).toPoint()); 1.43 + delete settings; 1.44 +} 1.45 + 1.46 +GoatView::~GoatView() 1.47 +{ 1.48 +} 1.49 + 1.50 +bool GoatView::load_scene(const char *fname) 1.51 { 1.52 if(scene) { 1.53 goat3d_free(scene); 1.54 @@ -24,39 +51,27 @@ 1.55 } 1.56 1.57 float bmin[3], bmax[3]; 1.58 - goat3d_get_bounds(scene, bmin, bmax); 1.59 - float bsize = (Vector3(bmax[0], bmax[1], bmax[2]) - Vector3(bmin[0], bmin[1], bmin[2])).length(); 1.60 - cam_dist = bsize / tan(DEG_TO_RAD(fov) / 2.0) + bsize; 1.61 + if(goat3d_get_bounds(scene, bmin, bmax) != -1) { 1.62 + float bsize = (Vector3(bmax[0], bmax[1], bmax[2]) - Vector3(bmin[0], bmin[1], bmin[2])).length(); 1.63 + cam_dist = bsize / tan(DEG_TO_RAD(fov) / 2.0) + bsize; 1.64 + printf("bounds size: %f, cam_dist: %f\n", bsize, cam_dist); 1.65 + } 1.66 1.67 - printf("bounds size: %f, cam_dist: %f\n", bsize, cam_dist); 1.68 + update_tree(scntree); 1.69 return true; 1.70 } 1.71 1.72 -GoatView::GoatView() 1.73 -{ 1.74 - make_menu(); 1.75 - make_dock(); 1.76 - make_center(); 1.77 - 1.78 - statusBar(); 1.79 - 1.80 - setWindowTitle("GoatView"); 1.81 - resize(settings->value("main/size", QSize(1024, 768)).toSize()); 1.82 - move(settings->value("main/pos", QPoint(100, 100)).toPoint()); 1.83 -} 1.84 - 1.85 -GoatView::~GoatView() 1.86 -{ 1.87 -} 1.88 - 1.89 void GoatView::closeEvent(QCloseEvent *ev) 1.90 { 1.91 + QSettings *settings = new QSettings; 1.92 settings->setValue("main/size", size()); 1.93 settings->setValue("main/pos", pos()); 1.94 + delete settings; 1.95 } 1.96 1.97 bool GoatView::make_menu() 1.98 { 1.99 + // file menu 1.100 QMenu *menu_file = menuBar()->addMenu("&File"); 1.101 1.102 QAction *act_open_sce = new QAction("&Open Scene", this); 1.103 @@ -72,6 +87,15 @@ 1.104 act_quit->setShortcuts(QKeySequence::Quit); 1.105 connect(act_quit, &QAction::triggered, [&](){qApp->quit();}); 1.106 menu_file->addAction(act_quit); 1.107 + 1.108 + // view menu 1.109 + QMenu *menu_view = menuBar()->addMenu("&View"); 1.110 + 1.111 + QAction *act_use_nodes = new QAction("use nodes", this); 1.112 + act_use_nodes->setCheckable(true); 1.113 + act_use_nodes->setChecked(use_nodes); 1.114 + connect(act_use_nodes, &QAction::triggered, this, [&](){use_nodes = !use_nodes; glview->updateGL();}); 1.115 + menu_view->addAction(act_use_nodes); 1.116 return true; 1.117 } 1.118 1.119 @@ -82,15 +106,27 @@ 1.120 QVBoxLayout *dock_vbox = new QVBoxLayout; 1.121 dock_cont->setLayout(dock_vbox); 1.122 1.123 - QPushButton *bn_quit = new QPushButton("quit"); 1.124 - dock_vbox->addWidget(bn_quit); 1.125 - connect(bn_quit, &QPushButton::clicked, [&](){qApp->quit();}); 1.126 - 1.127 QDockWidget *dock = new QDockWidget("Scene graph", this); 1.128 dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); 1.129 dock->setWidget(dock_cont); 1.130 addDockWidget(Qt::LeftDockWidgetArea, dock); 1.131 1.132 + // make the tree view widget 1.133 + scntree = new QTreeWidget; 1.134 + scntree->setColumnCount(1); 1.135 + QStringList hdrstr; 1.136 + hdrstr << "Node";// << "Type"; 1.137 + scntree->setHeaderItem(new QTreeWidgetItem((QTreeWidget*)0, hdrstr)); 1.138 + scntree->setAlternatingRowColors(true); 1.139 + dock_vbox->addWidget(scntree); 1.140 + 1.141 + update_tree(scntree); 1.142 + 1.143 + // misc 1.144 + QPushButton *bn_quit = new QPushButton("quit"); 1.145 + dock_vbox->addWidget(bn_quit); 1.146 + connect(bn_quit, &QPushButton::clicked, [&](){qApp->quit();}); 1.147 + 1.148 // ---- bottom dock ---- 1.149 dock_cont = new QWidget; 1.150 QHBoxLayout *dock_hbox = new QHBoxLayout; 1.151 @@ -110,8 +146,8 @@ 1.152 1.153 bool GoatView::make_center() 1.154 { 1.155 - GoatViewport *vport = new GoatViewport; 1.156 - setCentralWidget(vport); 1.157 + glview = new GoatViewport(this); 1.158 + setCentralWidget(glview); 1.159 return true; 1.160 } 1.161 1.162 @@ -135,11 +171,48 @@ 1.163 statusBar()->showMessage("opening animation..."); 1.164 } 1.165 1.166 +static void update_tree(QTreeWidget *tree) 1.167 +{ 1.168 + if(!scene) return; 1.169 + 1.170 + int num_nodes = goat3d_get_node_count(scene); 1.171 + for(int i=0; i<num_nodes; i++) { 1.172 + goat3d_node *node = goat3d_get_node(scene, i); 1.173 + if(goat3d_get_node_parent(node)) { 1.174 + continue; 1.175 + } 1.176 + 1.177 + // only add the root nodes, the rest will be added recursively by them 1.178 + add_tree(tree, node, 0); 1.179 + } 1.180 + tree->expandAll(); 1.181 +} 1.182 + 1.183 +static void add_tree(QTreeWidget *tree, goat3d_node *node, QTreeWidgetItem *parent) 1.184 +{ 1.185 + //char icon_name[64]; 1.186 + //sprintf(icon_name, ":/icons/icons/icon_%s.png", node->get_type()); 1.187 + 1.188 + QStringList row; 1.189 + row << goat3d_get_node_name(node) << "M"; 1.190 + QTreeWidgetItem *item = new QTreeWidgetItem(parent, row); 1.191 + //item->setIcon(0, QIcon(icon_name)); 1.192 + tree->addTopLevelItem(item); 1.193 + 1.194 + int num_children = goat3d_get_node_child_count(node); 1.195 + for(int i=0; i<num_children; i++) { 1.196 + add_tree(tree, goat3d_get_node_child(node, i), item); 1.197 + } 1.198 +} 1.199 + 1.200 + 1.201 1.202 // ---- OpenGL viewport ---- 1.203 -GoatViewport::GoatViewport() 1.204 +GoatViewport::GoatViewport(QWidget *main_win) 1.205 : QGLWidget(QGLFormat(QGL::DepthBuffer)) 1.206 { 1.207 + this->main_win = main_win; 1.208 + initialized = false; 1.209 } 1.210 1.211 GoatViewport::~GoatViewport() 1.212 @@ -151,10 +224,24 @@ 1.213 return QSize(800, 600); 1.214 } 1.215 1.216 +#define CRITICAL(error, detail) \ 1.217 + do { \ 1.218 + fprintf(stderr, "%s: %s\n", error, detail); \ 1.219 + QMessageBox::critical(main_win, error, detail); \ 1.220 + abort(); \ 1.221 + } while(0) 1.222 + 1.223 void GoatViewport::initializeGL() 1.224 { 1.225 + if(initialized) return; 1.226 + initialized = true; 1.227 + 1.228 init_opengl(); 1.229 1.230 + if(!GLEW_ARB_transpose_matrix) { 1.231 + CRITICAL("OpenGL initialization failed", "ARB_transpose_matrix extension not found!"); 1.232 + } 1.233 + 1.234 glClearColor(0.1f, 0.1f, 0.1f, 1.0f); 1.235 1.236 glEnable(GL_DEPTH_TEST); 1.237 @@ -179,61 +266,39 @@ 1.238 glRotatef(cam_phi, 1, 0, 0); 1.239 glRotatef(cam_theta, 0, 1, 0); 1.240 1.241 - if(scene) { 1.242 + if(!scene) return; 1.243 + 1.244 + if(use_nodes) { 1.245 int node_count = goat3d_get_node_count(scene); 1.246 for(int i=0; i<node_count; i++) { 1.247 goat3d_node *node = goat3d_get_node(scene, i); 1.248 - //if(!goat3d_get_node_parent(node)) { 1.249 - draw_node(node); // only draw root nodes, the rest will be drawn recursively 1.250 - //} 1.251 + draw_node(node); // only draw root nodes, the rest will be drawn recursively 1.252 + } 1.253 + } else { 1.254 + int mesh_count = goat3d_get_mesh_count(scene); 1.255 + for(int i=0; i<mesh_count; i++) { 1.256 + goat3d_mesh *mesh = goat3d_get_mesh(scene, i); 1.257 + draw_mesh(mesh); 1.258 } 1.259 } 1.260 } 1.261 1.262 +#ifndef GLEW_ARB_transpose_matrix 1.263 +#error "GLEW_ARB_transpose_matrix undefined?" 1.264 +#endif 1.265 + 1.266 static void draw_node(goat3d_node *node) 1.267 { 1.268 float xform[16]; 1.269 goat3d_get_node_matrix(node, xform, anim_time); 1.270 - for(int i=0; i<4; i++) { 1.271 - for(int j=0; j<i; j++) { 1.272 - float tmp = xform[i * 4 + j]; 1.273 - xform[i * 4 + j] = xform[j * 4 + i]; 1.274 - xform[j * 4 + i] = tmp; 1.275 - } 1.276 - } 1.277 1.278 glPushMatrix(); 1.279 - glMultMatrixf(xform); 1.280 + glMultTransposeMatrixf(xform); 1.281 1.282 if(goat3d_get_node_type(node) == GOAT3D_NODE_MESH) { 1.283 goat3d_mesh *mesh = (goat3d_mesh*)goat3d_get_node_object(node); 1.284 1.285 - int num_faces = goat3d_get_mesh_face_count(mesh); 1.286 - int num_verts = goat3d_get_mesh_attrib_count(mesh, GOAT3D_MESH_ATTR_VERTEX); 1.287 - 1.288 - glEnableClientState(GL_VERTEX_ARRAY); 1.289 - glVertexPointer(3, GL_FLOAT, 0, goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX)); 1.290 - 1.291 - float *data; 1.292 - if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL))) { 1.293 - glEnableClientState(GL_NORMAL_ARRAY); 1.294 - glNormalPointer(GL_FLOAT, 0, data); 1.295 - } 1.296 - if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD))) { 1.297 - glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.298 - glTexCoordPointer(2, GL_FLOAT, 0, data); 1.299 - } 1.300 - 1.301 - int *indices; 1.302 - if((indices = goat3d_get_mesh_faces(mesh))) { 1.303 - glDrawElements(GL_TRIANGLES, num_faces * 3, GL_UNSIGNED_INT, indices); 1.304 - } else { 1.305 - glDrawArrays(GL_TRIANGLES, 0, num_verts * 3); 1.306 - } 1.307 - 1.308 - glDisableClientState(GL_VERTEX_ARRAY); 1.309 - glDisableClientState(GL_NORMAL_ARRAY); 1.310 - glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.311 + draw_mesh(mesh); 1.312 } 1.313 1.314 /*int num_child = goat3d_get_node_child_count(node); 1.315 @@ -244,6 +309,36 @@ 1.316 glPopMatrix(); 1.317 } 1.318 1.319 +static void draw_mesh(goat3d_mesh *mesh) 1.320 +{ 1.321 + int num_faces = goat3d_get_mesh_face_count(mesh); 1.322 + int num_verts = goat3d_get_mesh_attrib_count(mesh, GOAT3D_MESH_ATTR_VERTEX); 1.323 + 1.324 + glEnableClientState(GL_VERTEX_ARRAY); 1.325 + glVertexPointer(3, GL_FLOAT, 0, goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX)); 1.326 + 1.327 + float *data; 1.328 + if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL))) { 1.329 + glEnableClientState(GL_NORMAL_ARRAY); 1.330 + glNormalPointer(GL_FLOAT, 0, data); 1.331 + } 1.332 + if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD))) { 1.333 + glEnableClientState(GL_TEXTURE_COORD_ARRAY); 1.334 + glTexCoordPointer(2, GL_FLOAT, 0, data); 1.335 + } 1.336 + 1.337 + int *indices; 1.338 + if((indices = goat3d_get_mesh_faces(mesh))) { 1.339 + glDrawElements(GL_TRIANGLES, num_faces * 3, GL_UNSIGNED_INT, indices); 1.340 + } else { 1.341 + glDrawArrays(GL_TRIANGLES, 0, num_verts * 3); 1.342 + } 1.343 + 1.344 + glDisableClientState(GL_VERTEX_ARRAY); 1.345 + glDisableClientState(GL_NORMAL_ARRAY); 1.346 + glDisableClientState(GL_TEXTURE_COORD_ARRAY); 1.347 +} 1.348 + 1.349 1.350 static float prev_x, prev_y; 1.351 void GoatViewport::mousePressEvent(QMouseEvent *ev)