goat3d
changeset 90:8b156bc5205b
[maxgoat] fixed the transform export bug
[goatview] added widgets for the animation controls
[goatview] added a grid ground plane with automatic sizing and transitions from size to size
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 17 May 2014 06:26:24 +0300 |
parents | c1871707c678 |
children | f92da4fa9a6d |
files | exporters/maxgoat/src/maxgoat.cc goatview/src/goatview.cc goatview/src/goatview.h |
diffstat | 3 files changed, 122 insertions(+), 14 deletions(-) [+] |
line diff
1.1 --- a/exporters/maxgoat/src/maxgoat.cc Fri May 16 05:23:10 2014 +0300 1.2 +++ b/exporters/maxgoat/src/maxgoat.cc Sat May 17 06:26:24 2014 +0300 1.3 @@ -295,13 +295,13 @@ 1.4 // grab the animation data 1.5 if(!dynamic_cast<GoatAnimExporter*>(this)) { 1.6 // no animation, just get the static PRS 1.7 - GMatrix maxmatrix = maxnode->GetObjectTM(); 1.8 + GMatrix maxmatrix = maxnode->GetLocalTM(); 1.9 Point3 trans = maxmatrix.Translation(); 1.10 Quat rot = maxmatrix.Rotation(); 1.11 Point3 scale = maxmatrix.Scaling(); 1.12 1.13 goat3d_set_node_position(node, trans.x, trans.y, trans.z, 0); 1.14 - goat3d_set_node_rotation(node, rot.x, rot.y, rot.z, rot.w, 0); 1.15 + goat3d_set_node_rotation(node, rot.x, rot.y, rot.z, -rot.w, 0); 1.16 goat3d_set_node_scaling(node, scale.x, scale.y, scale.z, 0); 1.17 1.18 } else { 1.19 @@ -412,19 +412,19 @@ 1.20 maxlog("node %s: getting %d linear rotation keys\n", nodename, rkeys.Count()); 1.21 for(int i=0; i<rkeys.Count(); i++) { 1.22 Quat q = rkeys[i].linearKey.qval; 1.23 - goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i])); 1.24 + goat3d_set_node_rotation(node, q.x, q.y, q.z, -q.w, KEY_TIME(rkeys[i])); 1.25 } 1.26 } else if(ctrl->GetBezierKeys(rkeys, IGAME_ROT)) { 1.27 maxlog("node %s: getting %d bezier rotation keys\n", nodename, rkeys.Count()); 1.28 for(int i=0; i<rkeys.Count(); i++) { 1.29 Quat q = rkeys[i].bezierKey.qval; 1.30 - goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i])); 1.31 + goat3d_set_node_rotation(node, q.x, q.y, q.z, -q.w, KEY_TIME(rkeys[i])); 1.32 } 1.33 } else if(ctrl->GetTCBKeys(rkeys, IGAME_ROT)) { 1.34 maxlog("node %s: getting %d TCB rotation keys\n", nodename, rkeys.Count()); 1.35 for(int i=0; i<rkeys.Count(); i++) { 1.36 Quat q(rkeys[i].tcbKey.aval); 1.37 - goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, KEY_TIME(rkeys[i])); 1.38 + goat3d_set_node_rotation(node, q.x, q.y, q.z, -q.w, KEY_TIME(rkeys[i])); 1.39 } 1.40 } else { 1.41 get_euler_keys(ctrl, node); 1.42 @@ -471,7 +471,7 @@ 1.43 while(it != euler.end()) { 1.44 Quat q; 1.45 EulerToQuat(it->second, q, order); 1.46 - goat3d_set_node_rotation(node, q.x, q.y, q.z, q.w, it->first); 1.47 + goat3d_set_node_rotation(node, q.x, q.y, q.z, -q.w, it->first); 1.48 ++it; 1.49 } 1.50 }
2.1 --- a/goatview/src/goatview.cc Fri May 16 05:23:10 2014 +0300 2.2 +++ b/goatview/src/goatview.cc Sat May 17 06:26:24 2014 +0300 2.3 @@ -6,22 +6,27 @@ 2.4 #include "goatview.h" 2.5 #include "goat3d.h" 2.6 2.7 +static void draw_grid(); 2.8 +static void draw_grid(float sz, int nlines, float alpha = 1.0f); 2.9 static void draw_node(goat3d_node *node); 2.10 static void draw_mesh(goat3d_mesh *mesh); 2.11 +static int next_pow2(int x); 2.12 2.13 goat3d *scene; 2.14 static SceneModel *sdata; 2.15 static GoatViewport *glview; 2.16 2.17 static long anim_time; 2.18 -static float cam_theta, cam_phi, cam_dist = 8; 2.19 +static float cam_theta, cam_phi = 25, cam_dist = 8; 2.20 static float fov = 60.0; 2.21 static bool use_nodes = true; 2.22 static bool use_lighting = true; 2.23 2.24 void post_redisplay() 2.25 { 2.26 - glview->updateGL(); 2.27 + if(glview) { 2.28 + glview->updateGL(); 2.29 + } 2.30 } 2.31 2.32 2.33 @@ -101,7 +106,7 @@ 2.34 2.35 QAction *act_quit = new QAction("&Quit", this); 2.36 act_quit->setShortcuts(QKeySequence::Quit); 2.37 - connect(act_quit, &QAction::triggered, [&](){qApp->quit();}); 2.38 + connect(act_quit, &QAction::triggered, [&](){ qApp->quit(); }); 2.39 menu_file->addAction(act_quit); 2.40 2.41 // view menu 2.42 @@ -136,7 +141,7 @@ 2.43 QVBoxLayout *dock_vbox = new QVBoxLayout; 2.44 dock_cont->setLayout(dock_vbox); 2.45 2.46 - QDockWidget *dock = new QDockWidget("Scene graph", this); 2.47 + QDockWidget *dock = new QDockWidget(this); 2.48 dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); 2.49 dock->setWidget(dock_cont); 2.50 addDockWidget(Qt::LeftDockWidgetArea, dock); 2.51 @@ -164,11 +169,37 @@ 2.52 QHBoxLayout *dock_hbox = new QHBoxLayout; 2.53 dock_cont->setLayout(dock_hbox); 2.54 2.55 - QSlider *slider_time = new QSlider(Qt::Orientation::Horizontal); 2.56 + // animation control box 2.57 + QGridLayout *anim_ctl_box = new QGridLayout; 2.58 + dock_hbox->addLayout(anim_ctl_box); 2.59 + 2.60 + anim_ctl_box->addWidget(new QLabel("Animation"), 0, 0); 2.61 + cbox_anims = new QComboBox; 2.62 + cbox_anims->setDisabled(true); 2.63 + anim_ctl_box->addWidget(cbox_anims, 0, 1); 2.64 + 2.65 + chk_loop = new QCheckBox("loop"); 2.66 + chk_loop->setChecked(false); 2.67 + anim_ctl_box->addWidget(chk_loop, 1, 0); 2.68 + 2.69 + QToolBar *toolbar_ctl = new QToolBar; 2.70 + anim_ctl_box->addWidget(toolbar_ctl, 1, 1); 2.71 + 2.72 + act_rewind = new QAction(style()->standardIcon(QStyle::SP_MediaSkipBackward), "Rewind", this); 2.73 + act_rewind->setDisabled(true); 2.74 + toolbar_ctl->addAction(act_rewind); 2.75 + act_play = new QAction(style()->standardIcon(QStyle::SP_MediaPlay), "Play", this); 2.76 + act_play->setDisabled(true); 2.77 + toolbar_ctl->addAction(act_play); 2.78 + 2.79 + // timeline slider 2.80 + slider_time = new QSlider(Qt::Orientation::Horizontal); 2.81 slider_time->setDisabled(true); 2.82 + connect(slider_time, &QSlider::valueChanged, 2.83 + [&](){ anim_time = slider_time->value(); post_redisplay(); }); 2.84 dock_hbox->addWidget(slider_time); 2.85 2.86 - dock = new QDockWidget("Animation", this); 2.87 + dock = new QDockWidget(this); 2.88 dock->setAllowedAreas(Qt::BottomDockWidgetArea); 2.89 dock->setWidget(dock_cont); 2.90 addDockWidget(Qt::BottomDockWidgetArea, dock); 2.91 @@ -270,6 +301,8 @@ 2.92 glRotatef(cam_phi, 1, 0, 0); 2.93 glRotatef(cam_theta, 0, 1, 0); 2.94 2.95 + draw_grid(); 2.96 + 2.97 if(!scene) return; 2.98 2.99 if(use_nodes) { 2.100 @@ -304,6 +337,63 @@ 2.101 #error "GLEW_ARB_transpose_matrix undefined?" 2.102 #endif 2.103 2.104 +static void draw_grid() 2.105 +{ 2.106 + float viewsz_orig = cam_dist * tan(DEG_TO_RAD(fov) / 2.0); 2.107 + float sz1 = next_pow2((int)viewsz_orig); 2.108 + float sz0 = sz1 / 2.0; 2.109 + float t = (viewsz_orig - sz0) / (sz1 - sz0); 2.110 + float alpha = t < 0.333333 ? 0.0 : (t > 0.666666 ? 1.0 : (t - 0.333333) / 0.333333); 2.111 + 2.112 + glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BITS); 2.113 + 2.114 + glEnable(GL_BLEND); 2.115 + glDepthFunc(GL_ALWAYS); 2.116 + 2.117 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 2.118 + draw_grid(sz0 * 2.0, 10, 1.0 - alpha); 2.119 + draw_grid(sz1 * 2.0, 10, alpha); 2.120 + 2.121 + glPopAttrib(); 2.122 +} 2.123 + 2.124 +static void draw_grid(float sz, int nlines, float alpha) 2.125 +{ 2.126 + float hsz = sz / 2.0; 2.127 + float offs = sz / (float)nlines; 2.128 + 2.129 + glPushAttrib(GL_ENABLE_BIT); 2.130 + glDisable(GL_LIGHTING); 2.131 + glDisable(GL_TEXTURE_2D); 2.132 + 2.133 + glLineWidth(2.0); 2.134 + glBegin(GL_LINES); 2.135 + glColor4f(1, 0, 0, alpha); 2.136 + glVertex3f(-hsz, 0, 0); 2.137 + glVertex3f(hsz, 0, 0); 2.138 + glColor4f(0, 0, 1, alpha); 2.139 + glVertex3f(0, 0, -hsz); 2.140 + glVertex3f(0, 0, hsz); 2.141 + glEnd(); 2.142 + 2.143 + glLineWidth(1.0); 2.144 + glBegin(GL_LINES); 2.145 + glColor4f(0.5, 0.5, 0.5, alpha); 2.146 + for(int i=0; i<nlines / 2; i++) { 2.147 + float dist = (float)(i + 1) * offs; 2.148 + for(int j=0; j<2; j++) { 2.149 + float sign = j > 0 ? -1.0 : 1.0; 2.150 + glVertex3f(-hsz, 0, dist * sign); 2.151 + glVertex3f(hsz, 0, dist * sign); 2.152 + glVertex3f(dist * sign, 0, -hsz); 2.153 + glVertex3f(dist * sign, 0, hsz); 2.154 + } 2.155 + } 2.156 + glEnd(); 2.157 + 2.158 + glPopAttrib(); 2.159 +} 2.160 + 2.161 static void draw_node(goat3d_node *node) 2.162 { 2.163 SceneNodeData *data = sdata ? sdata->get_node_data(node) : 0; 2.164 @@ -336,14 +426,12 @@ 2.165 glVertex3f(bmax[0], bmin[1], bmax[2]); 2.166 glVertex3f(bmin[0], bmin[1], bmax[2]); 2.167 glEnd(); 2.168 - 2.169 glBegin(GL_LINE_LOOP); 2.170 glVertex3f(bmin[0], bmax[1], bmin[2]); 2.171 glVertex3f(bmax[0], bmax[1], bmin[2]); 2.172 glVertex3f(bmax[0], bmax[1], bmax[2]); 2.173 glVertex3f(bmin[0], bmax[1], bmax[2]); 2.174 glEnd(); 2.175 - 2.176 glBegin(GL_LINES); 2.177 glVertex3f(bmin[0], bmin[1], bmin[2]); 2.178 glVertex3f(bmin[0], bmax[1], bmin[2]); 2.179 @@ -378,8 +466,10 @@ 2.180 2.181 if(mtl && (color = goat3d_get_mtl_attrib(mtl, GOAT3D_MAT_ATTR_DIFFUSE))) { 2.182 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color); 2.183 + glColor3fv(color); 2.184 } else { 2.185 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, white); 2.186 + glColor3fv(white); 2.187 } 2.188 if(mtl && (color = goat3d_get_mtl_attrib(mtl, GOAT3D_MAT_ATTR_SPECULAR))) { 2.189 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, color); 2.190 @@ -475,3 +565,15 @@ 2.191 { 2.192 QMessageBox::information(this, "About GoatView", about_str); 2.193 } 2.194 + 2.195 + 2.196 +static int next_pow2(int x) 2.197 +{ 2.198 + x--; 2.199 + x = (x >> 1) | x; 2.200 + x = (x >> 2) | x; 2.201 + x = (x >> 4) | x; 2.202 + x = (x >> 8) | x; 2.203 + x = (x >> 16) | x; 2.204 + return x + 1; 2.205 +}
3.1 --- a/goatview/src/goatview.h Fri May 16 05:23:10 2014 +0300 3.2 +++ b/goatview/src/goatview.h Sat May 17 06:26:24 2014 +0300 3.3 @@ -21,6 +21,12 @@ 3.4 QTreeView *treeview; 3.5 SceneModel *scene_model; 3.6 3.7 + // animation controls 3.8 + QSlider *slider_time; 3.9 + QComboBox *cbox_anims; 3.10 + QCheckBox *chk_loop; 3.11 + QAction *act_play, *act_rewind; 3.12 + 3.13 void closeEvent(QCloseEvent *ev); 3.14 bool make_menu(); 3.15 bool make_dock();