Source code of Windows XP (NT5)
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.

870 lines
21 KiB

  1. /*
  2. * (c) Copyright 1993, Silicon Graphics, Inc.
  3. * ALL RIGHTS RESERVED
  4. * Permission to use, copy, modify, and distribute this software for
  5. * any purpose and without fee is hereby granted, provided that the above
  6. * copyright notice appear in all copies and that both the copyright notice
  7. * and this permission notice appear in supporting documentation, and that
  8. * the name of Silicon Graphics, Inc. not be used in advertising
  9. * or publicity pertaining to distribution of the software without specific,
  10. * written prior permission.
  11. *
  12. * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS"
  13. * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE,
  14. * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR
  15. * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
  16. * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT,
  17. * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY
  18. * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION,
  19. * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF
  20. * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN
  21. * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON
  22. * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE
  23. * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE.
  24. *
  25. * US Government Users Restricted Rights
  26. * Use, duplication, or disclosure by the Government is subject to
  27. * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
  28. * (c)(1)(ii) of the Rights in Technical Data and Computer Software
  29. * clause at DFARS 252.227-7013 and/or in similar or successor
  30. * clauses in the FAR or the DOD or NASA FAR Supplement.
  31. * Unpublished-- rights reserved under the copyright laws of the
  32. * United States. Contractor/manufacturer is Silicon Graphics,
  33. * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311.
  34. *
  35. * OpenGL(TM) is a trademark of Silicon Graphics, Inc.
  36. */
  37. extern "C" {
  38. #include <windows.h>
  39. #include <GL/glu.h>
  40. }
  41. #include <stdio.h>
  42. #include <stdlib.h>
  43. #include <math.h>
  44. #include "Unitdisk.hxx"
  45. const float fudge = .000001;
  46. const float M_2PI = 2.0 * M_PI;
  47. Unitdisk::Unitdisk()
  48. {
  49. rdivisions = 3;
  50. tdivisions = 10;
  51. points = normals = NULL;
  52. colors = NULL;
  53. points_size = normals_size = colors_size = 0;
  54. angle = M_PI;
  55. zaxis[0] = 0;
  56. zaxis[1] = 0;
  57. zaxis[2] = 1;
  58. still_in_xy = 1;
  59. sintable = costable = NULL;
  60. }
  61. Unitdisk::~Unitdisk()
  62. {
  63. }
  64. void Unitdisk::draw()
  65. {
  66. if (points == NULL) return;
  67. glNormal3f(0, 0, 1);
  68. if (colors == NULL) draw_nocolors();
  69. else if (normals == NULL) draw_colors_nonormals();
  70. else draw_colors_normals();
  71. }
  72. void Unitdisk::draw_nocolors()
  73. {
  74. int r, t, p1, p2;
  75. int has_n;
  76. has_n = (normals != NULL);
  77. for (t = 1; t < tdivisions; t++) {
  78. glBegin(GL_QUAD_STRIP);
  79. p1 = t * (rdivisions + 1);
  80. p2 = (t - 1) * (rdivisions + 1);
  81. for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  82. if (has_n) glNormal3fv(normals[p1].pt);
  83. #ifdef TEXTURE
  84. glTexCoord2fv(points[p1].pt);
  85. #endif
  86. glVertex3fv(points[p1].pt);
  87. if (has_n) glNormal3fv(normals[p2].pt);
  88. #ifdef TEXTURE
  89. glTexCoord2fv(points[p2].pt);
  90. #endif
  91. glVertex3fv(points[p2].pt);
  92. }
  93. glEnd();
  94. }
  95. glBegin(GL_QUAD_STRIP);
  96. p1 = 0;
  97. p2 = (rdivisions + 1) * (tdivisions - 1);
  98. for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  99. if (has_n) glNormal3fv(normals[p1].pt);
  100. #ifdef TEXTURE
  101. glTexCoord2fv(points[p1].pt);
  102. #endif
  103. glVertex3fv(points[p1].pt);
  104. if (has_n) glNormal3fv(normals[p2].pt);
  105. #ifdef TEXTURE
  106. glTexCoord2fv(points[p2].pt);
  107. #endif
  108. glVertex3fv(points[p2].pt);
  109. }
  110. glEnd();
  111. }
  112. void Unitdisk::draw_colors_nonormals()
  113. {
  114. int r, t, p1, p2;
  115. for (t = 1; t < tdivisions; t++) {
  116. glBegin(GL_QUAD_STRIP);
  117. p1 = t * (rdivisions + 1);
  118. p2 = (t - 1) * (rdivisions + 1);
  119. for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  120. glColor4fv(colors[p1].c);
  121. #ifdef TEXTURE
  122. glTexCoord2fv(points[p1].pt);
  123. #endif
  124. glVertex3fv(points[p1].pt);
  125. glColor4fv(colors[p2].c);
  126. #ifdef TEXTURE
  127. glTexCoord2fv(points[p2].pt);
  128. #endif
  129. glVertex3fv(points[p2].pt);
  130. }
  131. glEnd();
  132. }
  133. glBegin(GL_QUAD_STRIP);
  134. p1 = 0;
  135. p2 = (rdivisions + 1) * (tdivisions - 1);
  136. for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  137. glColor4fv(colors[p1].c);
  138. #ifdef TEXTURE
  139. glTexCoord2fv(points[p1].pt);
  140. #endif
  141. glVertex3fv(points[p1].pt);
  142. glColor4fv(colors[p2].c);
  143. #ifdef TEXTURE
  144. glTexCoord2fv(points[p2].pt);
  145. #endif
  146. glVertex3fv(points[p2].pt);
  147. }
  148. glEnd();
  149. }
  150. void Unitdisk::draw_colors_normals()
  151. {
  152. int r, t, p1, p2;
  153. for (t = 1; t < tdivisions; t++) {
  154. glBegin(GL_QUAD_STRIP);
  155. p1 = t * (rdivisions + 1);
  156. p2 = (t - 1) * (rdivisions + 1);
  157. for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  158. glColor4fv(colors[p1].c);
  159. glNormal3fv(normals[p1].pt);
  160. #ifdef TEXTURE
  161. glTexCoord2fv(points[p1].pt);
  162. #endif
  163. glVertex3fv(points[p1].pt);
  164. glColor4fv(colors[p2].c);
  165. glNormal3fv(normals[p2].pt);
  166. #ifdef TEXTURE
  167. glTexCoord2fv(points[p2].pt);
  168. #endif
  169. glVertex3fv(points[p2].pt);
  170. }
  171. glEnd();
  172. }
  173. glBegin(GL_QUAD_STRIP);
  174. p1 = 0;
  175. p2 = (rdivisions + 1) * (tdivisions - 1);
  176. for (r = 0; r <= rdivisions; r++, p1++, p2++) {
  177. glColor4fv(colors[p1].c);
  178. glNormal3fv(normals[p1].pt);
  179. #ifdef TEXTURE
  180. glTexCoord2fv(points[p1].pt);
  181. #endif
  182. glVertex3fv(points[p1].pt);
  183. glColor4fv(colors[p2].c);
  184. glNormal3fv(normals[p2].pt);
  185. #ifdef TEXTURE
  186. glTexCoord2fv(points[p2].pt);
  187. #endif
  188. glVertex3fv(points[p2].pt);
  189. }
  190. glEnd();
  191. }
  192. void Unitdisk::draw_by_perimeter(int pass_colors, int pass_norms,
  193. int pass_tex)
  194. {
  195. int i, index, r = rdivisions + 1;
  196. if (points == NULL) return;
  197. if (pass_colors && colors == NULL) {
  198. fprintf(stderr, "Warning: No colors to draw in Unitdisk.c++");
  199. pass_colors = 0;
  200. }
  201. if (pass_norms && normals == NULL) {
  202. fprintf(stderr, "Warning: No normals to draw in Unitdisk.c++");
  203. pass_norms = 0;
  204. }
  205. glBegin(GL_POLYGON);
  206. for (i = 0, index = rdivisions; i < tdivisions; i++, index += r) {
  207. if (pass_colors) glColor4fv(colors[index].c);
  208. if (pass_norms) glNormal3fv(normals[index].pt);
  209. #ifdef TEXTURE
  210. if (pass_tex) glTexCoord2fv(points[index].pt);
  211. #endif
  212. glVertex3fv(points[index].pt);
  213. }
  214. glEnd();
  215. }
  216. void Unitdisk::set_angle(float new_angle)
  217. {
  218. angle = new_angle;
  219. }
  220. GLfloat Unitdisk::get_angle()
  221. {
  222. return angle;
  223. }
  224. GLfloat Unitdisk::get_radius()
  225. {
  226. return (GLfloat)cos((double)((M_PI - angle) / 2.0));
  227. }
  228. void Unitdisk::set_divisions(int new_rdivisions, int new_tdivisions)
  229. {
  230. if (tdivisions != new_tdivisions) {
  231. delete sintable;
  232. delete costable;
  233. sintable = costable = NULL;
  234. }
  235. if (tdivisions != new_tdivisions || rdivisions != new_rdivisions) {
  236. rdivisions = new_rdivisions;
  237. tdivisions = new_tdivisions;
  238. free_points();
  239. free_normals();
  240. free_colors();
  241. }
  242. }
  243. int Unitdisk::get_rdivisions()
  244. {
  245. return rdivisions;
  246. }
  247. int Unitdisk::get_tdivisions()
  248. {
  249. return tdivisions;
  250. }
  251. void Unitdisk::alloc_points()
  252. {
  253. int npoints = get_npoints();
  254. if (npoints > points_size) {
  255. delete points;
  256. points = new Point[npoints];
  257. points_size = npoints;
  258. }
  259. }
  260. void Unitdisk::alloc_normals()
  261. {
  262. int npoints = get_npoints();
  263. if (npoints > normals_size) {
  264. delete normals;
  265. normals = new Point[npoints];
  266. normals_size = npoints;
  267. }
  268. }
  269. void Unitdisk::alloc_points_normals()
  270. {
  271. alloc_points();
  272. alloc_normals();
  273. }
  274. void Unitdisk::free_points()
  275. {
  276. delete points;
  277. points = NULL;
  278. points_size = 0;
  279. }
  280. void Unitdisk::free_normals()
  281. {
  282. delete normals;
  283. normals = NULL;
  284. normals_size = 0;
  285. }
  286. void Unitdisk::free_points_normals()
  287. {
  288. free_points();
  289. free_normals();
  290. }
  291. void Unitdisk::fill_points()
  292. {
  293. alloc_points();
  294. fill_either(points);
  295. }
  296. void Unitdisk::fill_normals()
  297. {
  298. alloc_normals();
  299. fill_either(normals);
  300. }
  301. void Unitdisk::fill_points_normals()
  302. {
  303. alloc_points();
  304. alloc_normals();
  305. fill_either(points);
  306. fill_either(normals);
  307. }
  308. void Unitdisk::copy_points(Unitdisk src)
  309. {
  310. set_divisions(src.rdivisions, src.tdivisions);
  311. alloc_points();
  312. copy_either(points, src.points);
  313. }
  314. void Unitdisk::copy_normals(Unitdisk src)
  315. {
  316. set_divisions(src.rdivisions, src.tdivisions);
  317. alloc_normals();
  318. copy_either(normals, src.normals);
  319. }
  320. void Unitdisk::copy_either(Point *dpt, Point *spt) {
  321. int i, npoints;
  322. npoints = get_npoints();
  323. for (i = 0; i < npoints; i++, dpt++, spt++) {
  324. dpt->pt[0] = spt->pt[0];
  325. dpt->pt[1] = spt->pt[1];
  326. dpt->pt[2] = spt->pt[2];
  327. }
  328. }
  329. void Unitdisk::copy_normals_from_points(Unitdisk src) {
  330. set_divisions(src.rdivisions, src.tdivisions);
  331. alloc_normals();
  332. copy_either(normals, src.points);
  333. }
  334. void Unitdisk::copy_normals_from_points() {
  335. copy_normals_from_points(*this);
  336. }
  337. void Unitdisk::fill_either(Point *what) {
  338. int t, r;
  339. int i;
  340. fill_either_strip1(what);
  341. if (sintable == NULL) fill_trig_tables();
  342. i = rdivisions + 1;
  343. for (t = 1; t < tdivisions; t++) {
  344. for (r = 0; r <= rdivisions; r++) {
  345. what[i].pt[0] = costable[t] * what[r].pt[0];
  346. what[i].pt[1] = sintable[t] * what[r].pt[0];
  347. what[i].pt[2] = what[r].pt[2];
  348. i++;
  349. }
  350. }
  351. }
  352. void Unitdisk::fill_points_strip1()
  353. {
  354. alloc_points();
  355. fill_either_strip1(points);
  356. }
  357. void Unitdisk::fill_either_strip1(Point *what) {
  358. float radius, rinc;
  359. int r;
  360. rinc = get_radius() / (float)rdivisions;
  361. radius = 0.0;
  362. for (r = 0; r <= rdivisions; r++, radius += rinc) {
  363. what[r].pt[0] = radius;
  364. what[r].pt[1] = 0;
  365. // Round-off error avoidance hack
  366. what[r].pt[2] = (GLfloat)(1.0 - what[r].pt[0]*what[r].pt[0]);
  367. if (what[r].pt[2] > 0.0) what[r].pt[2] = (GLfloat)sqrt((double)what[r].pt[2]);
  368. else what[r].pt[2] = 0.0;
  369. }
  370. }
  371. void Unitdisk::translate(Point trans)
  372. {
  373. int i, npoints;
  374. npoints = get_npoints();
  375. for (i = 0; i < npoints; i++) {
  376. points[i].pt[0] += trans.pt[0];
  377. points[i].pt[1] += trans.pt[1];
  378. points[i].pt[2] += trans.pt[2];
  379. }
  380. }
  381. void Unitdisk::scale(float s)
  382. {
  383. int i, npoints;
  384. npoints = get_npoints();
  385. for (i = 0; i < npoints; i++) {
  386. points[i].pt[0] *= s;
  387. points[i].pt[1] *= s;
  388. points[i].pt[2] *= s;
  389. }
  390. }
  391. void Unitdisk::scale_translate(float s, Point trans)
  392. {
  393. int i, npoints;
  394. npoints = get_npoints();
  395. for (i = 0; i < npoints; i++) {
  396. points[i].pt[0] = points[i].pt[0]*s + trans.pt[0];
  397. points[i].pt[1] = points[i].pt[1]*s + trans.pt[1];
  398. points[i].pt[2] = points[i].pt[2]*s + trans.pt[2];
  399. }
  400. }
  401. int Unitdisk::get_npoints()
  402. {
  403. return (rdivisions + 1) * tdivisions;
  404. }
  405. void Unitdisk::project()
  406. {
  407. int i, npoints;
  408. if (normals == NULL) {
  409. fprintf(stderr, "Warning: No normals defined when project() called.\n");
  410. fill_normals();
  411. }
  412. if (points == NULL) fill_points();
  413. npoints = get_npoints();
  414. for (i = 0; i < npoints; i++) {
  415. /* I'm not sure quite what the justification for this is, but it
  416. * seems to work */
  417. if (normals[i].pt[2] < 0.0) normals[i].pt[2] = -normals[i].pt[2];
  418. points[i] = points[i].project_direction(normals[i]);
  419. }
  420. }
  421. void Unitdisk::project(Point projpt)
  422. {
  423. int i, npoints = get_npoints();
  424. float x, y, z;
  425. Point *pt;
  426. if (points == NULL) fill_points();
  427. x = projpt.pt[0];
  428. y = projpt.pt[1];
  429. z = projpt.pt[2];
  430. pt = points;
  431. for (i = 0; i < npoints; i++, pt++) pt->project_self(x, y, z);
  432. }
  433. void Unitdisk::project_borrow_points(Unitdisk src)
  434. {
  435. int i, npoints = get_npoints();
  436. Point *pt, *spt, *sn;
  437. spt = src.points;
  438. sn = normals;
  439. alloc_points();
  440. pt = points;
  441. for (i = 0; i < npoints; i++, pt++, spt++, sn++) {
  442. /* I'm not sure quite what the justification for this is, but it
  443. * seems to work */
  444. if (normals[i].pt[2] < 0.0) normals[i].pt[2] = -normals[i].pt[2];
  445. pt->compute_projected(spt->pt[0], spt->pt[1], spt->pt[2],
  446. sn->pt[0], sn->pt[1], sn->pt[2]);
  447. }
  448. }
  449. void Unitdisk::refract_normals(Point light, GLfloat I)
  450. {
  451. Point dlight;
  452. float cos1, sin1, cos2, sin2;
  453. int use_normals;
  454. int r, t, i;
  455. if (points == NULL) {
  456. fprintf(stderr, "Attempting to refract without points.\n");
  457. fill_normals();
  458. }
  459. use_normals = (normals != NULL);
  460. alloc_normals();
  461. /* Do the theta = 0 diagonal */
  462. for (r = 0; r <= rdivisions; r++) {
  463. /* Find the original normal - use the unit of the points if there are
  464. * no normals */
  465. if (!use_normals) normals[r] = points[r].unit();
  466. /* Compute the direction to the light */
  467. dlight = (light - points[r]).unit();
  468. /* Compute the cosine and the sine of the original angle */
  469. cos1 = dlight.dot(normals[r]);
  470. sin1 = (float)(1.0 - cos1*cos1);
  471. if (sin1 <= 0.0) continue;
  472. sin1 = (float)sqrt((double)sin1);
  473. /* Compute the cosine and the sine of the new angle */
  474. sin2 = sin1 / I;
  475. cos2 = (float)sqrt((double)(1.0 - sin2*sin2));
  476. /* Rotate the normal by the new sine and cosine */
  477. normals[r] = normals[r].rotate_abouty(cos2, -sin2);
  478. }
  479. /* Copy the rest of the rows from the current row */
  480. i = rdivisions + 1;
  481. if (sintable == NULL) fill_trig_tables();
  482. for (t = 1; t < tdivisions; t++) {
  483. for (r = 0; r <= rdivisions; r++) {
  484. normals[i].pt[0] = costable[t] * normals[r].pt[0];
  485. normals[i].pt[1] = sintable[t] * normals[r].pt[0];
  486. normals[i].pt[2] = normals[r].pt[2];
  487. i++;
  488. }
  489. }
  490. }
  491. void Unitdisk::face_direction(Point d)
  492. {
  493. face_direction(d, *this);
  494. }
  495. void Unitdisk::face_direction(Point d, Unitdisk src)
  496. {
  497. Point *spt, *dpt, *sn, *dn;
  498. float sin1, cos1;
  499. float x;
  500. int npoints, i;
  501. if (d.pt[1]) {
  502. fprintf(stderr,
  503. "Internal error: Can't face in direction not in xz plane.");
  504. return;
  505. }
  506. cos1 = d.pt[2];
  507. sin1 = d.pt[0];
  508. if (sin1 * sin1 > fudge) {
  509. spt = src.points;
  510. dpt = points;
  511. sn = src.normals;
  512. dn = normals;
  513. /* Change this to be seperate loops for points&&normals, points, normals
  514. * (faster than testing every iteration */
  515. npoints = get_npoints();
  516. for (i = 0; i < npoints; i++) {
  517. if (points != NULL) {
  518. x = spt->pt[0];
  519. dpt->pt[0] = x*cos1 + spt->pt[2]*sin1;
  520. dpt->pt[1] = spt->pt[1];
  521. dpt->pt[2] = -x*sin1 + spt->pt[2]*cos1;
  522. spt++; dpt++;
  523. }
  524. if (normals != NULL) {
  525. x = sn->pt[0];
  526. dn->pt[0] = x*cos1 + sn->pt[2]*sin1;
  527. dn->pt[1] = sn->pt[1];
  528. dn->pt[2] = -x*sin1 + sn->pt[2]*cos1;
  529. sn++; dn++;
  530. }
  531. }
  532. } else if (points != NULL && points != src.points) {
  533. copy_points(src);
  534. if (normals != NULL) copy_normals(src);
  535. }
  536. }
  537. void Unitdisk::alloc_colors()
  538. {
  539. int ncolors = get_npoints();
  540. if (ncolors > colors_size) {
  541. delete colors;
  542. colors = new Color[ncolors];
  543. colors_size = ncolors;
  544. }
  545. }
  546. void Unitdisk::map_normals_to_colors()
  547. {
  548. int t, r;
  549. int i;
  550. if (normals == NULL) fill_normals();
  551. alloc_colors();
  552. i = 0;
  553. for (t = 1; t <= tdivisions; t++) {
  554. for (r = 0; r <= rdivisions; r++) {
  555. colors[i] *= normals[r].pt[2];
  556. colors[i].c[3] = 1;
  557. i++;
  558. }
  559. }
  560. }
  561. void Unitdisk::map_z_to_colors()
  562. {
  563. int i, npoints = get_npoints();
  564. if (points == NULL) {
  565. fprintf(stderr, "Warning: no points defined in map_z_to_colors()\n");
  566. fill_points();
  567. }
  568. alloc_colors();
  569. for (i = 0; i < npoints; i++) {
  570. colors[i] = points[i].pt[2];
  571. colors[i].c[3] = 1;
  572. }
  573. }
  574. void Unitdisk::scale_alpha_by_z()
  575. {
  576. int i, npoints = get_npoints();
  577. if (colors == NULL) alloc_colors();
  578. if (points == NULL) {
  579. alloc_points();
  580. fill_points();
  581. }
  582. for (i = 0; i < npoints; i++) colors[i].c[3] *= points[i].pt[2];
  583. }
  584. void Unitdisk::scale_colors_by_z()
  585. {
  586. int i, npoints = get_npoints();
  587. if (colors == NULL) alloc_colors();
  588. if (points == NULL) {
  589. alloc_points();
  590. fill_points();
  591. }
  592. for (i = 0; i < npoints; i++) colors[i] *= points[i].pt[2];
  593. }
  594. void Unitdisk::scale_colors_by_normals(Point light)
  595. {
  596. scale_colors_by_normals(light, *this);
  597. }
  598. void Unitdisk::scale_colors_by_normals(Point light, Unitdisk src_normals)
  599. {
  600. scale_colors_by_either(light, src_normals.normals);
  601. }
  602. void Unitdisk::scale_colors_by_points(Point light, Unitdisk src_points)
  603. {
  604. scale_colors_by_either(light, src_points.points);
  605. }
  606. void Unitdisk::scale_colors_by_either(Point light, Point *what)
  607. {
  608. int t, r;
  609. int i;
  610. if (what == NULL) {
  611. fprintf(stderr, "Scaling colors to NULL pointer.\n");
  612. return;
  613. }
  614. if (light.pt[0] || light.pt[1] || light.pt[2] < 0.0) {
  615. fprintf(stderr, "Light not on z axis in scale_colors_by_normals.\n");
  616. }
  617. alloc_colors();
  618. for (r = 0; r <= rdivisions; r++)
  619. colors[r] *= what[r].dot(light);
  620. i = rdivisions + 1;
  621. for (t = 1; t < tdivisions; t++) {
  622. for (r = 0; r <= rdivisions; r++) {
  623. colors[i] = colors[r];
  624. i++;
  625. }
  626. }
  627. }
  628. void Unitdisk::set_colors(Color c)
  629. {
  630. Color *dst;
  631. int i, npoints = get_npoints();
  632. alloc_colors();
  633. dst = colors;
  634. for (i = 0; i < npoints; i++, dst++) {
  635. dst->c[0] = c.c[0];
  636. dst->c[1] = c.c[1];
  637. dst->c[2] = c.c[2];
  638. dst->c[3] = c.c[3];
  639. }
  640. }
  641. void Unitdisk::add_colors(Color c)
  642. {
  643. int i, npoints = get_npoints();
  644. alloc_colors();
  645. for (i = 0; i < npoints; i++) colors[i] += c;
  646. }
  647. void Unitdisk::free_colors()
  648. {
  649. delete colors;
  650. colors = NULL;
  651. colors_size = 0;
  652. }
  653. inline float Unitdisk::area_triangle(Point a, Point b, Point c)
  654. {
  655. return (float)(((a.pt[0]*b.pt[1] + b.pt[0]*c.pt[1] + c.pt[0]*a.pt[1]) -
  656. (a.pt[1]*b.pt[0] + b.pt[1]*c.pt[0] + c.pt[1]*a.pt[0])) * .5);
  657. }
  658. inline float Unitdisk::area_triangle(GLfloat *a, GLfloat *b,
  659. GLfloat *c)
  660. {
  661. return (float)(((a[0]*b[1] + b[0]*c[1] + c[0]*a[1]) -
  662. (a[1]*b[0] + b[1]*c[0] + c[1]*a[0])) * .5);
  663. }
  664. inline float Unitdisk::area_2triangle(GLfloat *a, GLfloat *b,
  665. GLfloat *c)
  666. {
  667. return ((a[0]*b[1] + b[0]*c[1] + c[0]*a[1]) -
  668. (a[1]*b[0] + b[1]*c[0] + c[1]*a[0]));
  669. }
  670. void Unitdisk::scale_colors_by_darea(Unitdisk disk)
  671. {
  672. int pt1, pt2, pt3;
  673. int t, r, i;
  674. int npoints = get_npoints();
  675. float *rproducts1, *tproducts1, *rproducts2, *tproducts2;
  676. float area1, area2;
  677. rproducts1 = new float[npoints];
  678. tproducts1 = new float[npoints];
  679. rproducts2 = new float[npoints];
  680. tproducts2 = new float[npoints];
  681. /* Compute the products of the segments which make up the disk -
  682. * these will later be used in the area calculations */
  683. i = 0;
  684. for (t = 0; t < tdivisions; t++) {
  685. for (r = 0; r < rdivisions; r++) {
  686. pt1 = i;
  687. pt2 = i + 1;
  688. rproducts1[i] = (points[pt1].pt[0]*points[pt2].pt[1] -
  689. points[pt1].pt[1]*points[pt2].pt[0]);
  690. rproducts2[i] = (disk.points[pt1].pt[0]*disk.points[pt2].pt[1] -
  691. disk.points[pt1].pt[1]*disk.points[pt2].pt[0]);
  692. pt2 = ((t+1)%tdivisions)*(rdivisions + 1) + r;
  693. tproducts1[i] = (points[pt1].pt[0]*points[pt2].pt[1] -
  694. points[pt1].pt[1]*points[pt2].pt[0]);
  695. tproducts2[i] = (disk.points[pt1].pt[0]*disk.points[pt2].pt[1] -
  696. disk.points[pt1].pt[1]*disk.points[pt2].pt[0]);
  697. i++;
  698. }
  699. pt1 = i;
  700. pt2 = ((t+1)%tdivisions)*(rdivisions + 1) + r;
  701. tproducts1[i] = (points[pt1].pt[0]*points[pt2].pt[1] -
  702. points[pt1].pt[1]*points[pt2].pt[0]);
  703. tproducts2[i] = (disk.points[pt1].pt[0]*disk.points[pt2].pt[1] -
  704. disk.points[pt1].pt[1]*disk.points[pt2].pt[0]);
  705. i++;
  706. }
  707. /* Compute the area at the center of the disk */
  708. area1 = area2 = 0.0;
  709. r = 1;
  710. for (t = 0; t <= tdivisions; t++) {
  711. pt1 = (t%tdivisions)*(rdivisions+1) + r;
  712. area1 += tproducts1[pt1];
  713. area2 += tproducts2[pt1];
  714. }
  715. if (area1 != 0.0) area1 = (float)fabs((double)(area2 / area1));
  716. for (t = 0; t < tdivisions; t++) {
  717. colors[t*(rdivisions+1)] *= area1;
  718. }
  719. for (t = 0; t < tdivisions; t++) {
  720. for (r = 1; r < rdivisions; r++) {
  721. pt1 = (t ? t-1 : tdivisions-1)*(rdivisions+1) + r - 1;
  722. pt3 = t*(rdivisions + 1) + r - 1;
  723. pt2 = ((t+1) % tdivisions)*(rdivisions+1) + r - 1;
  724. area1 = rproducts1[pt1] + rproducts1[pt1 + 1];
  725. area1 += tproducts1[pt1 + 2] + tproducts1[pt3 + 2];
  726. area1 -= rproducts1[pt2 + 1] + rproducts1[pt2];
  727. area1 -= tproducts1[pt3] + tproducts1[pt1];
  728. area2 = rproducts2[pt1] + rproducts2[pt1 + 1];
  729. area2 += tproducts2[pt1 + 2] + tproducts2[pt3 + 2];
  730. area2 -= rproducts2[pt2 + 1] + rproducts2[pt2];
  731. area2 -= tproducts2[pt3] + tproducts2[pt1];
  732. if (area1 != 0.0) area1 = (float)fabs((double)(area2 / area1));
  733. colors[pt3 + 1] *= area1;
  734. }
  735. }
  736. /* Compute the area around the outside of the disk */
  737. r = rdivisions;
  738. for (t = 0; t < tdivisions; t++) {
  739. pt1 = (t ? t-1 : tdivisions-1)*(rdivisions+1) + r - 1;
  740. pt3 = t*(rdivisions + 1) + r - 1;
  741. pt2 = ((t+1) % tdivisions)*(rdivisions+1) + r - 1;
  742. area1 = rproducts1[pt1];
  743. area1 += tproducts1[pt1 + 1] + tproducts1[pt3 + 1];
  744. area1 -= rproducts1[pt2];
  745. area1 -= tproducts1[pt1] + tproducts1[pt3];
  746. area2 = rproducts2[pt1];
  747. area2 += tproducts2[pt1 + 1] + tproducts2[pt3 + 1];
  748. area2 -= rproducts2[pt2];
  749. area2 -= tproducts2[pt1] + tproducts2[pt3];
  750. if (area1 != 0.0) area1 = (float)fabs((double)(area2 / area1));
  751. colors[pt3 + 1] *= area1;
  752. }
  753. delete rproducts1;
  754. delete tproducts1;
  755. delete rproducts2;
  756. delete tproducts2;
  757. }
  758. void Unitdisk::fill_trig_tables()
  759. {
  760. int t;
  761. delete sintable;
  762. delete costable;
  763. sintable = new float[tdivisions];
  764. costable = new float[tdivisions];
  765. for (t = 0; t < tdivisions; t++) {
  766. costable[t] = (float)cos((double)(M_2PI * (float)t / (float)tdivisions));
  767. sintable[t] = (float)sin((double)(M_2PI * (float)t / (float)tdivisions));
  768. }
  769. }