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)