goat3d

view goatview/src/goatview.cc @ 76:9785847d52d4

bounding boxes calculation (untested) and automatic camera placement in goatview
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 08 May 2014 13:43:45 +0300
parents 76dea247f75c
children 53ea5b25426e
line source
1 #include <QtOpenGL/QtOpenGL>
2 #include <GL/glu.h>
3 #include <vmath/vmath.h>
4 #include "goatview.h"
5 #include "goat3d.h"
7 goat3d *scene;
8 QSettings *settings;
10 static long anim_time;
11 static float cam_theta, cam_phi, cam_dist = 8;
12 static float fov = 60.0;
14 bool load_scene(const char *fname)
15 {
16 if(scene) {
17 goat3d_free(scene);
18 }
19 if(!(scene = goat3d_create()) || goat3d_load(scene, fname) == -1) {
20 return false;
21 }
23 float bmin[3], bmax[3];
24 goat3d_get_bounds(scene, bmin, bmax);
25 float bsize = (Vector3(bmax[0], bmax[1], bmax[2]) - Vector3(bmin[0], bmin[1], bmin[2])).length();
26 cam_dist = bsize / tan(DEG_TO_RAD(fov) / 2.0) + bsize;
28 printf("bounds size: %f, cam_dist: %f\n", bsize, cam_dist);
29 return true;
30 }
32 GoatView::GoatView()
33 {
34 make_menu();
35 make_dock();
36 make_center();
38 statusBar();
40 setWindowTitle("GoatView");
41 resize(settings->value("main/size", QSize(1024, 768)).toSize());
42 move(settings->value("main/pos", QPoint(100, 100)).toPoint());
43 }
45 GoatView::~GoatView()
46 {
47 }
49 void GoatView::closeEvent(QCloseEvent *ev)
50 {
51 settings->setValue("main/size", size());
52 settings->setValue("main/pos", pos());
53 }
55 bool GoatView::make_menu()
56 {
57 QMenu *menu_file = menuBar()->addMenu("&File");
59 QAction *act_open_sce = new QAction("&Open Scene", this);
60 act_open_sce->setShortcuts(QKeySequence::Open);
61 connect(act_open_sce, &QAction::triggered, this, &GoatView::open_scene);
62 menu_file->addAction(act_open_sce);
64 QAction *act_open_anm = new QAction("Open &Animation", this);
65 connect(act_open_anm, &QAction::triggered, this, &GoatView::open_anim);
66 menu_file->addAction(act_open_anm);
68 QAction *act_quit = new QAction("&Quit", this);
69 act_quit->setShortcuts(QKeySequence::Quit);
70 connect(act_quit, &QAction::triggered, [&](){qApp->quit();});
71 menu_file->addAction(act_quit);
72 return true;
73 }
75 bool GoatView::make_dock()
76 {
77 // ---- side-dock ----
78 QWidget *dock_cont = new QWidget;
79 QVBoxLayout *dock_vbox = new QVBoxLayout;
80 dock_cont->setLayout(dock_vbox);
82 QPushButton *bn_quit = new QPushButton("quit");
83 dock_vbox->addWidget(bn_quit);
84 connect(bn_quit, &QPushButton::clicked, [&](){qApp->quit();});
86 QDockWidget *dock = new QDockWidget("Scene graph", this);
87 dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
88 dock->setWidget(dock_cont);
89 addDockWidget(Qt::LeftDockWidgetArea, dock);
91 // ---- bottom dock ----
92 dock_cont = new QWidget;
93 QHBoxLayout *dock_hbox = new QHBoxLayout;
94 dock_cont->setLayout(dock_hbox);
96 QSlider *slider_time = new QSlider(Qt::Orientation::Horizontal);
97 slider_time->setDisabled(true);
98 dock_hbox->addWidget(slider_time);
100 dock = new QDockWidget("Animation", this);
101 dock->setAllowedAreas(Qt::BottomDockWidgetArea);
102 dock->setWidget(dock_cont);
103 addDockWidget(Qt::BottomDockWidgetArea, dock);
105 return true;
106 }
108 bool GoatView::make_center()
109 {
110 GoatViewport *vport = new GoatViewport;
111 setCentralWidget(vport);
112 return true;
113 }
115 void GoatView::open_scene()
116 {
117 std::string fname = QFileDialog::getOpenFileName(this, "Open scene file", "",
118 "Goat3D Scene (*.goatsce);;All Files (*)").toStdString();
119 if(fname.empty()) {
120 statusBar()->showMessage("Abort: No file selected!");
121 return;
122 }
124 statusBar()->showMessage("opening scene file");
125 if(!load_scene(fname.c_str())) {
126 statusBar()->showMessage("failed to load scene file");
127 }
128 }
130 void GoatView::open_anim()
131 {
132 statusBar()->showMessage("opening animation...");
133 }
136 // ---- OpenGL viewport ----
137 GoatViewport::GoatViewport()
138 : QGLWidget(QGLFormat(QGL::DepthBuffer))
139 {
140 }
142 GoatViewport::~GoatViewport()
143 {
144 }
146 QSize GoatViewport::sizeHint() const
147 {
148 return QSize(800, 600);
149 }
151 void GoatViewport::initializeGL()
152 {
153 glClearColor(0.1, 0.1, 0.1, 1);
154 }
156 void GoatViewport::resizeGL(int xsz, int ysz)
157 {
158 glViewport(0, 0, xsz, ysz);
159 glMatrixMode(GL_PROJECTION);
160 glLoadIdentity();
161 gluPerspective(60.0, (float)xsz / (float)ysz, 0.5, 5000.0);
162 }
164 static void draw_node(goat3d_node *node);
166 void GoatViewport::paintGL()
167 {
168 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
170 glMatrixMode(GL_MODELVIEW);
171 glLoadIdentity();
172 glTranslatef(0, 0, -cam_dist);
173 glRotatef(cam_phi, 1, 0, 0);
174 glRotatef(cam_theta, 0, 1, 0);
176 if(scene) {
177 int node_count = goat3d_get_node_count(scene);
178 for(int i=0; i<node_count; i++) {
179 goat3d_node *node = goat3d_get_node(scene, i);
180 draw_node(node);
181 }
182 }
183 }
185 static void draw_node(goat3d_node *node)
186 {
187 float xform[16];
188 goat3d_get_node_matrix(node, xform, anim_time);
189 glMultMatrixf(xform);
191 if(goat3d_get_node_type(node) == GOAT3D_NODE_MESH) {
192 goat3d_mesh *mesh = (goat3d_mesh*)goat3d_get_node_object(node);
194 int num_faces = goat3d_get_mesh_face_count(mesh);
195 int num_verts = goat3d_get_mesh_attrib_count(mesh, GOAT3D_MESH_ATTR_VERTEX);
197 glEnableClientState(GL_VERTEX_ARRAY);
198 glVertexPointer(3, GL_FLOAT, 0, goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_VERTEX));
200 float *data;
201 if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_NORMAL))) {
202 glEnableClientState(GL_NORMAL_ARRAY);
203 glNormalPointer(GL_FLOAT, 0, data);
204 }
205 if((data = (float*)goat3d_get_mesh_attribs(mesh, GOAT3D_MESH_ATTR_TEXCOORD))) {
206 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
207 glTexCoordPointer(2, GL_FLOAT, 0, data);
208 }
210 int *indices;
211 if((indices = goat3d_get_mesh_faces(mesh))) {
212 glDrawElements(GL_TRIANGLES, num_faces * 3, GL_UNSIGNED_INT, indices);
213 } else {
214 glDrawArrays(GL_TRIANGLES, 0, num_verts * 3);
215 }
217 glDisableClientState(GL_VERTEX_ARRAY);
218 glDisableClientState(GL_NORMAL_ARRAY);
219 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
220 }
222 int num_child = goat3d_get_node_child_count(node);
223 for(int i=0; i<num_child; i++) {
224 draw_node(goat3d_get_node_child(node, i));
225 }