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

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