Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

geartrain.c 30KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085
  1. /*
  2. * GearTrain Simulator * Version: 1.00
  3. *
  4. * Copyright (C) 1999 Shobhan Kumar Dutta All Rights Reserved.
  5. * <skdutta@del3.vsnl.net.in>
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a
  8. * copy of this software and associated documentation files (the "Software"),
  9. * to deal in the Software without restriction, including without limitation
  10. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. * and/or sell copies of the Software, and to permit persons to whom the
  12. * Software is furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included
  15. * in all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  18. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * SHOBHAN KUMAR DUTTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  21. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
  22. * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE.
  24. */
  25. #include <assert.h>
  26. #include <math.h>
  27. #include <stdlib.h>
  28. #include <GL/glut.h>
  29. #include <string.h>
  30. #include <stdio.h>
  31. #ifndef min
  32. #define min(x, y) ( x < y ? x : y )
  33. #endif
  34. #ifndef M_PI
  35. #define M_PI 3.14159265
  36. #endif /* */
  37. typedef GLfloat TDA[4];
  38. TDA background;
  39. struct AXLE
  40. {
  41. char name[20];
  42. GLint id;
  43. GLfloat radius;
  44. GLint axis;
  45. TDA color;
  46. TDA position;
  47. GLfloat length;
  48. GLint motored;
  49. GLfloat angular_velocity;
  50. GLint direction;
  51. };
  52. struct GEAR
  53. {
  54. char name[20];
  55. char type[7];
  56. GLint face;
  57. GLint id;
  58. GLfloat radius;
  59. GLfloat width;
  60. GLint teeth;
  61. GLfloat tooth_depth;
  62. GLfloat angle;
  63. GLfloat angular_velocity;
  64. TDA color;
  65. GLint relative_position;
  66. TDA position;
  67. char axle_name[20];
  68. GLint axis;
  69. GLint direction;
  70. GLint motored;
  71. };
  72. struct BELT
  73. {
  74. char name[20];
  75. GLint id;
  76. char gear1_name[20];
  77. char gear2_name[20];
  78. };
  79. FILE * mainfile;
  80. struct GEAR g[10];
  81. struct AXLE a[10];
  82. struct BELT b[10];
  83. int number_of_gears;
  84. int number_of_axles;
  85. int number_of_belts;
  86. char Buf1[256], Buf2[256], Buf3[256], Buf4[256], Buf5[256];
  87. static GLint T0 = 0;
  88. static GLint Frames = 0;
  89. #ifndef _WIN32
  90. static void
  91. strset (char buf[], char ch)
  92. {
  93. int i;
  94. for (i = 0; i < strlen (buf); i++)
  95. buf[i] = ch;
  96. }
  97. #endif
  98. static void
  99. Clear_Buffers ()
  100. {
  101. strset (Buf1, 0);
  102. strset (Buf2, 0);
  103. strset (Buf3, 0);
  104. strset (Buf4, 0);
  105. strset (Buf5, 0);
  106. }
  107. static void
  108. LoadTriplet (TDA A)
  109. {
  110. int result;
  111. Clear_Buffers ();
  112. result = fscanf (mainfile, "%s %s %s %s", Buf1, Buf2, Buf3, Buf4);
  113. assert(result != EOF);
  114. A[0] = atof (Buf2);
  115. A[1] = atof (Buf3);
  116. A[2] = atof (Buf4);
  117. }
  118. static void
  119. LoadReal (float *a)
  120. {
  121. int result;
  122. Clear_Buffers ();
  123. result = fscanf (mainfile, "%s %s", Buf1, Buf2);
  124. assert(result != EOF);
  125. *a = atof (Buf2);
  126. }
  127. static void
  128. LoadInteger (int *a)
  129. {
  130. int result;
  131. Clear_Buffers ();
  132. result = fscanf (mainfile, "%s %s", Buf1, Buf2);
  133. assert(result != EOF);
  134. *a = atoi (Buf2);
  135. }
  136. static void
  137. LoadText (char *a)
  138. {
  139. int result;
  140. Clear_Buffers ();
  141. result = fscanf (mainfile, "%s %s", Buf1, Buf2);
  142. assert(result != EOF);
  143. strcpy (a, Buf2);
  144. }
  145. static void
  146. getdata (char filename[])
  147. {
  148. int gear_count = 0, axle_count = 0, belt_count = 0, i;
  149. mainfile = fopen (filename, "r");
  150. if (!mainfile) {
  151. printf("Error: couldn't open %s\n", filename);
  152. exit(-1);
  153. }
  154. do
  155. {
  156. int result;
  157. Clear_Buffers ();
  158. result = fscanf (mainfile, "%s", Buf1);
  159. (void) result;
  160. if (ferror (mainfile))
  161. {
  162. printf ("\nError opening file !\n");
  163. exit (1);
  164. }
  165. if (!(strcmp (Buf1, "BACKGROUND")))
  166. LoadTriplet (background);
  167. if (!(strcmp (Buf1, "ANAME")))
  168. {
  169. LoadText (a[axle_count].name);
  170. axle_count++;
  171. }
  172. if (!(strcmp (Buf1, "ARADIUS")))
  173. LoadReal (&a[axle_count - 1].radius);
  174. if (!(strcmp (Buf1, "AAXIS")))
  175. LoadInteger (&a[axle_count - 1].axis);
  176. if (!(strcmp (Buf1, "ACOLOR")))
  177. LoadTriplet (a[axle_count - 1].color);
  178. if (!(strcmp (Buf1, "APOSITION")))
  179. LoadTriplet (a[axle_count - 1].position);
  180. if (!(strcmp (Buf1, "ALENGTH")))
  181. LoadReal (&a[axle_count - 1].length);
  182. if (!(strcmp (Buf1, "AMOTORED")))
  183. LoadInteger (&a[axle_count - 1].motored);
  184. if (!(strcmp (Buf1, "AANGULARVELOCITY")))
  185. LoadReal (&a[axle_count - 1].angular_velocity);
  186. if (!(strcmp (Buf1, "ADIRECTION")))
  187. LoadInteger (&a[axle_count - 1].direction);
  188. if (!(strcmp (Buf1, "GNAME")))
  189. {
  190. LoadText (g[gear_count].name);
  191. gear_count++;
  192. }
  193. if (!(strcmp (Buf1, "GTYPE")))
  194. LoadText (g[gear_count - 1].type);
  195. if (!(strcmp (Buf1, "GFACE")))
  196. LoadInteger (&g[gear_count - 1].face);
  197. if (!(strcmp (Buf1, "GRADIUS")))
  198. LoadReal (&g[gear_count - 1].radius);
  199. if (!(strcmp (Buf1, "GWIDTH")))
  200. LoadReal (&g[gear_count - 1].width);
  201. if (!(strcmp (Buf1, "GTEETH")))
  202. LoadInteger (&g[gear_count - 1].teeth);
  203. if (!(strcmp (Buf1, "GTOOTHDEPTH")))
  204. LoadReal (&g[gear_count - 1].tooth_depth);
  205. if (!(strcmp (Buf1, "GCOLOR")))
  206. LoadTriplet (g[gear_count - 1].color);
  207. if (!(strcmp (Buf1, "GAXLE")))
  208. LoadText (g[gear_count - 1].axle_name);
  209. if (!(strcmp (Buf1, "GPOSITION")))
  210. LoadInteger (&g[gear_count - 1].relative_position);
  211. if (!(strcmp (Buf1, "BELTNAME")))
  212. {
  213. LoadText (b[belt_count].name);
  214. belt_count++;
  215. }
  216. if (!(strcmp (Buf1, "GEAR1NAME")))
  217. LoadText (b[belt_count - 1].gear1_name);
  218. if (!(strcmp (Buf1, "GEAR2NAME")))
  219. LoadText (b[belt_count - 1].gear2_name);
  220. }
  221. while (Buf1[0] != 0);
  222. for (i = 0; i < number_of_gears; i++)
  223. {
  224. g[i].axis = -1;
  225. g[i].direction = 0;
  226. g[i].angular_velocity = 0.0;
  227. }
  228. number_of_gears = gear_count;
  229. number_of_axles = axle_count;
  230. number_of_belts = belt_count;
  231. fclose (mainfile);
  232. }
  233. static void
  234. axle (GLint j, GLfloat radius, GLfloat length)
  235. {
  236. GLfloat angle, rad, incr = 10.0 * M_PI / 180.0;
  237. /* draw main cylinder */
  238. glBegin (GL_QUADS);
  239. for (angle = 0.0; angle < 360.0; angle += 5.0)
  240. {
  241. rad = angle * M_PI / 180.0;
  242. glNormal3f (cos (rad), sin (rad), 0.0);
  243. glVertex3f (radius * cos (rad), radius * sin (rad), length / 2);
  244. glVertex3f (radius * cos (rad), radius * sin (rad), -length / 2);
  245. glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), -length / 2);
  246. glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), length / 2);
  247. }
  248. glEnd ();
  249. /* draw front face */
  250. glNormal3f (0.0, 0.0, 1.0);
  251. glBegin (GL_TRIANGLES);
  252. for (angle = 0.0; angle < 360.0; angle += 5.0)
  253. {
  254. rad = angle * M_PI / 180.0;
  255. glVertex3f (0.0, 0.0, length / 2);
  256. glVertex3f (radius * cos (rad), radius * sin (rad), length / 2);
  257. glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), length / 2);
  258. glVertex3f (0.0, 0.0, length / 2);
  259. }
  260. glEnd ();
  261. /* draw back face */
  262. glNormal3f (0.0, 0.0, -1.0);
  263. glBegin (GL_TRIANGLES);
  264. for (angle = 0.0; angle <= 360.0; angle += 5.0)
  265. {
  266. rad = angle * M_PI / 180.0;
  267. glVertex3f (0.0, 0.0, -length / 2);
  268. glVertex3f (radius * cos (rad), radius * sin (rad), -length / 2);
  269. glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), -length / 2);
  270. glVertex3f (0.0, 0.0, -length / 2);
  271. }
  272. glEnd ();
  273. }
  274. static void
  275. gear (GLint j, char type[], GLfloat radius, GLfloat width,
  276. GLint teeth, GLfloat tooth_depth)
  277. {
  278. GLint i;
  279. GLfloat r1, r2;
  280. GLfloat angle, da;
  281. GLfloat u, v, len, fraction = 0.5;
  282. GLfloat n = 1.0;
  283. r1 = radius - tooth_depth;
  284. r2 = radius;
  285. da = 2.0 * M_PI / teeth / 4.0;
  286. if (!g[j].face)
  287. {
  288. fraction = -0.5;
  289. n = -1.0;
  290. }
  291. if (!(strcmp (type, "NORMAL")))
  292. {
  293. fraction = 0.5;
  294. n = 1.0;
  295. }
  296. /* draw front face */
  297. if (!(strcmp (type, "NORMAL")))
  298. {
  299. glNormal3f (0.0, 0.0, 1.0 * n);
  300. glBegin (GL_QUAD_STRIP);
  301. for (i = 0; i <= teeth; i++)
  302. {
  303. angle = i * 2.0 * M_PI / teeth;
  304. glVertex3f (0.0, 0.0, width * fraction);
  305. glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
  306. glVertex3f (0.0, 0.0, width * fraction);
  307. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
  308. }
  309. glEnd ();
  310. }
  311. else
  312. {
  313. glNormal3f (0.0, 0.0, 1.0 * n);
  314. glBegin (GL_QUAD_STRIP);
  315. for (i = 0; i <= teeth; i++)
  316. {
  317. angle = i * 2.0 * M_PI / teeth;
  318. glVertex3f (0.0, 0.0, width * fraction);
  319. glVertex3f ((r2 - width) * cos (angle), (r2 - width) * sin (angle), width * fraction);
  320. glVertex3f (0.0, 0.0, width * fraction);
  321. glVertex3f ((r2 - width) * cos (angle + 3 * da), (r2 - width) * sin (angle + 3 * da), width * fraction);
  322. }
  323. glEnd ();
  324. }
  325. /* draw front sides of teeth */
  326. if (!(strcmp (type, "NORMAL")))
  327. {
  328. glNormal3f (0.0, 0.0, 1.0 * n);
  329. glBegin (GL_QUADS);
  330. da = 2.0 * M_PI / teeth / 4.0;
  331. for (i = 0; i < teeth; i++)
  332. {
  333. angle = i * 2.0 * M_PI / teeth;
  334. glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
  335. glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), width * fraction);
  336. glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), width * fraction);
  337. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
  338. }
  339. glEnd ();
  340. }
  341. glNormal3f (0.0, 0.0, -1.0 * n);
  342. /* draw back face */
  343. glBegin (GL_QUAD_STRIP);
  344. for (i = 0; i <= teeth; i++)
  345. {
  346. angle = i * 2.0 * M_PI / teeth;
  347. glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
  348. glVertex3f (0.0, 0.0, -width * fraction);
  349. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
  350. glVertex3f (0.0, 0.0, -width * fraction);
  351. }
  352. glEnd ();
  353. /* draw back sides of teeth */
  354. glNormal3f (0.0, 0.0, -1.0 * n);
  355. glBegin (GL_QUADS);
  356. da = 2.0 * M_PI / teeth / 4.0;
  357. for (i = 0; i < teeth; i++)
  358. {
  359. angle = i * 2.0 * M_PI / teeth;
  360. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
  361. glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), -width * fraction);
  362. glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), -width * fraction);
  363. glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
  364. }
  365. glEnd ();
  366. /* draw outward faces of teeth */
  367. if (!(strcmp (type, "NORMAL")))
  368. {
  369. glBegin (GL_QUAD_STRIP);
  370. for (i = 0; i < teeth; i++)
  371. {
  372. angle = i * 2.0 * M_PI / teeth;
  373. glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
  374. glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
  375. u = r2 * cos (angle + da) - r1 * cos (angle);
  376. v = r2 * sin (angle + da) - r1 * sin (angle);
  377. len = sqrt (u * u + v * v);
  378. u /= len;
  379. v /= len;
  380. glNormal3f (v, -u, 0.0);
  381. glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), width * fraction);
  382. glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), -width * fraction);
  383. glNormal3f (cos (angle), sin (angle), 0.0);
  384. glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), width * fraction);
  385. glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), -width * fraction);
  386. u = r1 * cos (angle + 3 * da) - r2 * cos (angle + 2 * da);
  387. v = r1 * sin (angle + 3 * da) - r2 * sin (angle + 2 * da);
  388. glNormal3f (v, -u, 0.0);
  389. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
  390. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
  391. glNormal3f (cos (angle), sin (angle), 0.0);
  392. }
  393. }
  394. else
  395. {
  396. glBegin (GL_QUAD_STRIP);
  397. for (i = 0; i < teeth; i++)
  398. {
  399. angle = i * 2.0 * M_PI / teeth;
  400. glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
  401. glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
  402. u = r2 * cos (angle + da) - r1 * cos (angle);
  403. v = r2 * sin (angle + da) - r1 * sin (angle);
  404. len = sqrt (u * u + v * v);
  405. u /= len;
  406. v /= len;
  407. glNormal3f (v, -u, 0.0);
  408. glVertex3f ((r2 - width) * cos (angle + da), (r2 - width) * sin (angle + da), width * fraction);
  409. glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), -width * fraction);
  410. glNormal3f (cos (angle), sin (angle), n);
  411. glVertex3f ((r2 - width) * cos (angle + 2 * da), (r2 - width) * sin (angle + 2 * da), width * fraction);
  412. glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), -width * fraction);
  413. u = r1 * cos (angle + 3 * da) - r2 * cos (angle + 2 * da);
  414. v = r1 * sin (angle + 3 * da) - r2 * sin (angle + 2 * da);
  415. glNormal3f (v, -u, 0.0);
  416. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
  417. glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
  418. glNormal3f (cos (angle), sin (angle), n);
  419. }
  420. }
  421. glVertex3f (r1 * cos (0), r1 * sin (0), width * fraction);
  422. glVertex3f (r1 * cos (0), r1 * sin (0), -width * fraction);
  423. glEnd ();
  424. }
  425. static void
  426. belt (struct GEAR g1, struct GEAR g2)
  427. {
  428. GLfloat D, alpha, phi, angle, incr, width;
  429. GLint indexes[3] =
  430. {
  431. 0, 0, 0
  432. };
  433. GLfloat col[3] =
  434. {
  435. 0.0, 0.0, 0.0
  436. };
  437. width = min (g1.width, g2.width);
  438. D = sqrt (pow (g1.position[0] - g2.position[0], 2) + pow (g1.position[1] - g2.position[1], 2) + pow (g1.position[2] - g2.position[2], 2));
  439. alpha = acos ((g2.position[0] - g1.position[0]) / D);
  440. phi = acos ((g1.radius - g2.radius) / D);
  441. glBegin (GL_QUADS);
  442. glColor3fv (col);
  443. glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
  444. incr = 1.2 * 360.0 / g1.teeth * M_PI / 180.00;
  445. for (angle = alpha + phi; angle <= 2 * M_PI - phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.00)
  446. {
  447. glNormal3f (cos (angle), sin (angle), 0.0);
  448. glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), width * 0.5);
  449. glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), -width * 0.5);
  450. glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), -width * 0.5);
  451. glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), width * 0.5);
  452. }
  453. glEnd ();
  454. glBegin (GL_QUADS);
  455. glColor3fv (col);
  456. glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
  457. incr = 1.2 * 360.0 / g2.teeth * M_PI / 180.00;
  458. for (angle = -phi + alpha; angle <= phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.0)
  459. {
  460. glNormal3f (cos (angle), sin (angle), 0.0);
  461. glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * 0.5);
  462. glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * -0.5);
  463. glVertex3f (g2.radius * cos (angle + incr) + g2.position[0] - g1.position[0], g2.radius * sin (angle + incr) + g2.position[1] - g1.position[1], width * -0.5);
  464. glVertex3f (g2.radius * cos (angle + incr) + g2.position[0] - g1.position[0], g2.radius * sin (angle + incr) + g2.position[1] - g1.position[1], width * 0.5);
  465. }
  466. glEnd ();
  467. glBegin (GL_QUADS);
  468. glColor3fv (col);
  469. glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
  470. glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * 0.5);
  471. glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * -0.5);
  472. glVertex3f (g2.radius * cos (alpha + phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha + phi) + g2.position[1] - g1.position[1], width * -0.5);
  473. glVertex3f (g2.radius * cos (alpha + phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha + phi) + g2.position[1] - g1.position[1], width * 0.5);
  474. glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * 0.5);
  475. glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * -0.5);
  476. glVertex3f (g2.radius * cos (alpha - phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha - phi) + g2.position[1] - g1.position[1], width * -0.5);
  477. glVertex3f (g2.radius * cos (alpha - phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha - phi) + g2.position[1] - g1.position[1], width * 0.5);
  478. glEnd ();
  479. }
  480. static int
  481. axle_find (char axle_name[])
  482. {
  483. int i;
  484. for (i = 0; i < number_of_axles; i++)
  485. {
  486. if (!(strcmp (axle_name, a[i].name)))
  487. break;
  488. }
  489. return i;
  490. }
  491. static int
  492. gear_find (char gear_name[])
  493. {
  494. int i;
  495. for (i = 0; i < number_of_gears; i++)
  496. {
  497. if (!(strcmp (gear_name, g[i].name)))
  498. break;
  499. }
  500. return i;
  501. }
  502. static void
  503. process ()
  504. {
  505. GLfloat x, y, z, D, dist;
  506. GLint axle_index, i, j, g1, g2, k;
  507. char error[80];
  508. for (i = 0; i < number_of_gears; i++)
  509. {
  510. x = 0.0;
  511. y = 0.0;
  512. z = 0.0;
  513. axle_index = axle_find (g[i].axle_name);
  514. g[i].axis = a[axle_index].axis;
  515. g[i].motored = a[axle_index].motored;
  516. if (a[axle_index].motored)
  517. {
  518. g[i].direction = a[axle_index].direction;
  519. g[i].angular_velocity = a[axle_index].angular_velocity;
  520. }
  521. if (g[i].axis == 0)
  522. x = 1.0;
  523. else if (g[i].axis == 1)
  524. y = 1.0;
  525. else
  526. z = 1.0;
  527. g[i].position[0] = a[axle_index].position[0] + x * g[i].relative_position;
  528. g[i].position[1] = a[axle_index].position[1] + y * g[i].relative_position;
  529. g[i].position[2] = a[axle_index].position[2] + z * g[i].relative_position;
  530. }
  531. for (k = 0; k < number_of_axles; k++)
  532. {
  533. for (i = 0; i < number_of_gears - 1; i++)
  534. {
  535. for (j = 0; j < number_of_gears; j++)
  536. {
  537. if (!(strcmp (g[i].type, g[j].type)) && (!(strcmp (g[i].type, "NORMAL"))) && ((strcmp (g[i].axle_name, g[j].axle_name) != 0)) && (g[i].axis == g[j].axis))
  538. {
  539. D = sqrt (pow (g[i].position[0] - g[j].position[0], 2) + pow (g[i].position[1] - g[j].position[1], 2) + pow (g[i].position[2] - g[j].position[2], 2));
  540. if (D < 1.1 * (g[i].radius - g[i].tooth_depth + g[j].radius - g[j].tooth_depth))
  541. {
  542. printf (error, "Gear %s and %s are too close to each other.", g[i].name, g[j].name);
  543. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  544. exit (1);
  545. }
  546. if (g[i].axis == 0)
  547. {
  548. dist = g[i].position[0] - g[j].position[0];
  549. }
  550. else if (g[i].axis == 1)
  551. {
  552. dist = g[i].position[1] - g[j].position[1];
  553. }
  554. else
  555. dist = g[i].position[2] - g[j].position[2];
  556. dist = fabs (dist);
  557. if (dist < (g[i].width / 2 + g[j].width / 2))
  558. {
  559. if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * (g[i].radius + g[j].radius)))
  560. {
  561. axle_index = axle_find (g[j].axle_name);
  562. if ((a[axle_index].direction != 0) && (g[j].angular_velocity != g[i].angular_velocity * g[i].teeth / g[j].teeth * g[i].radius / g[j].radius))
  563. {
  564. printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
  565. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  566. exit (1);
  567. }
  568. g[j].motored = (a[axle_index].motored = 1);
  569. g[j].direction = (a[axle_index].direction = -g[i].direction);
  570. a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth;
  571. g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius);
  572. }
  573. if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * (g[i].radius + g[j].radius)))
  574. {
  575. axle_index = axle_find (g[i].axle_name);
  576. if ((a[axle_index].direction != 0) && (g[i].angular_velocity != g[j].angular_velocity * g[j].teeth / g[i].teeth * g[j].radius / g[i].radius))
  577. {
  578. printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
  579. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  580. exit (1);
  581. }
  582. g[i].motored = (a[axle_index].motored = 1);
  583. g[i].direction = (a[axle_index].direction = -g[j].direction);
  584. a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth;
  585. g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius);
  586. }
  587. }
  588. }
  589. if (!(strcmp (g[i].type, g[j].type)) && (!(strcmp (g[i].type, "BEVEL"))) && ((strcmp (g[i].axle_name, g[j].axle_name) != 0)) && (g[i].axis != g[j].axis))
  590. {
  591. D = sqrt (pow (g[i].position[0] - g[j].position[0], 2) + pow (g[i].position[1] - g[j].position[1], 2) + pow (g[i].position[2] - g[j].position[2], 2));
  592. if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius)))
  593. {
  594. axle_index = axle_find (g[j].axle_name);
  595. if ((a[axle_index].direction != 0) && (g[j].angular_velocity != g[i].angular_velocity * g[i].teeth / g[j].teeth * g[i].radius / g[j].radius))
  596. {
  597. printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
  598. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  599. exit (1);
  600. }
  601. g[j].motored = (a[axle_index].motored = 1);
  602. g[j].direction = (a[axle_index].direction = -g[i].direction);
  603. a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth;
  604. g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius);
  605. }
  606. if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius)))
  607. {
  608. axle_index = axle_find (g[i].axle_name);
  609. if ((a[axle_index].direction != 0) && (g[i].angular_velocity != g[j].angular_velocity * g[j].teeth / g[i].teeth * g[j].radius / g[i].radius))
  610. {
  611. printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
  612. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  613. exit (1);
  614. }
  615. g[i].motored = (a[axle_index].motored = 1);
  616. g[i].direction = (a[axle_index].direction = -g[j].direction);
  617. a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth;
  618. g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius);
  619. }
  620. }
  621. }
  622. }
  623. for (i = 0; i < number_of_gears; i++)
  624. {
  625. axle_index = axle_find (g[i].axle_name);
  626. g[i].motored = a[axle_index].motored;
  627. if (a[axle_index].motored)
  628. {
  629. g[i].direction = a[axle_index].direction;
  630. g[i].angular_velocity = a[axle_index].angular_velocity;
  631. }
  632. }
  633. for (i = 0; i < number_of_belts; i++)
  634. {
  635. g1 = gear_find (b[i].gear1_name);
  636. g2 = gear_find (b[i].gear2_name);
  637. D = sqrt (pow (g[g1].position[0] - g[g2].position[0], 2) + pow (g[g1].position[1] - g[g2].position[1], 2) + pow (g[g1].position[2] - g[g2].position[2], 2));
  638. if (!((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL"))))
  639. {
  640. printf (error, "Belt %s invalid.", b[i].name);
  641. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  642. exit (1);
  643. }
  644. if ((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL")))
  645. {
  646. /*
  647. if((g[g1].motored)&&(g[g2].motored))
  648. if(g[g2].angular_velocity!=(g[g1].angular_velocity*g[g1].radius/g[g2].radius))
  649. {
  650. printf(error,"Error in belt linkage of gears %s and %s".,g[g1].name,g[g2].name);
  651. MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);
  652. exit(1);
  653. }
  654. */
  655. if (g[g1].axis == 0)
  656. {
  657. dist = g[g1].position[0] - g[g2].position[0];
  658. }
  659. else if (g[i].axis == 1)
  660. {
  661. dist = g[g1].position[1] - g[g2].position[1];
  662. }
  663. else
  664. dist = g[g1].position[2] - g[g2].position[2];
  665. dist = fabs (dist);
  666. if (dist > (g[g1].width / 2 + g[g2].width / 2))
  667. {
  668. printf (error, "Belt %s invalid.", b[i].name);
  669. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  670. exit (1);
  671. }
  672. if (dist < (g[g1].width / 2 + g[g2].width / 2))
  673. {
  674. if (D < g[g1].radius + g[g2].radius)
  675. {
  676. printf (error, "Gears %s and %s too close to be linked with belts", g[g1].name, g[g2].name);
  677. /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
  678. exit (1);
  679. }
  680. if ((g[g1].motored) && (!(g[g2].motored)))
  681. {
  682. axle_index = axle_find (g[g2].axle_name);
  683. g[g2].motored = (a[axle_index].motored = 1);
  684. g[g2].direction = (a[axle_index].direction = g[g1].direction);
  685. g[g2].angular_velocity = (a[axle_index].angular_velocity = g[g1].angular_velocity * g[g1].radius / g[g2].radius);
  686. }
  687. if ((!(g[g1].motored)) && (g[g2].motored))
  688. {
  689. axle_index = axle_find (g[g1].axle_name);
  690. g[g1].motored = (a[axle_index].motored = 1);
  691. g[g1].direction = (a[axle_index].direction = g[g2].direction);
  692. g[g1].angular_velocity = (a[axle_index].angular_velocity = g[g2].angular_velocity * g[g2].radius / g[g1].radius);
  693. }
  694. }
  695. }
  696. }
  697. for (i = 0; i < number_of_gears; i++)
  698. {
  699. axle_index = axle_find (g[i].axle_name);
  700. g[i].motored = a[axle_index].motored;
  701. if (a[axle_index].motored)
  702. {
  703. g[i].direction = a[axle_index].direction;
  704. g[i].angular_velocity = a[axle_index].angular_velocity;
  705. }
  706. }
  707. }
  708. }
  709. GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 10.0;
  710. static void
  711. draw (void)
  712. {
  713. int i;
  714. GLfloat x, y, z;
  715. int index;
  716. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  717. glPushMatrix ();
  718. glRotatef (view_rotx, 1.0, 0.0, 0.0);
  719. glRotatef (view_roty, 0.0, 1.0, 0.0);
  720. glRotatef (view_rotz, 0.0, 0.0, 1.0);
  721. for (i = 0; i < number_of_gears; i++)
  722. {
  723. x = 0.0;
  724. y = 0.0;
  725. z = 0.0;
  726. glPushMatrix ();
  727. /*glTranslatef( -3.0, -2.0, 0.0 );*/
  728. glTranslatef (g[i].position[0], g[i].position[1], g[i].position[2]);
  729. if (g[i].axis == 0)
  730. y = 1.0;
  731. else if (g[i].axis == 1)
  732. x = 1.0;
  733. else
  734. z = 1.0;
  735. if (z != 1.0)
  736. glRotatef (90.0, x, y, z);
  737. glRotatef (g[i].direction * g[i].angle, 0.0, 0.0, 1.0);
  738. glCallList (g[i].id);
  739. glPopMatrix ();
  740. }
  741. for (i = 0; i < number_of_axles; i++)
  742. {
  743. x = 0.0;
  744. y = 0.0;
  745. z = 0.0;
  746. glPushMatrix ();
  747. glTranslatef (a[i].position[0], a[i].position[1], a[i].position[2]);
  748. if (a[i].axis == 0)
  749. y = 1.0;
  750. else if (a[i].axis == 1)
  751. x = 1.0;
  752. else
  753. z = 1.0;
  754. if (z != 1.0)
  755. glRotatef (90.0, x, y, z);
  756. glCallList (a[i].id);
  757. glPopMatrix ();
  758. }
  759. for (i = 0; i < number_of_belts; i++)
  760. {
  761. x = 0.0;
  762. y = 0.0;
  763. z = 0.0;
  764. glPushMatrix ();
  765. index = gear_find (b[i].gear1_name);
  766. glTranslatef (g[index].position[0], g[index].position[1], g[index].position[2]);
  767. if (g[index].axis == 0)
  768. y = 1.0;
  769. else if (g[index].axis == 1)
  770. x = 1.0;
  771. else
  772. z = 1.0;
  773. if (z != 1.0)
  774. glRotatef (90.0, x, y, z);
  775. glCallList (b[i].id);
  776. glPopMatrix ();
  777. }
  778. glPopMatrix ();
  779. glutSwapBuffers ();
  780. {
  781. GLint t = glutGet(GLUT_ELAPSED_TIME);
  782. Frames++;
  783. if (t - T0 >= 5000) {
  784. GLfloat seconds = (t - T0) / 1000.0;
  785. GLfloat fps = Frames / seconds;
  786. printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
  787. fflush(stdout);
  788. T0 = t;
  789. Frames = 0;
  790. }
  791. }
  792. }
  793. static void
  794. idle (void)
  795. {
  796. int i;
  797. static double t0 = -1.;
  798. double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  799. if (t0 < 0.0)
  800. t0 = t;
  801. dt = t - t0;
  802. t0 = t;
  803. for (i = 0; i < number_of_gears; i++)
  804. g[i].angle += g[i].angular_velocity * dt;
  805. glutPostRedisplay();
  806. }
  807. /* change view angle, exit upon ESC */
  808. static void
  809. key (unsigned char k, int x, int y)
  810. {
  811. switch (k)
  812. {
  813. case 'x':
  814. view_rotx += 5.0;
  815. break;
  816. case 'X':
  817. view_rotx -= 5.0;
  818. break;
  819. case 'y':
  820. view_roty += 5.0;
  821. break;
  822. case 'Y':
  823. view_roty -= 5.0;
  824. break;
  825. case 'z':
  826. view_rotz += 5.0;
  827. break;
  828. case 'Z':
  829. view_rotz -= 5.0;
  830. break;
  831. case 0x1B:
  832. exit(0);
  833. }
  834. }
  835. /* new window size or exposure */
  836. static void
  837. reshape (int width, int height)
  838. {
  839. glViewport (0, 0, (GLint) width, (GLint) height);
  840. glMatrixMode (GL_PROJECTION);
  841. glLoadIdentity ();
  842. if (width > height)
  843. {
  844. GLfloat w = (GLfloat) width / (GLfloat) height;
  845. glFrustum (-w, w, -1.0, 1.0, 5.0, 60.0);
  846. }
  847. else
  848. {
  849. GLfloat h = (GLfloat) height / (GLfloat) width;
  850. glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
  851. }
  852. glMatrixMode (GL_MODELVIEW);
  853. glLoadIdentity ();
  854. glTranslatef (0.0, 0.0, -40.0);
  855. glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  856. }
  857. static void
  858. init (void)
  859. {
  860. GLfloat matShine = 20.00F;
  861. GLfloat light0Pos[4] =
  862. {
  863. 0.70F, 0.70F, 1.25F, 0.50F
  864. };
  865. int i;
  866. glClearColor (background[0], background[1], background[2], 1.0F);
  867. glClearIndex ((GLfloat) 0.0);
  868. glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, matShine);
  869. glLightfv (GL_LIGHT0, GL_POSITION, light0Pos);
  870. glEnable (GL_LIGHT0);
  871. glEnable (GL_LIGHTING);
  872. glEnable (GL_DEPTH_TEST);
  873. for (i = 0; i < number_of_gears; i++)
  874. g[i].angle = 0.0;
  875. for (i = 0; i < number_of_gears; i++)
  876. {
  877. g[i].id = glGenLists (1);
  878. glNewList (g[i].id, GL_COMPILE);
  879. glColor3fv (g[i].color);
  880. glMaterialfv (GL_FRONT, GL_SPECULAR, g[i].color);
  881. gear (i, g[i].type, g[i].radius, g[i].width, g[i].teeth, g[i].tooth_depth);
  882. glEndList ();
  883. }
  884. for (i = 0; i < number_of_axles; i++)
  885. {
  886. a[i].id = glGenLists (1);
  887. glNewList (a[i].id, GL_COMPILE);
  888. glColor3fv (a[i].color);
  889. glMaterialfv (GL_FRONT, GL_SPECULAR, a[i].color);
  890. axle (i, a[i].radius, a[i].length);
  891. glEndList ();
  892. }
  893. for (i = 0; i < number_of_belts; i++)
  894. {
  895. b[i].id = glGenLists (1);
  896. glNewList (b[i].id, GL_COMPILE);
  897. belt (g[gear_find (b[i].gear1_name)], g[gear_find (b[i].gear2_name)]);
  898. glEndList ();
  899. }
  900. glEnable (GL_COLOR_MATERIAL);
  901. }
  902. int
  903. main (int argc, char *argv[])
  904. {
  905. char *file;
  906. glutInitWindowSize(640,480);
  907. glutInit(&argc, argv);
  908. glutInitDisplayMode (GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
  909. if (glutCreateWindow ("Gear Train Simulation") == GL_FALSE)
  910. exit (1);
  911. if (argc < 2)
  912. file = "geartrain.dat";
  913. else
  914. file = argv[1];
  915. getdata (file);
  916. process ();
  917. init ();
  918. glutDisplayFunc (draw);
  919. glutReshapeFunc (reshape);
  920. glutKeyboardFunc (key);
  921. glutIdleFunc (idle);
  922. glutMainLoop ();
  923. return 0;
  924. }