1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).
8
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW SP 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 RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 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.
25
26 ===========================================================================
27 */
28
29
30 #include "tr_local.h"
31
32 /*
33
34 This file does all of the processing necessary to turn a raw grid of points
35 read from the map file into a srfBspSurface_t ready for rendering.
36
37 The level of detail solution is direction independent, based only on subdivided
38 distance from the true curve.
39
40 Only a single entry point:
41
42 srfBspSurface_t *R_SubdividePatchToGrid( int width, int height,
43 srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
44
45 */
46
47
48 /*
49 ============
50 LerpDrawVert
51 ============
52 */
LerpDrawVert(srfVert_t * a,srfVert_t * b,srfVert_t * out)53 static void LerpDrawVert( srfVert_t *a, srfVert_t *b, srfVert_t *out ) {
54 out->xyz[0] = 0.5f * ( a->xyz[0] + b->xyz[0] );
55 out->xyz[1] = 0.5f * ( a->xyz[1] + b->xyz[1] );
56 out->xyz[2] = 0.5f * ( a->xyz[2] + b->xyz[2] );
57
58 out->st[0] = 0.5f * ( a->st[0] + b->st[0] );
59 out->st[1] = 0.5f * ( a->st[1] + b->st[1] );
60
61 out->lightmap[0] = 0.5f * ( a->lightmap[0] + b->lightmap[0] );
62 out->lightmap[1] = 0.5f * ( a->lightmap[1] + b->lightmap[1] );
63
64 out->color[0] = ((int)a->color[0] + (int)b->color[0]) >> 1;
65 out->color[1] = ((int)a->color[1] + (int)b->color[1]) >> 1;
66 out->color[2] = ((int)a->color[2] + (int)b->color[2]) >> 1;
67 out->color[3] = ((int)a->color[3] + (int)b->color[3]) >> 1;
68 }
69
70 /*
71 ============
72 Transpose
73 ============
74 */
Transpose(int width,int height,srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE])75 static void Transpose( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
76 int i, j;
77 srfVert_t temp;
78
79 if ( width > height ) {
80 for ( i = 0 ; i < height ; i++ ) {
81 for ( j = i + 1 ; j < width ; j++ ) {
82 if ( j < height ) {
83 // swap the value
84 temp = ctrl[j][i];
85 ctrl[j][i] = ctrl[i][j];
86 ctrl[i][j] = temp;
87 } else {
88 // just copy
89 ctrl[j][i] = ctrl[i][j];
90 }
91 }
92 }
93 } else {
94 for ( i = 0 ; i < width ; i++ ) {
95 for ( j = i + 1 ; j < height ; j++ ) {
96 if ( j < width ) {
97 // swap the value
98 temp = ctrl[i][j];
99 ctrl[i][j] = ctrl[j][i];
100 ctrl[j][i] = temp;
101 } else {
102 // just copy
103 ctrl[i][j] = ctrl[j][i];
104 }
105 }
106 }
107 }
108
109 }
110
111
112 /*
113 =================
114 MakeMeshNormals
115
116 Handles all the complicated wrapping and degenerate cases
117 =================
118 */
MakeMeshNormals(int width,int height,srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE])119 static void MakeMeshNormals( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
120 int i, j, k, dist;
121 vec3_t normal;
122 vec3_t sum;
123 int count = 0;
124 vec3_t base;
125 vec3_t delta;
126 int x, y;
127 srfVert_t *dv;
128 vec3_t around[8], temp;
129 qboolean good[8];
130 qboolean wrapWidth, wrapHeight;
131 float len;
132 static int neighbors[8][2] = {
133 {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
134 };
135
136 wrapWidth = qfalse;
137 for ( i = 0 ; i < height ; i++ ) {
138 VectorSubtract( ctrl[i][0].xyz, ctrl[i][width - 1].xyz, delta );
139 len = VectorLengthSquared( delta );
140 if ( len > 1.0 ) {
141 break;
142 }
143 }
144 if ( i == height ) {
145 wrapWidth = qtrue;
146 }
147
148 wrapHeight = qfalse;
149 for ( i = 0 ; i < width ; i++ ) {
150 VectorSubtract( ctrl[0][i].xyz, ctrl[height - 1][i].xyz, delta );
151 len = VectorLengthSquared( delta );
152 if ( len > 1.0 ) {
153 break;
154 }
155 }
156 if ( i == width ) {
157 wrapHeight = qtrue;
158 }
159
160
161 for ( i = 0 ; i < width ; i++ ) {
162 for ( j = 0 ; j < height ; j++ ) {
163 count = 0;
164 dv = &ctrl[j][i];
165 VectorCopy( dv->xyz, base );
166 for ( k = 0 ; k < 8 ; k++ ) {
167 VectorClear( around[k] );
168 good[k] = qfalse;
169
170 for ( dist = 1 ; dist <= 3 ; dist++ ) {
171 x = i + neighbors[k][0] * dist;
172 y = j + neighbors[k][1] * dist;
173 if ( wrapWidth ) {
174 if ( x < 0 ) {
175 x = width - 1 + x;
176 } else if ( x >= width ) {
177 x = 1 + x - width;
178 }
179 }
180 if ( wrapHeight ) {
181 if ( y < 0 ) {
182 y = height - 1 + y;
183 } else if ( y >= height ) {
184 y = 1 + y - height;
185 }
186 }
187
188 if ( x < 0 || x >= width || y < 0 || y >= height ) {
189 break; // edge of patch
190 }
191 VectorSubtract( ctrl[y][x].xyz, base, temp );
192 if ( VectorNormalize2( temp, temp ) == 0 ) {
193 continue; // degenerate edge, get more dist
194 } else {
195 good[k] = qtrue;
196 VectorCopy( temp, around[k] );
197 break; // good edge
198 }
199 }
200 }
201
202 VectorClear( sum );
203 for ( k = 0 ; k < 8 ; k++ ) {
204 if ( !good[k] || !good[( k + 1 ) & 7] ) {
205 continue; // didn't get two points
206 }
207 CrossProduct( around[( k + 1 ) & 7], around[k], normal );
208 if ( VectorNormalize2( normal, normal ) == 0 ) {
209 continue;
210 }
211 VectorAdd( normal, sum, sum );
212 count++;
213 }
214 //if ( count == 0 ) {
215 //printf("bad normal\n");
216 //}
217 {
218 vec3_t fNormal;
219 VectorNormalize2(sum, fNormal);
220 R_VaoPackNormal(dv->normal, fNormal);
221 }
222 }
223 }
224 }
225
MakeMeshTangentVectors(int width,int height,srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],int numIndexes,glIndex_t indexes[(MAX_GRID_SIZE-1)* (MAX_GRID_SIZE-1)* 2* 3])226 static void MakeMeshTangentVectors(int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], int numIndexes,
227 glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
228 {
229 int i, j;
230 srfVert_t *dv[3];
231 static srfVert_t ctrl2[MAX_GRID_SIZE * MAX_GRID_SIZE];
232 glIndex_t *tri;
233
234 // FIXME: use more elegant way
235 for(i = 0; i < width; i++)
236 {
237 for(j = 0; j < height; j++)
238 {
239 dv[0] = &ctrl2[j * width + i];
240 *dv[0] = ctrl[j][i];
241 }
242 }
243
244 for(i = 0, tri = indexes; i < numIndexes; i += 3, tri += 3)
245 {
246 dv[0] = &ctrl2[tri[0]];
247 dv[1] = &ctrl2[tri[1]];
248 dv[2] = &ctrl2[tri[2]];
249
250 R_CalcTangentVectors(dv);
251 }
252
253 for(i = 0; i < width; i++)
254 {
255 for(j = 0; j < height; j++)
256 {
257 dv[0] = &ctrl2[j * width + i];
258 dv[1] = &ctrl[j][i];
259
260 VectorCopy4(dv[0]->tangent, dv[1]->tangent);
261 }
262 }
263 }
264
265
MakeMeshIndexes(int width,int height,glIndex_t indexes[(MAX_GRID_SIZE-1)* (MAX_GRID_SIZE-1)* 2* 3])266 static int MakeMeshIndexes(int width, int height, glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3])
267 {
268 int i, j;
269 int numIndexes;
270 int w, h;
271
272 h = height - 1;
273 w = width - 1;
274 numIndexes = 0;
275 for(i = 0; i < h; i++)
276 {
277 for(j = 0; j < w; j++)
278 {
279 int v1, v2, v3, v4;
280
281 // vertex order to be reckognized as tristrips
282 v1 = i * width + j + 1;
283 v2 = v1 - 1;
284 v3 = v2 + width;
285 v4 = v3 + 1;
286
287 indexes[numIndexes++] = v2;
288 indexes[numIndexes++] = v3;
289 indexes[numIndexes++] = v1;
290
291 indexes[numIndexes++] = v1;
292 indexes[numIndexes++] = v3;
293 indexes[numIndexes++] = v4;
294 }
295 }
296
297 return numIndexes;
298 }
299
300 /*
301 ============
302 InvertCtrl
303 ============
304 */
InvertCtrl(int width,int height,srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE])305 static void InvertCtrl( int width, int height, srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
306 int i, j;
307 srfVert_t temp;
308
309 for ( i = 0 ; i < height ; i++ ) {
310 for ( j = 0 ; j < width / 2 ; j++ ) {
311 temp = ctrl[i][j];
312 ctrl[i][j] = ctrl[i][width - 1 - j];
313 ctrl[i][width - 1 - j] = temp;
314 }
315 }
316 }
317
318
319 /*
320 =================
321 InvertErrorTable
322 =================
323 */
InvertErrorTable(float errorTable[2][MAX_GRID_SIZE],int width,int height)324 static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
325 int i;
326 float copy[2][MAX_GRID_SIZE];
327
328 memcpy( copy, errorTable, sizeof( copy ) );
329
330 for ( i = 0 ; i < width ; i++ ) {
331 errorTable[1][i] = copy[0][i]; //[width-1-i];
332 }
333
334 for ( i = 0 ; i < height ; i++ ) {
335 errorTable[0][i] = copy[1][height - 1 - i];
336 }
337
338 }
339
340 /*
341 ==================
342 PutPointsOnCurve
343 ==================
344 */
PutPointsOnCurve(srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],int width,int height)345 static void PutPointsOnCurve( srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
346 int width, int height ) {
347 int i, j;
348 srfVert_t prev, next;
349
350 for ( i = 0 ; i < width ; i++ ) {
351 for ( j = 1 ; j < height ; j += 2 ) {
352 LerpDrawVert( &ctrl[j][i], &ctrl[j + 1][i], &prev );
353 LerpDrawVert( &ctrl[j][i], &ctrl[j - 1][i], &next );
354 LerpDrawVert( &prev, &next, &ctrl[j][i] );
355 }
356 }
357
358
359 for ( j = 0 ; j < height ; j++ ) {
360 for ( i = 1 ; i < width ; i += 2 ) {
361 LerpDrawVert( &ctrl[j][i], &ctrl[j][i + 1], &prev );
362 LerpDrawVert( &ctrl[j][i], &ctrl[j][i - 1], &next );
363 LerpDrawVert( &prev, &next, &ctrl[j][i] );
364 }
365 }
366 }
367
368
369 /*
370 =================
371 R_CreateSurfaceGridMesh
372 =================
373 */
R_CreateSurfaceGridMesh(srfBspSurface_t * grid,int width,int height,srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],float errorTable[2][MAX_GRID_SIZE],int numIndexes,glIndex_t indexes[(MAX_GRID_SIZE-1)* (MAX_GRID_SIZE-1)* 2* 3])374 void R_CreateSurfaceGridMesh(srfBspSurface_t *grid, int width, int height,
375 srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE],
376 int numIndexes, glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3]) {
377 int i, j;
378 srfVert_t *vert;
379 vec3_t tmpVec;
380
381 // copy the results out to a grid
382 Com_Memset(grid, 0, sizeof(*grid));
383
384 #ifdef PATCH_STITCHING
385 grid->widthLodError = malloc( width * 4 );
386 memcpy( grid->widthLodError, errorTable[0], width * 4 );
387
388 grid->heightLodError = malloc( height * 4 );
389 memcpy( grid->heightLodError, errorTable[1], height * 4 );
390
391 grid->numIndexes = numIndexes;
392 grid->indexes = ri.Z_Malloc(grid->numIndexes * sizeof(glIndex_t));
393 Com_Memcpy(grid->indexes, indexes, numIndexes * sizeof(glIndex_t));
394
395 grid->numVerts = (width * height);
396 grid->verts = ri.Z_Malloc(grid->numVerts * sizeof(srfVert_t));
397 #else
398 grid->widthLodError = ri.Hunk_Alloc( width * 4, h_low );
399 memcpy( grid->widthLodError, errorTable[0], width * 4 );
400
401 grid->heightLodError = ri.Hunk_Alloc( height * 4, h_low );
402 memcpy( grid->heightLodError, errorTable[1], height * 4 );
403
404 grid->numIndexes = numIndexes;
405 grid->indexes = ri.Hunk_Alloc(grid->numIndexes * sizeof(glIndex_t), h_low);
406 Com_Memcpy(grid->indexes, indexes, numIndexes * sizeof(glIndex_t));
407
408 grid->numVerts = (width * height);
409 grid->verts = ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low);
410 #endif
411
412 grid->width = width;
413 grid->height = height;
414 grid->surfaceType = SF_GRID;
415 ClearBounds( grid->cullBounds[0], grid->cullBounds[1] );
416 for ( i = 0 ; i < width ; i++ ) {
417 for ( j = 0 ; j < height ; j++ ) {
418 vert = &grid->verts[j * width + i];
419 *vert = ctrl[j][i];
420 AddPointToBounds( vert->xyz, grid->cullBounds[0], grid->cullBounds[1] );
421 }
422 }
423
424 // compute local origin and bounds
425 VectorAdd( grid->cullBounds[0], grid->cullBounds[1], grid->cullOrigin );
426 VectorScale( grid->cullOrigin, 0.5f, grid->cullOrigin );
427 VectorSubtract( grid->cullBounds[0], grid->cullOrigin, tmpVec );
428 grid->cullRadius = VectorLength( tmpVec );
429
430 VectorCopy( grid->cullOrigin, grid->lodOrigin );
431 grid->lodRadius = grid->cullRadius;
432 //
433 }
434
435 /*
436 =================
437 R_FreeSurfaceGridMeshData
438 =================
439 */
R_FreeSurfaceGridMeshData(srfBspSurface_t * grid)440 static void R_FreeSurfaceGridMeshData( srfBspSurface_t *grid ) {
441 ri.Free( grid->widthLodError );
442 ri.Free( grid->heightLodError );
443 ri.Free( grid->indexes );
444 ri.Free( grid->verts );
445 }
446
447 /*
448 =================
449 R_SubdividePatchToGrid
450 =================
451 */
R_SubdividePatchToGrid(srfBspSurface_t * grid,int width,int height,srfVert_t points[MAX_PATCH_SIZE * MAX_PATCH_SIZE])452 void R_SubdividePatchToGrid( srfBspSurface_t *grid, int width, int height,
453 srfVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
454 int i, j, k, l;
455 srfVert_t_cleared( prev );
456 srfVert_t_cleared( next );
457 srfVert_t_cleared( mid );
458 float len, maxLen;
459 int dir;
460 int t;
461 srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
462 float errorTable[2][MAX_GRID_SIZE];
463 int numIndexes;
464 static glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3];
465 int consecutiveComplete;
466
467 for ( i = 0 ; i < width ; i++ ) {
468 for ( j = 0 ; j < height ; j++ ) {
469 ctrl[j][i] = points[j * width + i];
470 }
471 }
472
473 for ( dir = 0 ; dir < 2 ; dir++ ) {
474
475 for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
476 errorTable[dir][j] = 0;
477 }
478
479 consecutiveComplete = 0;
480
481 // horizontal subdivisions
482 for ( j = 0 ; ; j = (j + 2) % (width - 1) ) {
483 // check subdivided midpoints against control points
484
485 // FIXME: also check midpoints of adjacent patches against the control points
486 // this would basically stitch all patches in the same LOD group together.
487
488 maxLen = 0;
489 for ( i = 0 ; i < height ; i++ ) {
490 vec3_t midxyz;
491 vec3_t dir;
492 vec3_t projected;
493 float d;
494
495 // calculate the point on the curve
496 for ( l = 0 ; l < 3 ; l++ ) {
497 midxyz[l] = ( ctrl[i][j].xyz[l] + ctrl[i][j + 1].xyz[l] * 2
498 + ctrl[i][j + 2].xyz[l] ) * 0.25f;
499 }
500
501 // see how far off the line it is
502 // using dist-from-line will not account for internal
503 // texture warping, but it gives a lot less polygons than
504 // dist-from-midpoint
505 VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz );
506 VectorSubtract( ctrl[i][j + 2].xyz, ctrl[i][j].xyz, dir );
507 VectorNormalize( dir );
508
509 d = DotProduct( midxyz, dir );
510 VectorScale( dir, d, projected );
511 VectorSubtract( midxyz, projected, midxyz );
512 len = VectorLengthSquared( midxyz ); // we will do the sqrt later
513
514 if ( len > maxLen ) {
515 maxLen = len;
516 }
517 }
518
519 maxLen = sqrt( maxLen );
520 // if all the points are on the lines, remove the entire columns
521 if ( maxLen < 0.1f ) {
522 errorTable[dir][j + 1] = 999;
523 // if we go over the whole grid twice without adding any columns, stop
524 if (++consecutiveComplete >= width)
525 break;
526 continue;
527 }
528
529 // see if we want to insert subdivided columns
530 if ( width + 2 > MAX_GRID_SIZE ) {
531 errorTable[dir][j + 1] = 1.0f / maxLen;
532 break; // can't subdivide any more
533 }
534
535 if ( maxLen <= r_subdivisions->value ) {
536 errorTable[dir][j + 1] = 1.0f / maxLen;
537 // if we go over the whole grid twice without adding any columns, stop
538 if (++consecutiveComplete >= width)
539 break;
540 continue; // didn't need subdivision
541 }
542
543 errorTable[dir][j + 2] = 1.0f / maxLen;
544
545 consecutiveComplete = 0;
546
547 // insert two columns and replace the peak
548 width += 2;
549 for ( i = 0 ; i < height ; i++ ) {
550 LerpDrawVert( &ctrl[i][j], &ctrl[i][j + 1], &prev );
551 LerpDrawVert( &ctrl[i][j + 1], &ctrl[i][j + 2], &next );
552 LerpDrawVert( &prev, &next, &mid );
553
554 for ( k = width - 1 ; k > j + 3 ; k-- ) {
555 ctrl[i][k] = ctrl[i][k - 2];
556 }
557 ctrl[i][j + 1] = prev;
558 ctrl[i][j + 2] = mid;
559 ctrl[i][j + 3] = next;
560 }
561
562 // skip the new one, we'll get it on the next pass
563 j += 2;
564 }
565
566 Transpose( width, height, ctrl );
567 t = width;
568 width = height;
569 height = t;
570 }
571
572
573 // put all the aproximating points on the curve
574 PutPointsOnCurve( ctrl, width, height );
575
576 // cull out any rows or columns that are colinear
577 for ( i = 1 ; i < width - 1 ; i++ ) {
578 if ( errorTable[0][i] != 999 ) {
579 continue;
580 }
581 for ( j = i + 1 ; j < width ; j++ ) {
582 for ( k = 0 ; k < height ; k++ ) {
583 ctrl[k][j - 1] = ctrl[k][j];
584 }
585 errorTable[0][j - 1] = errorTable[0][j];
586 }
587 width--;
588 }
589
590 for ( i = 1 ; i < height - 1 ; i++ ) {
591 if ( errorTable[1][i] != 999 ) {
592 continue;
593 }
594 for ( j = i + 1 ; j < height ; j++ ) {
595 for ( k = 0 ; k < width ; k++ ) {
596 ctrl[j - 1][k] = ctrl[j][k];
597 }
598 errorTable[1][j - 1] = errorTable[1][j];
599 }
600 height--;
601 }
602
603 #if 1
604 // flip for longest tristrips as an optimization
605 // the results should be visually identical with or
606 // without this step
607 if ( height > width ) {
608 Transpose( width, height, ctrl );
609 InvertErrorTable( errorTable, width, height );
610 t = width;
611 width = height;
612 height = t;
613 InvertCtrl( width, height, ctrl );
614 }
615 #endif
616
617 // calculate indexes
618 numIndexes = MakeMeshIndexes(width, height, indexes);
619
620 // calculate normals
621 MakeMeshNormals( width, height, ctrl );
622 MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
623
624 R_CreateSurfaceGridMesh(grid, width, height, ctrl, errorTable, numIndexes, indexes);
625 }
626
627 /*
628 ===============
629 R_GridInsertColumn
630 ===============
631 */
R_GridInsertColumn(srfBspSurface_t * grid,int column,int row,vec3_t point,float loderror)632 void R_GridInsertColumn( srfBspSurface_t *grid, int column, int row, vec3_t point, float loderror ) {
633 int i, j;
634 int width, height, oldwidth;
635 srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
636 float errorTable[2][MAX_GRID_SIZE];
637 float lodRadius;
638 vec3_t lodOrigin;
639 int numIndexes;
640 static glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3];
641
642 oldwidth = 0;
643 width = grid->width + 1;
644 if ( width > MAX_GRID_SIZE ) {
645 return;
646 }
647 height = grid->height;
648 for ( i = 0; i < width; i++ ) {
649 if ( i == column ) {
650 //insert new column
651 for ( j = 0; j < grid->height; j++ ) {
652 LerpDrawVert( &grid->verts[j * grid->width + i - 1], &grid->verts[j * grid->width + i], &ctrl[j][i] );
653 if ( j == row ) {
654 VectorCopy( point, ctrl[j][i].xyz );
655 }
656 }
657 errorTable[0][i] = loderror;
658 continue;
659 }
660 errorTable[0][i] = grid->widthLodError[oldwidth];
661 for ( j = 0; j < grid->height; j++ ) {
662 ctrl[j][i] = grid->verts[j * grid->width + oldwidth];
663 }
664 oldwidth++;
665 }
666 for ( j = 0; j < grid->height; j++ ) {
667 errorTable[1][j] = grid->heightLodError[j];
668 }
669 // put all the aproximating points on the curve
670 //PutPointsOnCurve( ctrl, width, height );
671
672 // calculate indexes
673 numIndexes = MakeMeshIndexes(width, height, indexes);
674
675 // calculate normals
676 MakeMeshNormals( width, height, ctrl );
677 MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
678
679 VectorCopy( grid->lodOrigin, lodOrigin );
680 lodRadius = grid->lodRadius;
681 // free the old grid
682 R_FreeSurfaceGridMeshData(grid);
683 // create a new grid
684 R_CreateSurfaceGridMesh(grid, width, height, ctrl, errorTable, numIndexes, indexes);
685 grid->lodRadius = lodRadius;
686 VectorCopy( lodOrigin, grid->lodOrigin );
687 }
688
689 /*
690 ===============
691 R_GridInsertRow
692 ===============
693 */
R_GridInsertRow(srfBspSurface_t * grid,int row,int column,vec3_t point,float loderror)694 void R_GridInsertRow( srfBspSurface_t *grid, int row, int column, vec3_t point, float loderror ) {
695 int i, j;
696 int width, height, oldheight;
697 srfVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
698 float errorTable[2][MAX_GRID_SIZE];
699 float lodRadius;
700 vec3_t lodOrigin;
701 int numIndexes;
702 static glIndex_t indexes[(MAX_GRID_SIZE-1)*(MAX_GRID_SIZE-1)*2*3];
703
704 oldheight = 0;
705 width = grid->width;
706 height = grid->height + 1;
707 if ( height > MAX_GRID_SIZE ) {
708 return;
709 }
710 for ( i = 0; i < height; i++ ) {
711 if ( i == row ) {
712 //insert new row
713 for ( j = 0; j < grid->width; j++ ) {
714 LerpDrawVert( &grid->verts[( i - 1 ) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] );
715 if ( j == column ) {
716 VectorCopy( point, ctrl[i][j].xyz );
717 }
718 }
719 errorTable[1][i] = loderror;
720 continue;
721 }
722 errorTable[1][i] = grid->heightLodError[oldheight];
723 for ( j = 0; j < grid->width; j++ ) {
724 ctrl[i][j] = grid->verts[oldheight * grid->width + j];
725 }
726 oldheight++;
727 }
728 for ( j = 0; j < grid->width; j++ ) {
729 errorTable[0][j] = grid->widthLodError[j];
730 }
731 // put all the aproximating points on the curve
732 //PutPointsOnCurve( ctrl, width, height );
733
734 // calculate indexes
735 numIndexes = MakeMeshIndexes(width, height, indexes);
736
737 // calculate normals
738 MakeMeshNormals( width, height, ctrl );
739 MakeMeshTangentVectors(width, height, ctrl, numIndexes, indexes);
740
741 VectorCopy( grid->lodOrigin, lodOrigin );
742 lodRadius = grid->lodRadius;
743 // free the old grid
744 R_FreeSurfaceGridMeshData(grid);
745 // create a new grid
746 R_CreateSurfaceGridMesh(grid, width, height, ctrl, errorTable, numIndexes, indexes);
747 grid->lodRadius = lodRadius;
748 VectorCopy( lodOrigin, grid->lodOrigin );
749 }
750
751