goat3d

view goatview/src/goatview.cc @ 78:53ea5b25426e

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