TeapotGeometry.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /**
  2. * @author Eric Haines / http://erichaines.com/
  3. *
  4. * Tessellates the famous Utah teapot database by Martin Newell into triangles.
  5. *
  6. * THREE.TeapotGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn )
  7. *
  8. * defaults: size = 50, segments = 10, bottom = true, lid = true, body = true,
  9. * fitLid = false, blinn = true
  10. *
  11. * size is a relative scale: I've scaled the teapot to fit vertically between -1 and 1.
  12. * Think of it as a "radius".
  13. * segments - number of line segments to subdivide each patch edge;
  14. * 1 is possible but gives degenerates, so two is the real minimum.
  15. * bottom - boolean, if true (default) then the bottom patches are added. Some consider
  16. * adding the bottom heresy, so set this to "false" to adhere to the One True Way.
  17. * lid - to remove the lid and look inside, set to true.
  18. * body - to remove the body and leave the lid, set this and "bottom" to false.
  19. * fitLid - the lid is a tad small in the original. This stretches it a bit so you can't
  20. * see the teapot's insides through the gap.
  21. * blinn - Jim Blinn scaled the original data vertically by dividing by about 1.3 to look
  22. * nicer. If you want to see the original teapot, similar to the real-world model, set
  23. * this to false. True by default.
  24. * See http://en.wikipedia.org/wiki/File:Original_Utah_Teapot.jpg for the original
  25. * real-world teapot (from http://en.wikipedia.org/wiki/Utah_teapot).
  26. *
  27. * Note that the bottom (the last four patches) is not flat - blame Frank Crow, not me.
  28. *
  29. * The teapot should normally be rendered as a double sided object, since for some
  30. * patches both sides can be seen, e.g., the gap around the lid and inside the spout.
  31. *
  32. * Segments 'n' determines the number of triangles output.
  33. * Total triangles = 32*2*n*n - 8*n [degenerates at the top and bottom cusps are deleted]
  34. *
  35. * size_factor # triangles
  36. * 1 56
  37. * 2 240
  38. * 3 552
  39. * 4 992
  40. *
  41. * 10 6320
  42. * 20 25440
  43. * 30 57360
  44. *
  45. * Code converted from my ancient SPD software, http://tog.acm.org/resources/SPD/
  46. * Created for the Udacity course "Interactive Rendering", http://bit.ly/ericity
  47. * Lesson: https://www.udacity.com/course/viewer#!/c-cs291/l-68866048/m-106482448
  48. * YouTube video on teapot history: https://www.youtube.com/watch?v=DxMfblPzFNc
  49. *
  50. * See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot
  51. *
  52. */
  53. /*global THREE */
  54. THREE.TeapotGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn ) {
  55. "use strict";
  56. // 32 * 4 * 4 Bezier spline patches
  57. var teapotPatches = [
  58. /*rim*/
  59. 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
  60. 3,16,17,18,7,19,20,21,11,22,23,24,15,25,26,27,
  61. 18,28,29,30,21,31,32,33,24,34,35,36,27,37,38,39,
  62. 30,40,41,0,33,42,43,4,36,44,45,8,39,46,47,12,
  63. /*body*/
  64. 12,13,14,15,48,49,50,51,52,53,54,55,56,57,58,59,
  65. 15,25,26,27,51,60,61,62,55,63,64,65,59,66,67,68,
  66. 27,37,38,39,62,69,70,71,65,72,73,74,68,75,76,77,
  67. 39,46,47,12,71,78,79,48,74,80,81,52,77,82,83,56,
  68. 56,57,58,59,84,85,86,87,88,89,90,91,92,93,94,95,
  69. 59,66,67,68,87,96,97,98,91,99,100,101,95,102,103,104,
  70. 68,75,76,77,98,105,106,107,101,108,109,110,104,111,112,113,
  71. 77,82,83,56,107,114,115,84,110,116,117,88,113,118,119,92,
  72. /*handle*/
  73. 120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,
  74. 123,136,137,120,127,138,139,124,131,140,141,128,135,142,143,132,
  75. 132,133,134,135,144,145,146,147,148,149,150,151,68,152,153,154,
  76. 135,142,143,132,147,155,156,144,151,157,158,148,154,159,160,68,
  77. /*spout*/
  78. 161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
  79. 164,177,178,161,168,179,180,165,172,181,182,169,176,183,184,173,
  80. 173,174,175,176,185,186,187,188,189,190,191,192,193,194,195,196,
  81. 176,183,184,173,188,197,198,185,192,199,200,189,196,201,202,193,
  82. /*lid*/
  83. 203,203,203,203,204,205,206,207,208,208,208,208,209,210,211,212,
  84. 203,203,203,203,207,213,214,215,208,208,208,208,212,216,217,218,
  85. 203,203,203,203,215,219,220,221,208,208,208,208,218,222,223,224,
  86. 203,203,203,203,221,225,226,204,208,208,208,208,224,227,228,209,
  87. 209,210,211,212,229,230,231,232,233,234,235,236,237,238,239,240,
  88. 212,216,217,218,232,241,242,243,236,244,245,246,240,247,248,249,
  89. 218,222,223,224,243,250,251,252,246,253,254,255,249,256,257,258,
  90. 224,227,228,209,252,259,260,229,255,261,262,233,258,263,264,237,
  91. /*bottom*/
  92. 265,265,265,265,266,267,268,269,270,271,272,273,92,119,118,113,
  93. 265,265,265,265,269,274,275,276,273,277,278,279,113,112,111,104,
  94. 265,265,265,265,276,280,281,282,279,283,284,285,104,103,102,95,
  95. 265,265,265,265,282,286,287,266,285,288,289,270,95,94,93,92
  96. ] ;
  97. var teapotVertices = [
  98. 1.4,0,2.4,
  99. 1.4,-0.784,2.4,
  100. 0.784,-1.4,2.4,
  101. 0,-1.4,2.4,
  102. 1.3375,0,2.53125,
  103. 1.3375,-0.749,2.53125,
  104. 0.749,-1.3375,2.53125,
  105. 0,-1.3375,2.53125,
  106. 1.4375,0,2.53125,
  107. 1.4375,-0.805,2.53125,
  108. 0.805,-1.4375,2.53125,
  109. 0,-1.4375,2.53125,
  110. 1.5,0,2.4,
  111. 1.5,-0.84,2.4,
  112. 0.84,-1.5,2.4,
  113. 0,-1.5,2.4,
  114. -0.784,-1.4,2.4,
  115. -1.4,-0.784,2.4,
  116. -1.4,0,2.4,
  117. -0.749,-1.3375,2.53125,
  118. -1.3375,-0.749,2.53125,
  119. -1.3375,0,2.53125,
  120. -0.805,-1.4375,2.53125,
  121. -1.4375,-0.805,2.53125,
  122. -1.4375,0,2.53125,
  123. -0.84,-1.5,2.4,
  124. -1.5,-0.84,2.4,
  125. -1.5,0,2.4,
  126. -1.4,0.784,2.4,
  127. -0.784,1.4,2.4,
  128. 0,1.4,2.4,
  129. -1.3375,0.749,2.53125,
  130. -0.749,1.3375,2.53125,
  131. 0,1.3375,2.53125,
  132. -1.4375,0.805,2.53125,
  133. -0.805,1.4375,2.53125,
  134. 0,1.4375,2.53125,
  135. -1.5,0.84,2.4,
  136. -0.84,1.5,2.4,
  137. 0,1.5,2.4,
  138. 0.784,1.4,2.4,
  139. 1.4,0.784,2.4,
  140. 0.749,1.3375,2.53125,
  141. 1.3375,0.749,2.53125,
  142. 0.805,1.4375,2.53125,
  143. 1.4375,0.805,2.53125,
  144. 0.84,1.5,2.4,
  145. 1.5,0.84,2.4,
  146. 1.75,0,1.875,
  147. 1.75,-0.98,1.875,
  148. 0.98,-1.75,1.875,
  149. 0,-1.75,1.875,
  150. 2,0,1.35,
  151. 2,-1.12,1.35,
  152. 1.12,-2,1.35,
  153. 0,-2,1.35,
  154. 2,0,0.9,
  155. 2,-1.12,0.9,
  156. 1.12,-2,0.9,
  157. 0,-2,0.9,
  158. -0.98,-1.75,1.875,
  159. -1.75,-0.98,1.875,
  160. -1.75,0,1.875,
  161. -1.12,-2,1.35,
  162. -2,-1.12,1.35,
  163. -2,0,1.35,
  164. -1.12,-2,0.9,
  165. -2,-1.12,0.9,
  166. -2,0,0.9,
  167. -1.75,0.98,1.875,
  168. -0.98,1.75,1.875,
  169. 0,1.75,1.875,
  170. -2,1.12,1.35,
  171. -1.12,2,1.35,
  172. 0,2,1.35,
  173. -2,1.12,0.9,
  174. -1.12,2,0.9,
  175. 0,2,0.9,
  176. 0.98,1.75,1.875,
  177. 1.75,0.98,1.875,
  178. 1.12,2,1.35,
  179. 2,1.12,1.35,
  180. 1.12,2,0.9,
  181. 2,1.12,0.9,
  182. 2,0,0.45,
  183. 2,-1.12,0.45,
  184. 1.12,-2,0.45,
  185. 0,-2,0.45,
  186. 1.5,0,0.225,
  187. 1.5,-0.84,0.225,
  188. 0.84,-1.5,0.225,
  189. 0,-1.5,0.225,
  190. 1.5,0,0.15,
  191. 1.5,-0.84,0.15,
  192. 0.84,-1.5,0.15,
  193. 0,-1.5,0.15,
  194. -1.12,-2,0.45,
  195. -2,-1.12,0.45,
  196. -2,0,0.45,
  197. -0.84,-1.5,0.225,
  198. -1.5,-0.84,0.225,
  199. -1.5,0,0.225,
  200. -0.84,-1.5,0.15,
  201. -1.5,-0.84,0.15,
  202. -1.5,0,0.15,
  203. -2,1.12,0.45,
  204. -1.12,2,0.45,
  205. 0,2,0.45,
  206. -1.5,0.84,0.225,
  207. -0.84,1.5,0.225,
  208. 0,1.5,0.225,
  209. -1.5,0.84,0.15,
  210. -0.84,1.5,0.15,
  211. 0,1.5,0.15,
  212. 1.12,2,0.45,
  213. 2,1.12,0.45,
  214. 0.84,1.5,0.225,
  215. 1.5,0.84,0.225,
  216. 0.84,1.5,0.15,
  217. 1.5,0.84,0.15,
  218. -1.6,0,2.025,
  219. -1.6,-0.3,2.025,
  220. -1.5,-0.3,2.25,
  221. -1.5,0,2.25,
  222. -2.3,0,2.025,
  223. -2.3,-0.3,2.025,
  224. -2.5,-0.3,2.25,
  225. -2.5,0,2.25,
  226. -2.7,0,2.025,
  227. -2.7,-0.3,2.025,
  228. -3,-0.3,2.25,
  229. -3,0,2.25,
  230. -2.7,0,1.8,
  231. -2.7,-0.3,1.8,
  232. -3,-0.3,1.8,
  233. -3,0,1.8,
  234. -1.5,0.3,2.25,
  235. -1.6,0.3,2.025,
  236. -2.5,0.3,2.25,
  237. -2.3,0.3,2.025,
  238. -3,0.3,2.25,
  239. -2.7,0.3,2.025,
  240. -3,0.3,1.8,
  241. -2.7,0.3,1.8,
  242. -2.7,0,1.575,
  243. -2.7,-0.3,1.575,
  244. -3,-0.3,1.35,
  245. -3,0,1.35,
  246. -2.5,0,1.125,
  247. -2.5,-0.3,1.125,
  248. -2.65,-0.3,0.9375,
  249. -2.65,0,0.9375,
  250. -2,-0.3,0.9,
  251. -1.9,-0.3,0.6,
  252. -1.9,0,0.6,
  253. -3,0.3,1.35,
  254. -2.7,0.3,1.575,
  255. -2.65,0.3,0.9375,
  256. -2.5,0.3,1.125,
  257. -1.9,0.3,0.6,
  258. -2,0.3,0.9,
  259. 1.7,0,1.425,
  260. 1.7,-0.66,1.425,
  261. 1.7,-0.66,0.6,
  262. 1.7,0,0.6,
  263. 2.6,0,1.425,
  264. 2.6,-0.66,1.425,
  265. 3.1,-0.66,0.825,
  266. 3.1,0,0.825,
  267. 2.3,0,2.1,
  268. 2.3,-0.25,2.1,
  269. 2.4,-0.25,2.025,
  270. 2.4,0,2.025,
  271. 2.7,0,2.4,
  272. 2.7,-0.25,2.4,
  273. 3.3,-0.25,2.4,
  274. 3.3,0,2.4,
  275. 1.7,0.66,0.6,
  276. 1.7,0.66,1.425,
  277. 3.1,0.66,0.825,
  278. 2.6,0.66,1.425,
  279. 2.4,0.25,2.025,
  280. 2.3,0.25,2.1,
  281. 3.3,0.25,2.4,
  282. 2.7,0.25,2.4,
  283. 2.8,0,2.475,
  284. 2.8,-0.25,2.475,
  285. 3.525,-0.25,2.49375,
  286. 3.525,0,2.49375,
  287. 2.9,0,2.475,
  288. 2.9,-0.15,2.475,
  289. 3.45,-0.15,2.5125,
  290. 3.45,0,2.5125,
  291. 2.8,0,2.4,
  292. 2.8,-0.15,2.4,
  293. 3.2,-0.15,2.4,
  294. 3.2,0,2.4,
  295. 3.525,0.25,2.49375,
  296. 2.8,0.25,2.475,
  297. 3.45,0.15,2.5125,
  298. 2.9,0.15,2.475,
  299. 3.2,0.15,2.4,
  300. 2.8,0.15,2.4,
  301. 0,0,3.15,
  302. 0.8,0,3.15,
  303. 0.8,-0.45,3.15,
  304. 0.45,-0.8,3.15,
  305. 0,-0.8,3.15,
  306. 0,0,2.85,
  307. 0.2,0,2.7,
  308. 0.2,-0.112,2.7,
  309. 0.112,-0.2,2.7,
  310. 0,-0.2,2.7,
  311. -0.45,-0.8,3.15,
  312. -0.8,-0.45,3.15,
  313. -0.8,0,3.15,
  314. -0.112,-0.2,2.7,
  315. -0.2,-0.112,2.7,
  316. -0.2,0,2.7,
  317. -0.8,0.45,3.15,
  318. -0.45,0.8,3.15,
  319. 0,0.8,3.15,
  320. -0.2,0.112,2.7,
  321. -0.112,0.2,2.7,
  322. 0,0.2,2.7,
  323. 0.45,0.8,3.15,
  324. 0.8,0.45,3.15,
  325. 0.112,0.2,2.7,
  326. 0.2,0.112,2.7,
  327. 0.4,0,2.55,
  328. 0.4,-0.224,2.55,
  329. 0.224,-0.4,2.55,
  330. 0,-0.4,2.55,
  331. 1.3,0,2.55,
  332. 1.3,-0.728,2.55,
  333. 0.728,-1.3,2.55,
  334. 0,-1.3,2.55,
  335. 1.3,0,2.4,
  336. 1.3,-0.728,2.4,
  337. 0.728,-1.3,2.4,
  338. 0,-1.3,2.4,
  339. -0.224,-0.4,2.55,
  340. -0.4,-0.224,2.55,
  341. -0.4,0,2.55,
  342. -0.728,-1.3,2.55,
  343. -1.3,-0.728,2.55,
  344. -1.3,0,2.55,
  345. -0.728,-1.3,2.4,
  346. -1.3,-0.728,2.4,
  347. -1.3,0,2.4,
  348. -0.4,0.224,2.55,
  349. -0.224,0.4,2.55,
  350. 0,0.4,2.55,
  351. -1.3,0.728,2.55,
  352. -0.728,1.3,2.55,
  353. 0,1.3,2.55,
  354. -1.3,0.728,2.4,
  355. -0.728,1.3,2.4,
  356. 0,1.3,2.4,
  357. 0.224,0.4,2.55,
  358. 0.4,0.224,2.55,
  359. 0.728,1.3,2.55,
  360. 1.3,0.728,2.55,
  361. 0.728,1.3,2.4,
  362. 1.3,0.728,2.4,
  363. 0,0,0,
  364. 1.425,0,0,
  365. 1.425,0.798,0,
  366. 0.798,1.425,0,
  367. 0,1.425,0,
  368. 1.5,0,0.075,
  369. 1.5,0.84,0.075,
  370. 0.84,1.5,0.075,
  371. 0,1.5,0.075,
  372. -0.798,1.425,0,
  373. -1.425,0.798,0,
  374. -1.425,0,0,
  375. -0.84,1.5,0.075,
  376. -1.5,0.84,0.075,
  377. -1.5,0,0.075,
  378. -1.425,-0.798,0,
  379. -0.798,-1.425,0,
  380. 0,-1.425,0,
  381. -1.5,-0.84,0.075,
  382. -0.84,-1.5,0.075,
  383. 0,-1.5,0.075,
  384. 0.798,-1.425,0,
  385. 1.425,-0.798,0,
  386. 0.84,-1.5,0.075,
  387. 1.5,-0.84,0.075
  388. ] ;
  389. THREE.Geometry.call( this );
  390. this.type = 'TeapotGeometry';
  391. this.size = size || 50;
  392. // number of segments per patch
  393. this.segments = Math.max( 2, Math.floor( segments ) || 10 );
  394. // which parts should be visible
  395. this.bottom = bottom === undefined ? true : bottom;
  396. this.lid = lid === undefined ? true : lid;
  397. this.body = body === undefined ? true : body;
  398. // Should the lid be snug? It's not traditional, so off by default
  399. this.fitLid = fitLid === undefined ? false : fitLid;
  400. // Jim Blinn scaled the teapot down in size by about 1.3 for
  401. // some rendering tests. He liked the new proportions that he kept
  402. // the data in this form. The model was distributed with these new
  403. // proportions and became the norm. Trivia: comparing images of the
  404. // real teapot and the computer model, the ratio for the bowl of the
  405. // real teapot is more like 1.25, but since 1.3 is the traditional
  406. // value given, we use it here.
  407. var blinnScale = 1.3;
  408. this.blinn = blinn === undefined ? true : blinn;
  409. // scale the size to be the real scaling factor
  410. var maxHeight = 3.15 * (this.blinn ? 1 : blinnScale);
  411. var maxHeight2 = maxHeight / 2;
  412. var trueSize = this.size / maxHeight2;
  413. var normals = [], uvs = [];
  414. // Bezier form
  415. var ms = new THREE.Matrix4();
  416. ms.set( -1.0, 3.0, -3.0, 1.0,
  417. 3.0, -6.0, 3.0, 0.0,
  418. -3.0, 3.0, 0.0, 0.0,
  419. 1.0, 0.0, 0.0, 0.0 ) ;
  420. var g = [];
  421. var i, r, c;
  422. var sp = [];
  423. var tp = [];
  424. var dsp = [];
  425. var dtp = [];
  426. // M * G * M matrix, sort of see
  427. // http://www.cs.helsinki.fi/group/goa/mallinnus/curves/surfaces.html
  428. var mgm = [];
  429. var vert = [];
  430. var sdir = [];
  431. var tdir = [];
  432. var norm = new THREE.Vector3();
  433. var tcoord;
  434. var sstep, tstep;
  435. var gmx, tmtx;
  436. var vertPerRow, eps;
  437. var s, t, sval, tval, p, dsval, dtval;
  438. var vsp, vtp, vdsp, vdtp;
  439. var vsdir, vtdir, normOut, vertOut;
  440. var v1, v2, v3, v4;
  441. var mst = ms.clone();
  442. mst.transpose();
  443. // internal function: test if triangle has any matching vertices;
  444. // if so, don't save triangle, since it won't display anything.
  445. var notDegenerate = function ( vtx1, vtx2, vtx3 ) {
  446. if ( vtx1.equals( vtx2 ) ) { return false; }
  447. if ( vtx1.equals( vtx3 ) ) { return false; }
  448. if ( vtx2.equals( vtx3 ) ) { return false; }
  449. return true;
  450. };
  451. for ( i = 0; i < 3; i++ )
  452. {
  453. mgm[i] = new THREE.Matrix4();
  454. }
  455. var minPatches = this.body ? 0 : 20;
  456. var maxPatches = this.bottom ? 32 : 28;
  457. vertPerRow = (this.segments+1);
  458. eps = 0.0000001;
  459. var surfCount = 0;
  460. for ( var surf = minPatches ; surf < maxPatches ; surf++ ) {
  461. // lid is in the middle of the data, patches 20-27,
  462. // so ignore it for this part of the loop if the lid is not desired
  463. if ( this.lid || (surf < 20 || surf >= 28) ) {
  464. // get M * G * M matrix for x,y,z
  465. for ( i = 0 ; i < 3 ; i++ ) {
  466. // get control patches
  467. for ( r = 0 ; r < 4 ; r++ ) {
  468. for ( c = 0 ; c < 4 ; c++ ) {
  469. // transposed
  470. g[c*4+r] = teapotVertices[teapotPatches[surf*16 + r*4 + c]*3 + i] ;
  471. // is the lid to be made larger, and is this a point on the lid
  472. // that is X or Y?
  473. if ( this.fitLid && (surf >= 20 && surf < 28) && (i !== 2) ) {
  474. // increase XY size by 7.7%, found empirically. I don't
  475. // increase Z so that the teapot will continue to fit in the
  476. // space -1 to 1 for Y (Y is up for the final model).
  477. g[c*4+r] *= 1.077;
  478. }
  479. // Blinn "fixed" the teapot by dividing Z by blinnScale, and that's the
  480. // data we now use. The original teapot is taller. Fix it:
  481. if ( !this.blinn && (i === 2) ) {
  482. g[c*4+r] *= blinnScale;
  483. }
  484. }
  485. }
  486. gmx = new THREE.Matrix4();
  487. gmx.set( g[0], g[1], g[2], g[3], g[4], g[5], g[6], g[7], g[8], g[9], g[10], g[11], g[12], g[13], g[14], g[15] );
  488. tmtx = new THREE.Matrix4();
  489. tmtx.multiplyMatrices( gmx, ms );
  490. mgm[i].multiplyMatrices( mst, tmtx );
  491. }
  492. // step along, get points, and output
  493. for ( sstep = 0 ; sstep <= this.segments ; sstep++ ) {
  494. s = sstep / this.segments;
  495. for ( tstep = 0 ; tstep <= this.segments ; tstep++ ) {
  496. t = tstep / this.segments;
  497. // point from basis
  498. // get power vectors and their derivatives
  499. for ( p = 4, sval = tval = 1.0 ; p-- ; ) {
  500. sp[p] = sval ;
  501. tp[p] = tval ;
  502. sval *= s ;
  503. tval *= t ;
  504. if ( p === 3 ) {
  505. dsp[p] = dtp[p] = 0.0 ;
  506. dsval = dtval = 1.0 ;
  507. } else {
  508. dsp[p] = dsval * (3-p) ;
  509. dtp[p] = dtval * (3-p) ;
  510. dsval *= s ;
  511. dtval *= t ;
  512. }
  513. }
  514. vsp = new THREE.Vector4( sp[0], sp[1], sp[2], sp[3] );
  515. vtp = new THREE.Vector4( tp[0], tp[1], tp[2], tp[3] );
  516. vdsp = new THREE.Vector4( dsp[0], dsp[1], dsp[2], dsp[3] );
  517. vdtp = new THREE.Vector4( dtp[0], dtp[1], dtp[2], dtp[3] );
  518. // do for x,y,z
  519. for ( i = 0 ; i < 3 ; i++ ) {
  520. // multiply power vectors times matrix to get value
  521. tcoord = vsp.clone();
  522. tcoord.applyMatrix4( mgm[i] );
  523. vert[i] = tcoord.dot( vtp );
  524. // get s and t tangent vectors
  525. tcoord = vdsp.clone();
  526. tcoord.applyMatrix4( mgm[i] );
  527. sdir[i] = tcoord.dot( vtp ) ;
  528. tcoord = vsp.clone();
  529. tcoord.applyMatrix4( mgm[i] );
  530. tdir[i] = tcoord.dot( vdtp ) ;
  531. }
  532. // find normal
  533. vsdir = new THREE.Vector3( sdir[0], sdir[1], sdir[2] );
  534. vtdir = new THREE.Vector3( tdir[0], tdir[1], tdir[2] );
  535. norm.crossVectors( vtdir, vsdir );
  536. norm.normalize();
  537. // rotate on X axis
  538. normOut = new THREE.Vector3( norm.x, norm.z, -norm.y );
  539. // if X and Z length is 0, at the cusp, so point the normal up or down, depending on patch number
  540. if ( vert[0] === 0 && vert[1] === 0 )
  541. {
  542. // if above the middle of the teapot, normal points up, else down
  543. normOut.set( 0, vert[2] > maxHeight2 ? 1 : -1, 0 );
  544. }
  545. normals.push( normOut );
  546. uvs.push( new THREE.Vector2( 1-t, 1-s ) );
  547. // three.js uses Y up, the code makes Z up, so time for a trick:
  548. // rotate on X axis, and offset down on Y axis so object ranges from -1 to 1 in Y
  549. vertOut = new THREE.Vector3( trueSize*vert[0], trueSize*(vert[2] - maxHeight2), -trueSize*vert[1] );
  550. this.vertices.push( vertOut );
  551. }
  552. }
  553. // save the faces
  554. for ( sstep = 0 ; sstep < this.segments ; sstep++ ) {
  555. for ( tstep = 0 ; tstep < this.segments ; tstep++ ) {
  556. v1 = surfCount * vertPerRow * vertPerRow + sstep * vertPerRow + tstep;
  557. v2 = v1 + 1;
  558. v3 = v2 + vertPerRow;
  559. v4 = v1 + vertPerRow;
  560. if ( notDegenerate ( this.vertices[v1], this.vertices[v2], this.vertices[v3] ) ) {
  561. this.faces.push( new THREE.Face3( v1, v2, v3, [ normals[v1], normals[v2], normals[v3] ] ) );
  562. this.faceVertexUvs[ 0 ].push( [ uvs[v1], uvs[v2], uvs[v3] ] );
  563. }
  564. if ( notDegenerate ( this.vertices[v1], this.vertices[v3], this.vertices[v4] ) ) {
  565. this.faces.push( new THREE.Face3( v1, v3, v4, [ normals[v1], normals[v3], normals[v4] ] ) );
  566. this.faceVertexUvs[ 0 ].push( [ uvs[v1], uvs[v3], uvs[v4] ] );
  567. }
  568. }
  569. }
  570. // increment only if a surface was used
  571. surfCount++;
  572. }
  573. }
  574. this.computeFaceNormals();
  575. };
  576. THREE.TeapotGeometry.prototype = Object.create( THREE.Geometry.prototype );
  577. THREE.TeapotGeometry.prototype.constructor = THREE.TeapotGeometry;