goat3d

annotate goatview/src/goatview.cc @ 80:c5e997e8fd62

lalala
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 08 May 2014 23:00:30 +0300
parents a42f6cd4e2fa
children 70b7c41a4f17
rev   line source
nuclear@78 1 #include <stdio.h>
nuclear@76 2 #include <QtOpenGL/QtOpenGL>
nuclear@79 3 #include "opengl.h"
nuclear@76 4 #include <vmath/vmath.h>
nuclear@73 5 #include "goatview.h"
nuclear@74 6 #include "goat3d.h"
nuclear@74 7
nuclear@78 8 static void draw_node(goat3d_node *node);
nuclear@78 9
nuclear@74 10 goat3d *scene;
nuclear@75 11 QSettings *settings;
nuclear@75 12
nuclear@75 13 static long anim_time;
nuclear@75 14 static float cam_theta, cam_phi, cam_dist = 8;
nuclear@76 15 static float fov = 60.0;
nuclear@75 16
nuclear@76 17 bool load_scene(const char *fname)
nuclear@76 18 {
nuclear@76 19 if(scene) {
nuclear@76 20 goat3d_free(scene);
nuclear@76 21 }
nuclear@76 22 if(!(scene = goat3d_create()) || goat3d_load(scene, fname) == -1) {
nuclear@76 23 return false;
nuclear@76 24 }
nuclear@76 25
nuclear@76 26 float bmin[3], bmax[3];
nuclear@76 27 goat3d_get_bounds(scene, bmin, bmax);
nuclear@76 28 float bsize = (Vector3(bmax[0], bmax[1], bmax[2]) - Vector3(bmin[0], bmin[1], bmin[2])).length();
nuclear@76 29 cam_dist = bsize / tan(DEG_TO_RAD(fov) / 2.0) + bsize;
nuclear@76 30
nuclear@76 31 printf("bounds size: %f, cam_dist: %f\n", bsize, cam_dist);
nuclear@76 32 return true;
nuclear@76 33 }
nuclear@73 34
nuclear@73 35 GoatView::GoatView()
nuclear@73 36 {
nuclear@73 37 make_menu();
nuclear@73 38 make_dock();
nuclear@73 39 make_center();
nuclear@73 40
nuclear@73 41 statusBar();
nuclear@73 42
nuclear@73 43 setWindowTitle("GoatView");
nuclear@75 44 resize(settings->value("main/size", QSize(1024, 768)).toSize());
nuclear@75 45 move(settings->value("main/pos", QPoint(100, 100)).toPoint());
nuclear@73 46 }
nuclear@73 47
nuclear@73 48 GoatView::~GoatView()
nuclear@73 49 {
nuclear@73 50 }
nuclear@73 51
nuclear@75 52 void GoatView::closeEvent(QCloseEvent *ev)
nuclear@75 53 {
nuclear@75 54 settings->setValue("main/size", size());
nuclear@75 55 settings->setValue("main/pos", pos());
nuclear@75 56 }
nuclear@75 57
nuclear@73 58 bool GoatView::make_menu()
nuclear@73 59 {
nuclear@73 60 QMenu *menu_file = menuBar()->addMenu("&File");
nuclear@73 61
nuclear@73 62 QAction *act_open_sce = new QAction("&Open Scene", this);
nuclear@73 63 act_open_sce->setShortcuts(QKeySequence::Open);
nuclear@73 64 connect(act_open_sce, &QAction::triggered, this, &GoatView::open_scene);
nuclear@73 65 menu_file->addAction(act_open_sce);
nuclear@73 66
nuclear@73 67 QAction *act_open_anm = new QAction("Open &Animation", this);
nuclear@73 68 connect(act_open_anm, &QAction::triggered, this, &GoatView::open_anim);
nuclear@73 69 menu_file->addAction(act_open_anm);
nuclear@73 70
nuclear@73 71 QAction *act_quit = new QAction("&Quit", this);
nuclear@73 72 act_quit->setShortcuts(QKeySequence::Quit);
nuclear@73 73 connect(act_quit, &QAction::triggered, [&](){qApp->quit();});
nuclear@73 74 menu_file->addAction(act_quit);
nuclear@73 75 return true;
nuclear@73 76 }
nuclear@73 77
nuclear@73 78 bool GoatView::make_dock()
nuclear@73 79 {
nuclear@73 80 // ---- side-dock ----
nuclear@73 81 QWidget *dock_cont = new QWidget;
nuclear@73 82 QVBoxLayout *dock_vbox = new QVBoxLayout;
nuclear@73 83 dock_cont->setLayout(dock_vbox);
nuclear@73 84
nuclear@73 85 QPushButton *bn_quit = new QPushButton("quit");
nuclear@73 86 dock_vbox->addWidget(bn_quit);
nuclear@73 87 connect(bn_quit, &QPushButton::clicked, [&](){qApp->quit();});
nuclear@73 88
nuclear@73 89 QDockWidget *dock = new QDockWidget("Scene graph", this);
nuclear@73 90 dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
nuclear@73 91 dock->setWidget(dock_cont);
nuclear@73 92 addDockWidget(Qt::LeftDockWidgetArea, dock);
nuclear@73 93
nuclear@73 94 // ---- bottom dock ----
nuclear@73 95 dock_cont = new QWidget;
nuclear@73 96 QHBoxLayout *dock_hbox = new QHBoxLayout;
nuclear@73 97 dock_cont->setLayout(dock_hbox);
nuclear@73 98
nuclear@73 99 QSlider *slider_time = new QSlider(Qt::Orientation::Horizontal);
nuclear@73 100 slider_time->setDisabled(true);
nuclear@73 101 dock_hbox->addWidget(slider_time);
nuclear@73 102
nuclear@73 103 dock = new QDockWidget("Animation", this);
nuclear@73 104 dock->setAllowedAreas(Qt::BottomDockWidgetArea);
nuclear@73 105 dock->setWidget(dock_cont);
nuclear@73 106 addDockWidget(Qt::BottomDockWidgetArea, dock);
nuclear@73 107
nuclear@73 108 return true;
nuclear@73 109 }
nuclear@73 110
nuclear@73 111 bool GoatView::make_center()
nuclear@73 112 {
nuclear@73 113 GoatViewport *vport = new GoatViewport;
nuclear@73 114 setCentralWidget(vport);
nuclear@73 115 return true;
nuclear@73 116 }
nuclear@73 117
nuclear@73 118 void GoatView::open_scene()
nuclear@73 119 {
nuclear@74 120 std::string fname = QFileDialog::getOpenFileName(this, "Open scene file", "",
nuclear@74 121 "Goat3D Scene (*.goatsce);;All Files (*)").toStdString();
nuclear@74 122 if(fname.empty()) {
nuclear@74 123 statusBar()->showMessage("Abort: No file selected!");
nuclear@74 124 return;
nuclear@74 125 }
nuclear@74 126
nuclear@74 127 statusBar()->showMessage("opening scene file");
nuclear@76 128 if(!load_scene(fname.c_str())) {
nuclear@74 129 statusBar()->showMessage("failed to load scene file");
nuclear@74 130 }
nuclear@73 131 }
nuclear@73 132
nuclear@73 133 void GoatView::open_anim()
nuclear@73 134 {
nuclear@73 135 statusBar()->showMessage("opening animation...");
nuclear@73 136 }
nuclear@73 137
nuclear@73 138
nuclear@73 139 // ---- OpenGL viewport ----
nuclear@73 140 GoatViewport::GoatViewport()
nuclear@73 141 : QGLWidget(QGLFormat(QGL::DepthBuffer))
nuclear@73 142 {
nuclear@73 143 }
nuclear@73 144
nuclear@73 145 GoatViewport::~GoatViewport()
nuclear@73 146 {
nuclear@73 147 }
nuclear@73 148
nuclear@73 149 QSize GoatViewport::sizeHint() const
nuclear@73 150 {
nuclear@73 151 return QSize(800, 600);
nuclear@73 152 }
nuclear@73 153
nuclear@73 154 void GoatViewport::initializeGL()
nuclear@73 155 {
nuclear@79 156 init_opengl();
nuclear@79 157
nuclear@79 158 glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
nuclear@78 159
nuclear@78 160 glEnable(GL_DEPTH_TEST);
nuclear@78 161 glEnable(GL_CULL_FACE);
nuclear@73 162 }
nuclear@73 163
nuclear@73 164 void GoatViewport::resizeGL(int xsz, int ysz)
nuclear@73 165 {
nuclear@73 166 glViewport(0, 0, xsz, ysz);
nuclear@75 167 glMatrixMode(GL_PROJECTION);
nuclear@75 168 glLoadIdentity();
nuclear@75 169 gluPerspective(60.0, (float)xsz / (float)ysz, 0.5, 5000.0);
nuclear@73 170 }
nuclear@73 171
nuclear@73 172 void GoatViewport::paintGL()
nuclear@73 173 {
nuclear@75 174 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@75 175
nuclear@75 176 glMatrixMode(GL_MODELVIEW);
nuclear@75 177 glLoadIdentity();
nuclear@75 178 glTranslatef(0, 0, -cam_dist);
nuclear@75 179 glRotatef(cam_phi, 1, 0, 0);
nuclear@75 180 glRotatef(cam_theta, 0, 1, 0);
nuclear@75 181
nuclear@75 182 if(scene) {
nuclear@75 183 int node_count = goat3d_get_node_count(scene);
nuclear@75 184 for(int i=0; i<node_count; i++) {
nuclear@75 185 goat3d_node *node = goat3d_get_node(scene, i);
nuclear@80 186 //if(!goat3d_get_node_parent(node)) {
nuclear@78 187 draw_node(node); // only draw root nodes, the rest will be drawn recursively
nuclear@80 188 //}
nuclear@75 189 }
nuclear@75 190 }
nuclear@73 191 }
nuclear@75 192
nuclear@75 193 static void draw_node(goat3d_node *node)
nuclear@75 194 {
nuclear@75 195 float xform[16];
nuclear@75 196 goat3d_get_node_matrix(node, xform, anim_time);
nuclear@78 197 for(int i=0; i<4; i++) {
nuclear@79 198 for(int j=0; j<i; j++) {
nuclear@79 199 float tmp = xform[i * 4 + j];
nuclear@79 200 xform[i * 4 + j] = xform[j * 4 + i];
nuclear@79 201 xform[j * 4 + i] = tmp;
nuclear@79 202 }
nuclear@78 203 }
nuclear@78 204
nuclear@78 205 glPushMatrix();
nuclear@80 206 glMultMatrixf(xform);
nuclear@75 207
nuclear@75 208 if(goat3d_get_node_type(node) == GOAT3D_NODE_MESH) {
nuclear@75 209 goat3d_mesh *mesh = (goat3d_mesh*)goat3d_get_node_object(node);
nuclear@75 210
nuclear@75 211 int num_faces = goat3d_get_mesh_face_count(mesh);
nuclear@75 212 int num_verts = goat3d_get_mesh_attrib_count(mesh, GOAT3D_MESH_ATTR_VERTEX);
nuclear@75 213
nuclear@75 214 glEnableClientState(GL_VERTEX_ARRAY);
nuclear@75 215 glVertexPointer(3, GL_FLOAT, 0, goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX));
nuclear@75 216
nuclear@75 217 float *data;
nuclear@75 218 if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL))) {
nuclear@75 219 glEnableClientState(GL_NORMAL_ARRAY);
nuclear@75 220 glNormalPointer(GL_FLOAT, 0, data);
nuclear@75 221 }
nuclear@75 222 if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD))) {
nuclear@75 223 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@75 224 glTexCoordPointer(2, GL_FLOAT, 0, data);
nuclear@75 225 }
nuclear@75 226
nuclear@75 227 int *indices;
nuclear@75 228 if((indices = goat3d_get_mesh_faces(mesh))) {
nuclear@75 229 glDrawElements(GL_TRIANGLES, num_faces * 3, GL_UNSIGNED_INT, indices);
nuclear@75 230 } else {
nuclear@75 231 glDrawArrays(GL_TRIANGLES, 0, num_verts * 3);
nuclear@75 232 }
nuclear@75 233
nuclear@75 234 glDisableClientState(GL_VERTEX_ARRAY);
nuclear@75 235 glDisableClientState(GL_NORMAL_ARRAY);
nuclear@75 236 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
nuclear@75 237 }
nuclear@75 238
nuclear@80 239 /*int num_child = goat3d_get_node_child_count(node);
nuclear@75 240 for(int i=0; i<num_child; i++) {
nuclear@75 241 draw_node(goat3d_get_node_child(node, i));
nuclear@80 242 }*/
nuclear@78 243
nuclear@78 244 glPopMatrix();
nuclear@78 245 }
nuclear@78 246
nuclear@78 247
nuclear@78 248 static float prev_x, prev_y;
nuclear@78 249 void GoatViewport::mousePressEvent(QMouseEvent *ev)
nuclear@78 250 {
nuclear@78 251 prev_x = ev->x();
nuclear@78 252 prev_y = ev->y();
nuclear@78 253 }
nuclear@78 254
nuclear@78 255 void GoatViewport::mouseMoveEvent(QMouseEvent *ev)
nuclear@78 256 {
nuclear@78 257 int dx = ev->x() - prev_x;
nuclear@78 258 int dy = ev->y() - prev_y;
nuclear@80 259 prev_x = ev->x();
nuclear@80 260 prev_y = ev->y();
nuclear@78 261
nuclear@78 262 if(!dx && !dy) return;
nuclear@78 263
nuclear@78 264 if(ev->buttons() & Qt::LeftButton) {
nuclear@78 265 cam_theta += dx * 0.5;
nuclear@78 266 cam_phi += dy * 0.5;
nuclear@78 267
nuclear@78 268 if(cam_phi < -90) cam_phi = -90;
nuclear@78 269 if(cam_phi > 90) cam_phi = 90;
nuclear@78 270 }
nuclear@78 271 if(ev->buttons() & Qt::RightButton) {
nuclear@78 272 cam_dist += dy * 0.1;
nuclear@78 273
nuclear@78 274 if(cam_dist < 0.0) cam_dist = 0.0;
nuclear@78 275 }
nuclear@78 276 updateGL();
nuclear@78 277 }