Commit 0224d2ef24298c824520c87e21a96cb28a8c14d2
1 parent
057ea93b
fixed square wave connection bugs : degenerate case. Added new features for vect…
…or field visualization
Showing
2 changed files
with
214 additions
and
39 deletions
Show diff stats
@@ -1013,7 +1013,7 @@ namespace stim { | @@ -1013,7 +1013,7 @@ namespace stim { | ||
1013 | } | 1013 | } |
1014 | 1014 | ||
1015 | // draw main feeder as solid cube | 1015 | // draw main feeder as solid cube |
1016 | - void glSolidCuboid(bool manufacture = false, T length = 40.0f, T height = 10.0f) { | 1016 | + void glSolidCuboid(bool arrow, GLint subdivision, bool manufacture = false, T length = 40.0f, T height = 10.0f) { |
1017 | 1017 | ||
1018 | T width; | 1018 | T width; |
1019 | stim::vec3<T> L = bb.A; // get the bottom left corner | 1019 | stim::vec3<T> L = bb.A; // get the bottom left corner |
@@ -1073,6 +1073,46 @@ namespace stim { | @@ -1073,6 +1073,46 @@ namespace stim { | ||
1073 | glVertex3f(main_feeder[i][0] + length / 2, main_feeder[i][1] - height / 2, main_feeder[i][2] + width / 2); | 1073 | glVertex3f(main_feeder[i][0] + length / 2, main_feeder[i][1] - height / 2, main_feeder[i][2] + width / 2); |
1074 | glEnd(); | 1074 | glEnd(); |
1075 | } | 1075 | } |
1076 | + | ||
1077 | + // render total flow direction | ||
1078 | + if (arrow) { | ||
1079 | + stim::vec3<T> d = main_feeder[1] - main_feeder[0]; | ||
1080 | + d = d.norm(); | ||
1081 | + stim::vec3<T> v1, v2, v3; | ||
1082 | + stim::vec3<T> center = bb.center(); | ||
1083 | + stim::vec3<T> size = bb.size(); | ||
1084 | + stim::circle<float> tmp_c; | ||
1085 | + tmp_c.rotate(d); | ||
1086 | + std::vector<typename stim::vec3<float> > cp1(subdivision + 1); | ||
1087 | + std::vector<typename stim::vec3<float> > cp2(subdivision + 1); | ||
1088 | + v2 = center - stim::vec3<T>(0.0f, size[1] + 10.0f, 0.0f); | ||
1089 | + v1 = v2 - stim::vec3<T>(30.0f, 0.0f, 0.0f); | ||
1090 | + v3 = v2 + stim::vec3<T>(30.0f, 0.0f, 0.0f); | ||
1091 | + v2 = v2 + stim::vec3<T>(20.0f, 0.0f, 0.0f); | ||
1092 | + | ||
1093 | + // draw the total flow direciton indicating arrow | ||
1094 | + stim::circle<T> c1(v1, 5.0f / 2, d, tmp_c.U); | ||
1095 | + cp1 = c1.glpoints(subdivision); | ||
1096 | + stim::circle<T> c2(v2, 5.0f / 2, d, tmp_c.U); | ||
1097 | + cp2 = c2.glpoints(subdivision); | ||
1098 | + | ||
1099 | + glColor3f(0.0f, 1.0f, 0.0f); | ||
1100 | + glBegin(GL_QUAD_STRIP); | ||
1101 | + for (unsigned k = 0; k < cp1.size(); k++) { | ||
1102 | + glVertex3f(cp1[k][0], cp1[k][1], cp1[k][2]); | ||
1103 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | ||
1104 | + } | ||
1105 | + glEnd(); | ||
1106 | + | ||
1107 | + // render the cone part | ||
1108 | + stim::circle<T> c3(v2, 5.0f, d, tmp_c.U); | ||
1109 | + cp2 = c3.glpoints(subdivision); | ||
1110 | + glBegin(GL_TRIANGLE_FAN); | ||
1111 | + glVertex3f(v3[0], v3[1], v3[2]); | ||
1112 | + for (unsigned k = 0; k < cp2.size(); k++) | ||
1113 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | ||
1114 | + glEnd(); | ||
1115 | + } | ||
1076 | glFlush(); | 1116 | glFlush(); |
1077 | } | 1117 | } |
1078 | 1118 | ||
@@ -1163,8 +1203,8 @@ namespace stim { | @@ -1163,8 +1203,8 @@ namespace stim { | ||
1163 | glPopMatrix(); | 1203 | glPopMatrix(); |
1164 | } | 1204 | } |
1165 | 1205 | ||
1166 | - // draw the bridge as lines | ||
1167 | - void line_bridge(bool &redisplay) { | 1206 | + // draw the bridge as lines or arrows |
1207 | + void line_bridge(bool &redisplay, bool arrow, T r = 4.0f) { | ||
1168 | 1208 | ||
1169 | if (redisplay) | 1209 | if (redisplay) |
1170 | glDeleteLists(dlist, 1); | 1210 | glDeleteLists(dlist, 1); |
@@ -1173,28 +1213,152 @@ namespace stim { | @@ -1173,28 +1213,152 @@ namespace stim { | ||
1173 | if (!glIsList(dlist)) { | 1213 | if (!glIsList(dlist)) { |
1174 | dlist = glGenLists(1); | 1214 | dlist = glGenLists(1); |
1175 | glNewList(dlist, GL_COMPILE); | 1215 | glNewList(dlist, GL_COMPILE); |
1176 | - | ||
1177 | - glLineWidth(5); | ||
1178 | - for (unsigned i = 0; i < inlet.size(); i++) { | ||
1179 | - if (inlet_feasibility[i]) | ||
1180 | - glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | ||
1181 | - else | ||
1182 | - glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | ||
1183 | 1216 | ||
1184 | - glBegin(GL_LINE_STRIP); | ||
1185 | - for (unsigned j = 0; j < inlet[i].V.size(); j++) | ||
1186 | - glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); | ||
1187 | - glEnd(); | 1217 | + // render flow direction arrows |
1218 | + if (arrow) { | ||
1219 | + // v1----v2-->v3 | ||
1220 | + T k = 4.0f; // quartering | ||
1221 | + stim::vec3<T> v1, v2, v3; // three point | ||
1222 | + stim::vec3<T> d; // direction vector | ||
1223 | + stim::circle<float> tmp_c; | ||
1224 | + std::vector<typename stim::vec3<float> > cp1(subdivision + 1); | ||
1225 | + std::vector<typename stim::vec3<float> > cp2(subdivision + 1); | ||
1226 | + | ||
1227 | + // inlet, right-going | ||
1228 | + for (unsigned i = 0; i < inlet.size(); i++) { | ||
1229 | + if (inlet_feasibility[i]) | ||
1230 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | ||
1231 | + else | ||
1232 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | ||
1233 | + for (unsigned j = 0; j < inlet[i].V.size() - 1; j++) { | ||
1234 | + v1 = inlet[i].V[j]; | ||
1235 | + v3 = inlet[i].V[j + 1]; | ||
1236 | + d = v3 - v1; | ||
1237 | + // place the arrow in the middel of one edge | ||
1238 | + v2 = v1 + (1.0f / k * 2.0f) * d; // looks like =->= | ||
1239 | + v1 = v1 + (1.0f / k) * d; | ||
1240 | + v3 = v3 - (1.0f / k) * d; | ||
1241 | + d = d.norm(); | ||
1242 | + tmp_c.rotate(d); | ||
1243 | + | ||
1244 | + // render the cylinder part | ||
1245 | + stim::circle<T> c1(v1, r / 2, d, tmp_c.U); | ||
1246 | + cp1 = c1.glpoints(subdivision); | ||
1247 | + stim::circle<T> c2(v2, r / 2, d, tmp_c.U); | ||
1248 | + cp2 = c2.glpoints(subdivision); | ||
1249 | + | ||
1250 | + glBegin(GL_QUAD_STRIP); | ||
1251 | + for (unsigned k = 0; k < cp1.size(); k++) { | ||
1252 | + glVertex3f(cp1[k][0], cp1[k][1], cp1[k][2]); | ||
1253 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | ||
1254 | + } | ||
1255 | + glEnd(); | ||
1256 | + | ||
1257 | + // render the cone part | ||
1258 | + stim::circle<T> c3(v2, r, d, tmp_c.U); | ||
1259 | + cp2 = c3.glpoints(subdivision); | ||
1260 | + glBegin(GL_TRIANGLE_FAN); | ||
1261 | + glVertex3f(v3[0], v3[1], v3[2]); | ||
1262 | + for (unsigned k = 0; k < cp2.size(); k++) | ||
1263 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | ||
1264 | + glEnd(); | ||
1265 | + } | ||
1266 | + } | ||
1267 | + | ||
1268 | + // outlet, right-going | ||
1269 | + for (unsigned i = 0; i < outlet.size(); i++) { | ||
1270 | + if (outlet_feasibility[i]) | ||
1271 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | ||
1272 | + else | ||
1273 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | ||
1274 | + for (unsigned j = 0; j < outlet[i].V.size() - 1; j++) { | ||
1275 | + v1 = outlet[i].V[j + 1]; | ||
1276 | + v3 = outlet[i].V[j]; | ||
1277 | + d = v3 - v1; | ||
1278 | + // place the arrow in the middel of one edge | ||
1279 | + v2 = v1 + (1.0f / k * 2.0f) * d; // looks like =->= | ||
1280 | + v1 = v1 + (1.0f / k) * d; | ||
1281 | + v3 = v3 - (1.0f / k) * d; | ||
1282 | + d = d.norm(); | ||
1283 | + tmp_c.rotate(d); | ||
1284 | + | ||
1285 | + // render the cylinder part | ||
1286 | + stim::circle<T> c1(v1, r / 2, d, tmp_c.U); | ||
1287 | + cp1 = c1.glpoints(subdivision); | ||
1288 | + stim::circle<T> c2(v2, r / 2, d, tmp_c.U); | ||
1289 | + cp2 = c2.glpoints(subdivision); | ||
1290 | + | ||
1291 | + glBegin(GL_QUAD_STRIP); | ||
1292 | + for (unsigned k = 0; k < cp1.size(); k++) { | ||
1293 | + glVertex3f(cp1[k][0], cp1[k][1], cp1[k][2]); | ||
1294 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | ||
1295 | + } | ||
1296 | + glEnd(); | ||
1297 | + | ||
1298 | + // render the cone part | ||
1299 | + stim::circle<T> c3(v2, r, d, tmp_c.U); | ||
1300 | + cp2 = c3.glpoints(subdivision); | ||
1301 | + glBegin(GL_TRIANGLE_FAN); | ||
1302 | + glVertex3f(v3[0], v3[1], v3[2]); | ||
1303 | + for (unsigned k = 0; k < cp2.size(); k++) | ||
1304 | + glVertex3f(cp2[k][0], cp2[k][1], cp2[k][2]); | ||
1305 | + glEnd(); | ||
1306 | + } | ||
1307 | + } | ||
1308 | + | ||
1309 | + // render transparent lines as indexing | ||
1310 | + glEnable(GL_BLEND); // enable color blend | ||
1311 | + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // set blend function | ||
1312 | + glDisable(GL_DEPTH_TEST); | ||
1313 | + glLineWidth(5); | ||
1314 | + for (unsigned i = 0; i < inlet.size(); i++) { | ||
1315 | + if (inlet_feasibility[i]) | ||
1316 | + glColor4f(0.0f, 0.0f, 0.0f, 0.2f); // feasible -> black | ||
1317 | + else | ||
1318 | + glColor4f(1.0f, 0.0f, 0.0f, 0.2f); // nonfeasible -> red | ||
1319 | + | ||
1320 | + glBegin(GL_LINE_STRIP); | ||
1321 | + for (unsigned j = 0; j < inlet[i].V.size(); j++) | ||
1322 | + glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); | ||
1323 | + glEnd(); | ||
1324 | + } | ||
1325 | + for (unsigned i = 0; i < outlet.size(); i++) { | ||
1326 | + if (outlet_feasibility[i]) | ||
1327 | + glColor4f(0.0f, 0.0f, 0.0f, 0.2f); // feasible -> black | ||
1328 | + else | ||
1329 | + glColor4f(1.0f, 0.0f, 0.0f, 0.2f); // nonfeasible -> red | ||
1330 | + glBegin(GL_LINE_STRIP); | ||
1331 | + for (unsigned j = 0; j < outlet[i].V.size(); j++) | ||
1332 | + glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); | ||
1333 | + glEnd(); | ||
1334 | + } | ||
1335 | + glDisable(GL_BLEND); | ||
1336 | + glEnable(GL_DEPTH_TEST); | ||
1188 | } | 1337 | } |
1189 | - for (unsigned i = 0; i < outlet.size(); i++) { | ||
1190 | - if (outlet_feasibility[i]) | ||
1191 | - glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | ||
1192 | - else | ||
1193 | - glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | ||
1194 | - glBegin(GL_LINE_STRIP); | ||
1195 | - for (unsigned j = 0; j < outlet[i].V.size(); j++) | ||
1196 | - glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); | ||
1197 | - glEnd(); | 1338 | + // render connection lines |
1339 | + else { | ||
1340 | + glLineWidth(5); | ||
1341 | + for (unsigned i = 0; i < inlet.size(); i++) { | ||
1342 | + if (inlet_feasibility[i]) | ||
1343 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | ||
1344 | + else | ||
1345 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | ||
1346 | + | ||
1347 | + glBegin(GL_LINE_STRIP); | ||
1348 | + for (unsigned j = 0; j < inlet[i].V.size(); j++) | ||
1349 | + glVertex3f(inlet[i].V[j][0], inlet[i].V[j][1], inlet[i].V[j][2]); | ||
1350 | + glEnd(); | ||
1351 | + } | ||
1352 | + for (unsigned i = 0; i < outlet.size(); i++) { | ||
1353 | + if (outlet_feasibility[i]) | ||
1354 | + glColor3f(0.0f, 0.0f, 0.0f); // feasible -> black | ||
1355 | + else | ||
1356 | + glColor3f(1.0f, 0.0f, 0.0f); // nonfeasible -> red | ||
1357 | + glBegin(GL_LINE_STRIP); | ||
1358 | + for (unsigned j = 0; j < outlet[i].V.size(); j++) | ||
1359 | + glVertex3f(outlet[i].V[j][0], outlet[i].V[j][1], outlet[i].V[j][2]); | ||
1360 | + glEnd(); | ||
1361 | + } | ||
1198 | } | 1362 | } |
1199 | glFlush(); | 1363 | glFlush(); |
1200 | glEndList(); | 1364 | glEndList(); |
@@ -1617,10 +1781,10 @@ namespace stim { | @@ -1617,10 +1781,10 @@ namespace stim { | ||
1617 | 1781 | ||
1618 | // find the number of U-shape or square-shape structure for extending length of connection | 1782 | // find the number of U-shape or square-shape structure for extending length of connection |
1619 | // @param t: width = t * radius | 1783 | // @param t: width = t * radius |
1620 | - int find_number_square(T origin_l, T desire_l, T radius = 5.0f, int times = 4) { | 1784 | + int find_number_square(T origin_l, T desire_l, T radius = 5.0f, int times = 10) { |
1621 | 1785 | ||
1622 | bool done = false; // flag indicates the current number of square shape structure is feasible | 1786 | bool done = false; // flag indicates the current number of square shape structure is feasible |
1623 | - int n = origin_l / (times * 4 * radius);// number of square shape structure | 1787 | + int n = origin_l / (times * 4 * radius); // number of square shape structure |
1624 | T need_l = desire_l - origin_l; | 1788 | T need_l = desire_l - origin_l; |
1625 | T height; // height of the square shapce structure | 1789 | T height; // height of the square shapce structure |
1626 | 1790 | ||
@@ -1638,7 +1802,7 @@ namespace stim { | @@ -1638,7 +1802,7 @@ namespace stim { | ||
1638 | } | 1802 | } |
1639 | 1803 | ||
1640 | // build square connections | 1804 | // build square connections |
1641 | - void build_square_connection(int i, T width, T height, T origin_l, T desire_l, int n, int feeder, T threshold, bool z, bool left = true, bool up = true, int times = 4, T ratio = 0, T radius = 5.0f) { | 1805 | + void build_square_connection(int i, T width, T height, T origin_l, T desire_l, int n, int feeder, T threshold, bool z, bool left = true, bool up = true, int times = 10, T ratio = 0, T radius = 5.0f) { |
1642 | 1806 | ||
1643 | int coef_up = (up) ? 1 : -1; // y coefficient | 1807 | int coef_up = (up) ? 1 : -1; // y coefficient |
1644 | int coef_left = (left) ? 1 : -1; // x coefficient | 1808 | int coef_left = (left) ? 1 : -1; // x coefficient |
@@ -1669,8 +1833,8 @@ namespace stim { | @@ -1669,8 +1833,8 @@ namespace stim { | ||
1669 | 1833 | ||
1670 | // there are cases that the fragment can not satisfy the requirement for width | 1834 | // there are cases that the fragment can not satisfy the requirement for width |
1671 | if (width < times * radius || n == 0) { // check feasibility | 1835 | if (width < times * radius || n == 0) { // check feasibility |
1672 | - ratio = 0.0f; // load | ||
1673 | - desire_l = tmp_d; | 1836 | + ratio = 0.0f; // load original lengths |
1837 | + desire_l = tmp_d; | ||
1674 | origin_l = tmp_l; | 1838 | origin_l = tmp_l; |
1675 | 1839 | ||
1676 | std::cout << "Warning: current ratio is not feasible, use full original line." << std::endl; | 1840 | std::cout << "Warning: current ratio is not feasible, use full original line." << std::endl; |
@@ -2134,7 +2298,7 @@ namespace stim { | @@ -2134,7 +2298,7 @@ namespace stim { | ||
2134 | width = (T)origin_l / (2 * n); | 2298 | width = (T)origin_l / (2 * n); |
2135 | height = (desire_l - origin_l) / (2 * n); | 2299 | height = (desire_l - origin_l) / (2 * n); |
2136 | 2300 | ||
2137 | - build_square_connection(i, width, height, origin_l, desire_l, n, 1, threshold, z, true, upper, 5, ratio); | 2301 | + build_square_connection(i, width, height, origin_l, desire_l, n, 1, threshold, z, true, upper, 2, ratio); |
2138 | inlet[i].V.push_back(bus_v); | 2302 | inlet[i].V.push_back(bus_v); |
2139 | 2303 | ||
2140 | std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex | 2304 | std::reverse(inlet[i].V.begin(), inlet[i].V.end()); // from bus to pendant vertex |
@@ -2183,7 +2347,7 @@ namespace stim { | @@ -2183,7 +2347,7 @@ namespace stim { | ||
2183 | width = (T)origin_l / (2 * n); | 2347 | width = (T)origin_l / (2 * n); |
2184 | height = (desire_l - origin_l) / (2 * n); | 2348 | height = (desire_l - origin_l) / (2 * n); |
2185 | 2349 | ||
2186 | - build_square_connection(i, width, height, origin_l, desire_l, n, 0, threshold, z, false, upper, 5, ratio); | 2350 | + build_square_connection(i, width, height, origin_l, desire_l, n, 0, threshold, z, false, upper, 2, ratio); |
2187 | outlet[i].V.push_back(bus_v); | 2351 | outlet[i].V.push_back(bus_v); |
2188 | 2352 | ||
2189 | std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex | 2353 | std::reverse(outlet[i].V.begin(), outlet[i].V.end()); // from bus to pendant vertex |
main.cu
@@ -268,17 +268,16 @@ void glut_render() { | @@ -268,17 +268,16 @@ void glut_render() { | ||
268 | else | 268 | else |
269 | flow.glyph(color, subdivision); | 269 | flow.glyph(color, subdivision); |
270 | 270 | ||
271 | - flow.glSolidCuboid(manufacture, length); | 271 | + flow.glSolidCuboid(flow_direction, subdivision, manufacture, length); |
272 | if (render_direction) | 272 | if (render_direction) |
273 | flow.glSolidCone(direction_index, scale, subdivision); | 273 | flow.glSolidCone(direction_index, scale, subdivision); |
274 | } | 274 | } |
275 | 275 | ||
276 | - if (build_inlet_outlet) { | ||
277 | - flow.line_bridge(redisplay); | ||
278 | - } | ||
279 | - | 276 | + if (build_inlet_outlet) |
277 | + flow.line_bridge(redisplay, flow_direction); | ||
278 | + | ||
280 | if (manufacture) { | 279 | if (manufacture) { |
281 | - flow.glSolidCuboid(manufacture, length); | 280 | + flow.glSolidCuboid(flow_direction, subdivision, manufacture, length); |
282 | flow.tube_bridge(subdivision); | 281 | flow.tube_bridge(subdivision); |
283 | } | 282 | } |
284 | 283 | ||
@@ -470,7 +469,8 @@ void glut_menu(int value) { | @@ -470,7 +469,8 @@ void glut_menu(int value) { | ||
470 | flow_stable_state(); // main function of solving the linear system | 469 | flow_stable_state(); // main function of solving the linear system |
471 | flow.print_flow(); | 470 | flow.print_flow(); |
472 | 471 | ||
473 | - glut_set_menu(num, 2); | 472 | + if (!flow_direction) |
473 | + glut_set_menu(num, 2); | ||
474 | } | 474 | } |
475 | 475 | ||
476 | if (value == 2) { | 476 | if (value == 2) { |
@@ -496,6 +496,7 @@ void glut_menu(int value) { | @@ -496,6 +496,7 @@ void glut_menu(int value) { | ||
496 | simulation = false; | 496 | simulation = false; |
497 | build_inlet_outlet = false; | 497 | build_inlet_outlet = false; |
498 | manufacture = true; | 498 | manufacture = true; |
499 | + flow_direction = false; // manufacuture mode doesn't need flow direction | ||
499 | } | 500 | } |
500 | 501 | ||
501 | if (value == 4) { | 502 | if (value == 4) { |
@@ -855,10 +856,20 @@ void glut_keyboard(unsigned char key, int x, int y) { | @@ -855,10 +856,20 @@ void glut_keyboard(unsigned char key, int x, int y) { | ||
855 | 856 | ||
856 | // flow vector field visualization, Glyphs | 857 | // flow vector field visualization, Glyphs |
857 | case 'f': | 858 | case 'f': |
858 | - if (flow_direction && !manufacture && (simulation || build_inlet_outlet)) | 859 | + if (flow_direction && !manufacture && (simulation || build_inlet_outlet)) { |
859 | flow_direction = false; | 860 | flow_direction = false; |
860 | - else if(!flow_direction && !manufacture && (simulation || build_inlet_outlet)) | 861 | + redisplay = true; // lines and arrows rendering use the same display list |
862 | + int num = glutGet(GLUT_MENU_NUM_ITEMS); | ||
863 | + if (num == 1) | ||
864 | + glut_set_menu(num, 2); | ||
865 | + } | ||
866 | + else if (!flow_direction && !manufacture && (simulation || build_inlet_outlet)) { | ||
861 | flow_direction = true; | 867 | flow_direction = true; |
868 | + redisplay = true; | ||
869 | + int num = glutGet(GLUT_MENU_NUM_ITEMS); | ||
870 | + if (num == 2) | ||
871 | + glut_set_menu(num, 1); | ||
872 | + } | ||
862 | break; | 873 | break; |
863 | 874 | ||
864 | // open/close index marks | 875 | // open/close index marks |