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