Surface_Patch.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../precompiled.h"
  21. #pragma hdrstop
  22. /*
  23. =================
  24. idSurface_Patch::SetSize
  25. =================
  26. */
  27. void idSurface_Patch::SetSize( int patchWidth, int patchHeight ) {
  28. if ( patchWidth < 1 || patchWidth > maxWidth ) {
  29. idLib::common->FatalError("idSurface_Patch::SetSize: invalid patchWidth");
  30. }
  31. if ( patchHeight < 1 || patchHeight > maxHeight ) {
  32. idLib::common->FatalError("idSurface_Patch::SetSize: invalid patchHeight");
  33. }
  34. width = patchWidth;
  35. height = patchHeight;
  36. verts.SetNum( width * height, false );
  37. }
  38. /*
  39. =================
  40. idSurface_Patch::PutOnCurve
  41. Expects an expanded patch.
  42. =================
  43. */
  44. void idSurface_Patch::PutOnCurve( void ) {
  45. int i, j;
  46. idDrawVert prev, next;
  47. assert( expanded == true );
  48. // put all the approximating points on the curve
  49. for ( i = 0; i < width; i++ ) {
  50. for ( j = 1; j < height; j += 2 ) {
  51. LerpVert( verts[j*maxWidth+i], verts[(j+1)*maxWidth+i], prev );
  52. LerpVert( verts[j*maxWidth+i], verts[(j-1)*maxWidth+i], next );
  53. LerpVert( prev, next, verts[j*maxWidth+i] );
  54. }
  55. }
  56. for ( j = 0; j < height; j++ ) {
  57. for ( i = 1; i < width; i += 2 ) {
  58. LerpVert( verts[j*maxWidth+i], verts[j*maxWidth+i+1], prev );
  59. LerpVert( verts[j*maxWidth+i], verts[j*maxWidth+i-1], next );
  60. LerpVert( prev, next, verts[j*maxWidth+i] );
  61. }
  62. }
  63. }
  64. /*
  65. ================
  66. idSurface_Patch::ProjectPointOntoVector
  67. ================
  68. */
  69. void idSurface_Patch::ProjectPointOntoVector( const idVec3 &point, const idVec3 &vStart, const idVec3 &vEnd, idVec3 &vProj ) {
  70. idVec3 pVec, vec;
  71. pVec = point - vStart;
  72. vec = vEnd - vStart;
  73. vec.Normalize();
  74. // project onto the directional vector for this segment
  75. vProj = vStart + (pVec * vec) * vec;
  76. }
  77. /*
  78. ================
  79. idSurface_Patch::RemoveLinearColumnsRows
  80. Expects an expanded patch.
  81. ================
  82. */
  83. void idSurface_Patch::RemoveLinearColumnsRows( void ) {
  84. int i, j, k;
  85. float len, maxLength;
  86. idVec3 proj, dir;
  87. assert( expanded == true );
  88. for ( j = 1; j < width - 1; j++ ) {
  89. maxLength = 0;
  90. for ( i = 0; i < height; i++ ) {
  91. idSurface_Patch::ProjectPointOntoVector( verts[i*maxWidth + j].xyz,
  92. verts[i*maxWidth + j-1].xyz, verts[i*maxWidth + j+1].xyz, proj);
  93. dir = verts[i*maxWidth + j].xyz - proj;
  94. len = dir.LengthSqr();
  95. if ( len > maxLength ) {
  96. maxLength = len;
  97. }
  98. }
  99. if ( maxLength < Square( 0.2f ) ) {
  100. width--;
  101. for ( i = 0; i < height; i++ ) {
  102. for ( k = j; k < width; k++ ) {
  103. verts[i*maxWidth + k] = verts[i*maxWidth + k+1];
  104. }
  105. }
  106. j--;
  107. }
  108. }
  109. for ( j = 1; j < height - 1; j++ ) {
  110. maxLength = 0;
  111. for ( i = 0; i < width; i++ ) {
  112. idSurface_Patch::ProjectPointOntoVector( verts[j*maxWidth + i].xyz,
  113. verts[(j-1)*maxWidth + i].xyz, verts[(j+1)*maxWidth + i].xyz, proj);
  114. dir = verts[j*maxWidth + i].xyz - proj;
  115. len = dir.LengthSqr();
  116. if ( len > maxLength ) {
  117. maxLength = len;
  118. }
  119. }
  120. if ( maxLength < Square( 0.2f ) ) {
  121. height--;
  122. for ( i = 0; i < width; i++ ) {
  123. for ( k = j; k < height; k++ ) {
  124. verts[k*maxWidth + i] = verts[(k+1)*maxWidth + i];
  125. }
  126. }
  127. j--;
  128. }
  129. }
  130. }
  131. /*
  132. ================
  133. idSurface_Patch::ResizeExpanded
  134. ================
  135. */
  136. void idSurface_Patch::ResizeExpanded( int newHeight, int newWidth ) {
  137. int i, j;
  138. assert( expanded == true );
  139. if ( newHeight <= maxHeight && newWidth <= maxWidth ) {
  140. return;
  141. }
  142. if ( newHeight * newWidth > maxHeight * maxWidth ) {
  143. verts.SetNum( newHeight * newWidth );
  144. }
  145. // space out verts for new height and width
  146. for ( j = maxHeight-1; j >= 0; j-- ) {
  147. for ( i = maxWidth-1; i >= 0; i-- ) {
  148. verts[j*newWidth + i] = verts[j*maxWidth + i];
  149. }
  150. }
  151. maxHeight = newHeight;
  152. maxWidth = newWidth;
  153. }
  154. /*
  155. ================
  156. idSurface_Patch::Collapse
  157. ================
  158. */
  159. void idSurface_Patch::Collapse( void ) {
  160. int i, j;
  161. if ( !expanded ) {
  162. idLib::common->FatalError("idSurface_Patch::Collapse: patch not expanded");
  163. }
  164. expanded = false;
  165. if ( width != maxWidth ) {
  166. for ( j = 0; j < height; j++ ) {
  167. for ( i = 0; i < width; i++ ) {
  168. verts[j*width + i] = verts[j*maxWidth + i];
  169. }
  170. }
  171. }
  172. verts.SetNum( width * height, false );
  173. }
  174. /*
  175. ================
  176. idSurface_Patch::Expand
  177. ================
  178. */
  179. void idSurface_Patch::Expand( void ) {
  180. int i, j;
  181. if ( expanded ) {
  182. idLib::common->FatalError("idSurface_Patch::Expand: patch alread expanded");
  183. }
  184. expanded = true;
  185. verts.SetNum( maxWidth * maxHeight, false );
  186. if ( width != maxWidth ) {
  187. for ( j = height-1; j >= 0; j-- ) {
  188. for ( i = width-1; i >= 0; i-- ) {
  189. verts[j*maxWidth + i] = verts[j*width + i];
  190. }
  191. }
  192. }
  193. }
  194. /*
  195. ============
  196. idSurface_Patch::LerpVert
  197. ============
  198. */
  199. void idSurface_Patch::LerpVert( const idDrawVert &a, const idDrawVert &b, idDrawVert &out ) const {
  200. out.xyz[0] = 0.5f * ( a.xyz[0] + b.xyz[0] );
  201. out.xyz[1] = 0.5f * ( a.xyz[1] + b.xyz[1] );
  202. out.xyz[2] = 0.5f * ( a.xyz[2] + b.xyz[2] );
  203. out.normal[0] = 0.5f * ( a.normal[0] + b.normal[0] );
  204. out.normal[1] = 0.5f * ( a.normal[1] + b.normal[1] );
  205. out.normal[2] = 0.5f * ( a.normal[2] + b.normal[2] );
  206. out.st[0] = 0.5f * ( a.st[0] + b.st[0] );
  207. out.st[1] = 0.5f * ( a.st[1] + b.st[1] );
  208. }
  209. /*
  210. =================
  211. idSurface_Patch::GenerateNormals
  212. Handles all the complicated wrapping and degenerate cases
  213. Expects a Not expanded patch.
  214. =================
  215. */
  216. #define COPLANAR_EPSILON 0.1f
  217. void idSurface_Patch::GenerateNormals( void ) {
  218. int i, j, k, dist;
  219. idVec3 norm;
  220. idVec3 sum;
  221. int count;
  222. idVec3 base;
  223. idVec3 delta;
  224. int x, y;
  225. idVec3 around[8], temp;
  226. bool good[8];
  227. bool wrapWidth, wrapHeight;
  228. static int neighbors[8][2] = {
  229. {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
  230. };
  231. assert( expanded == false );
  232. //
  233. // if all points are coplanar, set all normals to that plane
  234. //
  235. idVec3 extent[3];
  236. float offset;
  237. extent[0] = verts[width - 1].xyz - verts[0].xyz;
  238. extent[1] = verts[(height-1) * width + width - 1].xyz - verts[0].xyz;
  239. extent[2] = verts[(height-1) * width].xyz - verts[0].xyz;
  240. norm = extent[0].Cross( extent[1] );
  241. if ( norm.LengthSqr() == 0.0f ) {
  242. norm = extent[0].Cross( extent[2] );
  243. if ( norm.LengthSqr() == 0.0f ) {
  244. norm = extent[1].Cross( extent[2] );
  245. }
  246. }
  247. // wrapped patched may not get a valid normal here
  248. if ( norm.Normalize() != 0.0f ) {
  249. offset = verts[0].xyz * norm;
  250. for ( i = 1; i < width * height; i++ ) {
  251. float d = verts[i].xyz * norm;
  252. if ( idMath::Fabs( d - offset ) > COPLANAR_EPSILON ) {
  253. break;
  254. }
  255. }
  256. if ( i == width * height ) {
  257. // all are coplanar
  258. for ( i = 0; i < width * height; i++ ) {
  259. verts[i].normal = norm;
  260. }
  261. return;
  262. }
  263. }
  264. // check for wrapped edge cases, which should smooth across themselves
  265. wrapWidth = false;
  266. for ( i = 0; i < height; i++ ) {
  267. delta = verts[i * width].xyz - verts[i * width + width-1].xyz;
  268. if ( delta.LengthSqr() > Square( 1.0f ) ) {
  269. break;
  270. }
  271. }
  272. if ( i == height ) {
  273. wrapWidth = true;
  274. }
  275. wrapHeight = false;
  276. for ( i = 0; i < width; i++ ) {
  277. delta = verts[i].xyz - verts[(height-1) * width + i].xyz;
  278. if ( delta.LengthSqr() > Square( 1.0f ) ) {
  279. break;
  280. }
  281. }
  282. if ( i == width ) {
  283. wrapHeight = true;
  284. }
  285. for ( i = 0; i < width; i++ ) {
  286. for ( j = 0; j < height; j++ ) {
  287. count = 0;
  288. base = verts[j * width + i].xyz;
  289. for ( k = 0; k < 8; k++ ) {
  290. around[k] = vec3_origin;
  291. good[k] = false;
  292. for ( dist = 1; dist <= 3; dist++ ) {
  293. x = i + neighbors[k][0] * dist;
  294. y = j + neighbors[k][1] * dist;
  295. if ( wrapWidth ) {
  296. if ( x < 0 ) {
  297. x = width - 1 + x;
  298. } else if ( x >= width ) {
  299. x = 1 + x - width;
  300. }
  301. }
  302. if ( wrapHeight ) {
  303. if ( y < 0 ) {
  304. y = height - 1 + y;
  305. } else if ( y >= height ) {
  306. y = 1 + y - height;
  307. }
  308. }
  309. if ( x < 0 || x >= width || y < 0 || y >= height ) {
  310. break; // edge of patch
  311. }
  312. temp = verts[y * width + x].xyz - base;
  313. if ( temp.Normalize() == 0.0f ) {
  314. continue; // degenerate edge, get more dist
  315. } else {
  316. good[k] = true;
  317. around[k] = temp;
  318. break; // good edge
  319. }
  320. }
  321. }
  322. sum = vec3_origin;
  323. for ( k = 0; k < 8; k++ ) {
  324. if ( !good[k] || !good[(k+1)&7] ) {
  325. continue; // didn't get two points
  326. }
  327. norm = around[(k+1)&7].Cross( around[k] );
  328. if ( norm.Normalize() == 0.0f ) {
  329. continue;
  330. }
  331. sum += norm;
  332. count++;
  333. }
  334. if ( count == 0 ) {
  335. //idLib::common->Printf("bad normal\n");
  336. count = 1;
  337. }
  338. verts[j * width + i].normal = sum;
  339. verts[j * width + i].normal.Normalize();
  340. }
  341. }
  342. }
  343. /*
  344. =================
  345. idSurface_Patch::GenerateIndexes
  346. =================
  347. */
  348. void idSurface_Patch::GenerateIndexes( void ) {
  349. int i, j, v1, v2, v3, v4, index;
  350. indexes.SetNum( (width-1) * (height-1) * 2 * 3, false );
  351. index = 0;
  352. for ( i = 0; i < width - 1; i++ ) {
  353. for ( j = 0; j < height - 1; j++ ) {
  354. v1 = j * width + i;
  355. v2 = v1 + 1;
  356. v3 = v1 + width + 1;
  357. v4 = v1 + width;
  358. indexes[index++] = v1;
  359. indexes[index++] = v3;
  360. indexes[index++] = v2;
  361. indexes[index++] = v1;
  362. indexes[index++] = v4;
  363. indexes[index++] = v3;
  364. }
  365. }
  366. GenerateEdgeIndexes();
  367. }
  368. /*
  369. ===============
  370. idSurface_Patch::SampleSinglePatchPoint
  371. ===============
  372. */
  373. void idSurface_Patch::SampleSinglePatchPoint( const idDrawVert ctrl[3][3], float u, float v, idDrawVert *out ) const {
  374. float vCtrl[3][8];
  375. int vPoint;
  376. int axis;
  377. // find the control points for the v coordinate
  378. for ( vPoint = 0; vPoint < 3; vPoint++ ) {
  379. for ( axis = 0; axis < 8; axis++ ) {
  380. float a, b, c;
  381. float qA, qB, qC;
  382. if ( axis < 3 ) {
  383. a = ctrl[0][vPoint].xyz[axis];
  384. b = ctrl[1][vPoint].xyz[axis];
  385. c = ctrl[2][vPoint].xyz[axis];
  386. } else if ( axis < 6 ) {
  387. a = ctrl[0][vPoint].normal[axis-3];
  388. b = ctrl[1][vPoint].normal[axis-3];
  389. c = ctrl[2][vPoint].normal[axis-3];
  390. } else {
  391. a = ctrl[0][vPoint].st[axis-6];
  392. b = ctrl[1][vPoint].st[axis-6];
  393. c = ctrl[2][vPoint].st[axis-6];
  394. }
  395. qA = a - 2.0f * b + c;
  396. qB = 2.0f * b - 2.0f * a;
  397. qC = a;
  398. vCtrl[vPoint][axis] = qA * u * u + qB * u + qC;
  399. }
  400. }
  401. // interpolate the v value
  402. for ( axis = 0; axis < 8; axis++ ) {
  403. float a, b, c;
  404. float qA, qB, qC;
  405. a = vCtrl[0][axis];
  406. b = vCtrl[1][axis];
  407. c = vCtrl[2][axis];
  408. qA = a - 2.0f * b + c;
  409. qB = 2.0f * b - 2.0f * a;
  410. qC = a;
  411. if ( axis < 3 ) {
  412. out->xyz[axis] = qA * v * v + qB * v + qC;
  413. } else if ( axis < 6 ) {
  414. out->normal[axis-3] = qA * v * v + qB * v + qC;
  415. } else {
  416. out->st[axis-6] = qA * v * v + qB * v + qC;
  417. }
  418. }
  419. }
  420. /*
  421. ===================
  422. idSurface_Patch::SampleSinglePatch
  423. ===================
  424. */
  425. void idSurface_Patch::SampleSinglePatch( const idDrawVert ctrl[3][3], int baseCol, int baseRow, int width, int horzSub, int vertSub, idDrawVert *outVerts ) const {
  426. int i, j;
  427. float u, v;
  428. horzSub++;
  429. vertSub++;
  430. for ( i = 0; i < horzSub; i++ ) {
  431. for ( j = 0; j < vertSub; j++ ) {
  432. u = (float) i / ( horzSub - 1 );
  433. v = (float) j / ( vertSub - 1 );
  434. SampleSinglePatchPoint( ctrl, u, v, &outVerts[((baseRow + j) * width) + i + baseCol] );
  435. }
  436. }
  437. }
  438. /*
  439. =================
  440. idSurface_Patch::SubdivideExplicit
  441. =================
  442. */
  443. void idSurface_Patch::SubdivideExplicit( int horzSubdivisions, int vertSubdivisions, bool genNormals, bool removeLinear ) {
  444. int i, j, k, l;
  445. idDrawVert sample[3][3];
  446. int outWidth = ((width - 1) / 2 * horzSubdivisions) + 1;
  447. int outHeight = ((height - 1) / 2 * vertSubdivisions) + 1;
  448. idDrawVert *dv = new idDrawVert[ outWidth * outHeight ];
  449. // generate normals for the control mesh
  450. if ( genNormals ) {
  451. GenerateNormals();
  452. }
  453. int baseCol = 0;
  454. for ( i = 0; i + 2 < width; i += 2 ) {
  455. int baseRow = 0;
  456. for ( j = 0; j + 2 < height; j += 2 ) {
  457. for ( k = 0; k < 3; k++ ) {
  458. for ( l = 0; l < 3; l++ ) {
  459. sample[k][l] = verts[ ((j + l) * width) + i + k ];
  460. }
  461. }
  462. SampleSinglePatch( sample, baseCol, baseRow, outWidth, horzSubdivisions, vertSubdivisions, dv );
  463. baseRow += vertSubdivisions;
  464. }
  465. baseCol += horzSubdivisions;
  466. }
  467. verts.SetNum( outWidth * outHeight );
  468. for ( i = 0; i < outWidth * outHeight; i++ ) {
  469. verts[i] = dv[i];
  470. }
  471. delete[] dv;
  472. width = maxWidth = outWidth;
  473. height = maxHeight = outHeight;
  474. expanded = false;
  475. if ( removeLinear ) {
  476. Expand();
  477. RemoveLinearColumnsRows();
  478. Collapse();
  479. }
  480. // normalize all the lerped normals
  481. if ( genNormals ) {
  482. for ( i = 0; i < width * height; i++ ) {
  483. verts[i].normal.Normalize();
  484. }
  485. }
  486. GenerateIndexes();
  487. }
  488. /*
  489. =================
  490. idSurface_Patch::Subdivide
  491. =================
  492. */
  493. void idSurface_Patch::Subdivide( float maxHorizontalError, float maxVerticalError, float maxLength, bool genNormals ) {
  494. int i, j, k, l;
  495. idDrawVert prev, next, mid;
  496. idVec3 prevxyz, nextxyz, midxyz;
  497. idVec3 delta;
  498. float maxHorizontalErrorSqr, maxVerticalErrorSqr, maxLengthSqr;
  499. // generate normals for the control mesh
  500. if ( genNormals ) {
  501. GenerateNormals();
  502. }
  503. maxHorizontalErrorSqr = Square( maxHorizontalError );
  504. maxVerticalErrorSqr = Square( maxVerticalError );
  505. maxLengthSqr = Square( maxLength );
  506. Expand();
  507. // horizontal subdivisions
  508. for ( j = 0; j + 2 < width; j += 2 ) {
  509. // check subdivided midpoints against control points
  510. for ( i = 0; i < height; i++ ) {
  511. for ( l = 0; l < 3; l++ ) {
  512. prevxyz[l] = verts[i*maxWidth + j+1].xyz[l] - verts[i*maxWidth + j ].xyz[l];
  513. nextxyz[l] = verts[i*maxWidth + j+2].xyz[l] - verts[i*maxWidth + j+1].xyz[l];
  514. midxyz[l] = (verts[i*maxWidth + j ].xyz[l] + verts[i*maxWidth + j+1].xyz[l] * 2.0f +
  515. verts[i*maxWidth + j+2].xyz[l] ) * 0.25f;
  516. }
  517. if ( maxLength > 0.0f ) {
  518. // if the span length is too long, force a subdivision
  519. if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
  520. break;
  521. }
  522. }
  523. // see if this midpoint is off far enough to subdivide
  524. delta = verts[i*maxWidth + j+1].xyz - midxyz;
  525. if ( delta.LengthSqr() > maxHorizontalErrorSqr ) {
  526. break;
  527. }
  528. }
  529. if ( i == height ) {
  530. continue; // didn't need subdivision
  531. }
  532. if ( width + 2 >= maxWidth ) {
  533. ResizeExpanded( maxHeight, maxWidth + 4 );
  534. }
  535. // insert two columns and replace the peak
  536. width += 2;
  537. for ( i = 0; i < height; i++ ) {
  538. idSurface_Patch::LerpVert( verts[i*maxWidth + j ], verts[i*maxWidth + j+1], prev );
  539. idSurface_Patch::LerpVert( verts[i*maxWidth + j+1], verts[i*maxWidth + j+2], next );
  540. idSurface_Patch::LerpVert( prev, next, mid );
  541. for ( k = width - 1; k > j + 3; k-- ) {
  542. verts[i*maxWidth + k] = verts[i*maxWidth + k-2];
  543. }
  544. verts[i*maxWidth + j+1] = prev;
  545. verts[i*maxWidth + j+2] = mid;
  546. verts[i*maxWidth + j+3] = next;
  547. }
  548. // back up and recheck this set again, it may need more subdivision
  549. j -= 2;
  550. }
  551. // vertical subdivisions
  552. for ( j = 0; j + 2 < height; j += 2 ) {
  553. // check subdivided midpoints against control points
  554. for ( i = 0; i < width; i++ ) {
  555. for ( l = 0; l < 3; l++ ) {
  556. prevxyz[l] = verts[(j+1)*maxWidth + i].xyz[l] - verts[j*maxWidth + i].xyz[l];
  557. nextxyz[l] = verts[(j+2)*maxWidth + i].xyz[l] - verts[(j+1)*maxWidth + i].xyz[l];
  558. midxyz[l] = (verts[j*maxWidth + i].xyz[l] + verts[(j+1)*maxWidth + i].xyz[l] * 2.0f +
  559. verts[(j+2)*maxWidth + i].xyz[l] ) * 0.25f;
  560. }
  561. if ( maxLength > 0.0f ) {
  562. // if the span length is too long, force a subdivision
  563. if ( prevxyz.LengthSqr() > maxLengthSqr || nextxyz.LengthSqr() > maxLengthSqr ) {
  564. break;
  565. }
  566. }
  567. // see if this midpoint is off far enough to subdivide
  568. delta = verts[(j+1)*maxWidth + i].xyz - midxyz;
  569. if ( delta.LengthSqr() > maxVerticalErrorSqr ) {
  570. break;
  571. }
  572. }
  573. if ( i == width ) {
  574. continue; // didn't need subdivision
  575. }
  576. if ( height + 2 >= maxHeight ) {
  577. ResizeExpanded( maxHeight + 4, maxWidth );
  578. }
  579. // insert two columns and replace the peak
  580. height += 2;
  581. for ( i = 0; i < width; i++ ) {
  582. LerpVert( verts[j*maxWidth + i], verts[(j+1)*maxWidth + i], prev );
  583. LerpVert( verts[(j+1)*maxWidth + i], verts[(j+2)*maxWidth + i], next );
  584. LerpVert( prev, next, mid );
  585. for ( k = height - 1; k > j + 3; k-- ) {
  586. verts[k*maxWidth + i] = verts[(k-2)*maxWidth + i];
  587. }
  588. verts[(j+1)*maxWidth + i] = prev;
  589. verts[(j+2)*maxWidth + i] = mid;
  590. verts[(j+3)*maxWidth + i] = next;
  591. }
  592. // back up and recheck this set again, it may need more subdivision
  593. j -= 2;
  594. }
  595. PutOnCurve();
  596. RemoveLinearColumnsRows();
  597. Collapse();
  598. // normalize all the lerped normals
  599. if ( genNormals ) {
  600. for ( i = 0; i < width * height; i++ ) {
  601. verts[i].normal.Normalize();
  602. }
  603. }
  604. GenerateIndexes();
  605. }