2 GenSurf plugin for GtkRadiant
3 Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library 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 GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 double xmin,xmax,ymin,ymax,zmin,zmax;
29 XYZ xyz[MAX_ROWS + 1][MAX_ROWS + 1];
35 #include "refcounted_ptr.h"
44 scene::Node* h_func_group;
45 scene::Node* h_worldspawn;
48 //=============================================================
49 // Hydra : snap-to-grid begin
50 double CalculateSnapValue( double value ){
53 // simple uncomplicated snapping, rounding both UP and DOWN to the nearest
55 if ( SnapToGrid > 0 ) {
56 snapvalue = (int)value / SnapToGrid;
57 if ( (long)value % SnapToGrid < ( SnapToGrid / 2 ) ) { // Snap Downwards if less than halfway between to grid units
58 value = snapvalue * SnapToGrid;
60 else{ // Snap Upwards if more than halfway between to grid units
61 value = ( snapvalue + 1 ) * SnapToGrid;
66 // Hydra : snap-to-grid end
68 //=============================================================
70 if ( WaveType == WAVE_BITMAP && !gbmp.colors ) {
76 if ( NH > MAX_ROWS ) {
82 if ( NV > MAX_ROWS ) {
94 //=============================================================
101 int i, j, k1, k2, k3;
105 dh = ( Hur - Hll ) / NH;
106 dv = ( Vur - Vll ) / NV;
108 // Generate control points in pp array to give desired values currently
131 for ( i = 0; i <= NH; i++ )
133 for ( j = 0; j <= NV; j++ )
135 xyz[i][j].pp[k1] = xyz[i][j].p[k1];
136 xyz[i][j].pp[k2] = xyz[i][j].p[k2];
139 for ( i = 0; i <= NH; i += 2 )
141 for ( j = 0; j <= NV; j += 2 )
142 xyz[i][j].pp[k3] = xyz[i][j].p[k3];
144 for ( i = 1; i < NH; i += 2 )
146 for ( j = 0; j <= NV; j += 2 )
148 xyz[i][j].pp[k3] = ( 4 * xyz[i][j].p[k3] - xyz[i - 1][j].p[k3] - xyz[i + 1][j].p[k3] ) / 2;
151 for ( j = 1; j < NV; j += 2 )
153 for ( i = 0; i <= NH; i += 2 )
155 xyz[i][j].pp[k3] = ( 4 * xyz[i][j].p[k3] - xyz[i][j - 1].p[k3] - xyz[i][j + 1].p[k3] ) / 2;
158 for ( i = 1; i < NH; i += 2 )
160 for ( j = 1; j < NV; j += 2 )
162 xyz[i][j].pp[k3] = ( 16 * xyz[i][j].p[k3] - xyz[i - 1][j - 1].p[k3] - 2 * xyz[i][j - 1].p[k3]
163 - xyz[i + 1][j - 1].p[k3] - 2 * xyz[i - 1][j].p[k3] - 2 * xyz[i + 1][j].p[k3]
164 - xyz[i - 1][j + 1].p[k3] - 2 * xyz[i][j + 1].p[k3] - xyz[i + 1][j + 1].p[k3] ) / 4;
170 while ( NH_remain > 1 )
172 if ( ( ( NH_remain - 1 ) % 14 ) == 0 ) {
175 else if ( ( ( NH_remain - 1 ) % 12 ) == 0 ) {
178 else if ( ( ( NH_remain - 1 ) % 10 ) == 0 ) {
181 else if ( ( ( NH_remain - 1 ) % 8 ) == 0 ) {
184 else if ( ( ( NH_remain - 1 ) % 6 ) == 0 ) {
187 else if ( ( ( NH_remain - 1 ) % 4 ) == 0 ) {
190 else if ( ( ( NH_remain - 1 ) % 2 ) == 0 ) {
193 else if ( NH_remain > 16 ) {
196 else if ( NH_remain > 4 ) {
202 while ( NH_patch > 3 && ( NH_patch - 1 ) * dh > 512 )
204 NH_remain -= ( NH_patch - 1 );
205 if ( NH_remain < 0 ) {
206 sprintf( szOops,"Oops... screwed up with NH=%d",NH );
207 g_FuncTable.m_pfnMessageBox( NULL,szOops,"Uh oh" );
211 while ( NV_remain > 1 )
213 if ( ( ( NV_remain - 1 ) % 14 ) == 0 ) {
216 else if ( ( ( NV_remain - 1 ) % 12 ) == 0 ) {
219 else if ( ( ( NV_remain - 1 ) % 10 ) == 0 ) {
222 else if ( ( ( NV_remain - 1 ) % 8 ) == 0 ) {
225 else if ( ( ( NV_remain - 1 ) % 6 ) == 0 ) {
228 else if ( ( ( NV_remain - 1 ) % 4 ) == 0 ) {
231 else if ( ( ( NV_remain - 1 ) % 2 ) == 0 ) {
234 else if ( NV_remain > 16 ) {
237 else if ( NV_remain > 4 ) {
243 while ( NV_patch > 3 && ( NV_patch - 1 ) * dh > 512 )
245 NV_remain -= ( NV_patch - 1 );
246 if ( NV_remain < 0 ) {
247 sprintf( szOops,"Oops... screwed up with NV=%d",NV );
248 g_FuncTable.m_pfnMessageBox( NULL,szOops,"Uh oh" );
251 scene::Node* patch = MakePatch();
260 //=============================================================
269 vec3_t PlaneNormal,SurfNormal;
277 strcpy( surftext,Texture[Game][0] );
278 strcpy( sidetext,( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
279 strcpy( surftext2,( strlen( Texture[Game][2] ) ? Texture[Game][2] : Texture[Game][0] ) );
281 // if surftext2 is identical to surftext, there's no need to
282 // check surface angle
283 if ( !g_strcasecmp( surftext,surftext2 ) ) {
289 Steep = (float)cos( (double)SlantAngle / 57.2957795 );
292 case PLANE_XY0: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
293 case PLANE_XY1: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = -1.; break;
294 case PLANE_XZ0: PlaneNormal[0] = 0.; PlaneNormal[1] = 1.; PlaneNormal[2] = 1.; break;
295 case PLANE_XZ1: PlaneNormal[0] = 0.; PlaneNormal[1] = -1.; PlaneNormal[2] = 1.; break;
296 case PLANE_YZ0: PlaneNormal[0] = 1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
297 case PLANE_YZ1: PlaneNormal[0] = -1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
303 for ( i = 0; i < NH; i++ )
305 for ( j = 0; j < NV; j++ )
307 if ( ( i + j ) % 2 ) {
308 VectorCopy( xyz[i ][j ].p, v[0].p );
314 VectorCopy( xyz[i + 1][j ].p, v[1].p );
315 VectorCopy( xyz[i + 1][j + 1].p, v[2].p );
318 VectorCopy( xyz[i + 1][j + 1].p, v[1].p );
319 VectorCopy( xyz[i + 1][j ].p, v[2].p );
324 VectorCopy( xyz[i ][j ].p, v[0].p );
330 VectorCopy( xyz[i + 1][j ].p, v[1].p );
331 VectorCopy( xyz[i ][j + 1].p, v[2].p );
334 VectorCopy( xyz[i ][j + 1].p, v[1].p );
335 VectorCopy( xyz[i + 1][j ].p, v[2].p );
338 VectorCopy( v[0].p,v[3].p );
339 VectorCopy( v[1].p,v[4].p );
340 VectorCopy( v[2].p,v[5].p );
345 v[0].p[1] = backface;
346 v[1].p[1] = backface;
347 v[2].p[1] = backface;
351 v[3].p[0] = backface;
352 v[4].p[0] = backface;
353 v[5].p[0] = backface;
356 v[3].p[2] = backface;
357 v[4].p[2] = backface;
358 v[5].p[2] = backface;
361 brush.Number = i * NV * 2 + j * 2;
363 XYZtoV( &v[0],&brush.face[0].v[0] );
364 XYZtoV( &v[3],&brush.face[0].v[1] );
365 XYZtoV( &v[4],&brush.face[0].v[2] );
366 strcpy( brush.face[0].texture,
367 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
368 brush.face[0].Shift[0] = (float)TexOffset[0];
369 brush.face[0].Shift[1] = (float)TexOffset[1];
370 brush.face[0].Rotate = 0.;
371 brush.face[0].Scale[0] = (float)TexScale[0];
372 brush.face[0].Scale[1] = (float)TexScale[1];
373 brush.face[0].Contents = contents;
374 brush.face[0].Surface = surface[1];
375 brush.face[0].Value = 0;
377 XYZtoV( &v[1],&brush.face[1].v[0] );
378 XYZtoV( &v[4],&brush.face[1].v[1] );
379 XYZtoV( &v[5],&brush.face[1].v[2] );
380 strcpy( brush.face[1].texture,
381 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
382 brush.face[1].Shift[0] = (float)TexOffset[0];
383 brush.face[1].Shift[1] = (float)TexOffset[1];
384 brush.face[1].Rotate = 0.;
385 brush.face[1].Scale[0] = (float)TexScale[0];
386 brush.face[1].Scale[1] = (float)TexScale[1];
387 brush.face[1].Contents = contents;
388 brush.face[1].Surface = surface[1];
389 brush.face[1].Value = 0;
391 XYZtoV( &v[2],&brush.face[2].v[0] );
392 XYZtoV( &v[5],&brush.face[2].v[1] );
393 XYZtoV( &v[3],&brush.face[2].v[2] );
394 strcpy( brush.face[2].texture,
395 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
396 brush.face[2].Shift[0] = (float)TexOffset[0];
397 brush.face[2].Shift[1] = (float)TexOffset[1];
398 brush.face[2].Rotate = 0.;
399 brush.face[2].Scale[0] = (float)TexScale[0];
400 brush.face[2].Scale[1] = (float)TexScale[1];
401 brush.face[2].Contents = contents;
402 brush.face[2].Surface = surface[1];
403 brush.face[2].Value = 0;
405 if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) {
406 XYZVectorSubtract( v[4].p,v[3].p,t[0] );
407 XYZVectorSubtract( v[5].p,v[4].p,t[1] );
408 CrossProduct( t[0],t[1],SurfNormal );
409 VectorNormalize( SurfNormal,SurfNormal );
410 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
411 strcpy( surft,surftext2 );
416 strcpy( surft,surftext );
422 strcpy( surft,surftext );
426 XYZtoV( &v[3],&brush.face[3].v[0] );
427 XYZtoV( &v[5],&brush.face[3].v[1] );
428 XYZtoV( &v[4],&brush.face[3].v[2] );
429 strcpy( brush.face[3].texture,
430 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) );
431 brush.face[3].Shift[0] = (float)TexOffset[0];
432 brush.face[3].Shift[1] = (float)TexOffset[1];
433 brush.face[3].Rotate = 0.;
434 brush.face[3].Scale[0] = (float)TexScale[0];
435 brush.face[3].Scale[1] = (float)TexScale[1];
436 brush.face[3].Contents = contents;
437 brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] );
438 brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 );
440 if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) {
441 XYZVectorSubtract( v[2].p,v[0].p,t[0] );
442 XYZVectorSubtract( v[1].p,v[2].p,t[1] );
443 CrossProduct( t[0],t[1],SurfNormal );
444 VectorNormalize( SurfNormal,SurfNormal );
445 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
446 strcpy( surft,surftext2 );
451 strcpy( surft,surftext );
457 strcpy( surft,surftext );
461 XYZtoV( &v[0],&brush.face[4].v[0] );
462 XYZtoV( &v[1],&brush.face[4].v[1] );
463 XYZtoV( &v[2],&brush.face[4].v[2] );
464 strcpy( brush.face[4].texture,
465 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) );
466 brush.face[4].Shift[0] = (float)TexOffset[0];
467 brush.face[4].Shift[1] = (float)TexOffset[1];
468 brush.face[4].Rotate = 0.;
469 brush.face[4].Scale[0] = (float)TexScale[0];
470 brush.face[4].Scale[1] = (float)TexScale[1];
471 brush.face[4].Contents = contents;
472 brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf );
473 brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 );
476 if ( ( i + j ) % 2 ) {
477 VectorCopy( xyz[i ][j + 1].p,v[0].p );
483 VectorCopy( xyz[i ][j ].p,v[1].p );
484 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
487 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
488 VectorCopy( xyz[i ][j ].p,v[2].p );
493 VectorCopy( xyz[i ][j + 1].p,v[0].p );
499 VectorCopy( xyz[i + 1][j ].p,v[1].p );
500 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
503 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
504 VectorCopy( xyz[i + 1][j ].p,v[2].p );
507 VectorCopy( v[0].p,v[3].p );
508 VectorCopy( v[1].p,v[4].p );
509 VectorCopy( v[2].p,v[5].p );
514 v[0].p[1] = backface;
515 v[1].p[1] = backface;
516 v[2].p[1] = backface;
520 v[3].p[0] = backface;
521 v[4].p[0] = backface;
522 v[5].p[0] = backface;
525 v[3].p[2] = backface;
526 v[4].p[2] = backface;
527 v[5].p[2] = backface;
529 brush.Number = i * NV * 2 + j * 2 + 1;
531 XYZtoV( &v[0],&brush.face[0].v[0] );
532 XYZtoV( &v[3],&brush.face[0].v[1] );
533 XYZtoV( &v[4],&brush.face[0].v[2] );
534 strcpy( brush.face[0].texture,
535 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
536 brush.face[0].Shift[0] = (float)TexOffset[0];
537 brush.face[0].Shift[1] = (float)TexOffset[1];
538 brush.face[0].Rotate = 0.;
539 brush.face[0].Scale[0] = (float)TexScale[0];
540 brush.face[0].Scale[1] = (float)TexScale[1];
541 brush.face[0].Contents = contents;
542 brush.face[0].Surface = surface[1];
543 brush.face[0].Value = 0;
545 XYZtoV( &v[1],&brush.face[1].v[0] );
546 XYZtoV( &v[4],&brush.face[1].v[1] );
547 XYZtoV( &v[5],&brush.face[1].v[2] );
548 strcpy( brush.face[1].texture,
549 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
550 brush.face[1].Shift[0] = (float)TexOffset[0];
551 brush.face[1].Shift[1] = (float)TexOffset[1];
552 brush.face[1].Rotate = 0.;
553 brush.face[1].Scale[0] = (float)TexScale[0];
554 brush.face[1].Scale[1] = (float)TexScale[1];
555 brush.face[1].Contents = contents;
556 brush.face[1].Surface = surface[1];
557 brush.face[1].Value = 0;
559 XYZtoV( &v[2],&brush.face[2].v[0] );
560 XYZtoV( &v[5],&brush.face[2].v[1] );
561 XYZtoV( &v[3],&brush.face[2].v[2] );
562 strcpy( brush.face[2].texture,
563 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
564 brush.face[2].Shift[0] = (float)TexOffset[0];
565 brush.face[2].Shift[1] = (float)TexOffset[1];
566 brush.face[2].Rotate = 0.;
567 brush.face[2].Scale[0] = (float)TexScale[0];
568 brush.face[2].Scale[1] = (float)TexScale[1];
569 brush.face[2].Contents = contents;
570 brush.face[2].Surface = surface[1];
571 brush.face[2].Value = 0;
573 if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) {
574 XYZVectorSubtract( v[4].p,v[3].p,t[0] );
575 XYZVectorSubtract( v[5].p,v[4].p,t[1] );
576 CrossProduct( t[0],t[1],SurfNormal );
577 VectorNormalize( SurfNormal,SurfNormal );
578 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
579 strcpy( surft,surftext2 );
584 strcpy( surft,surftext );
590 strcpy( surft,surftext );
593 XYZtoV( &v[3],&brush.face[3].v[0] );
594 XYZtoV( &v[5],&brush.face[3].v[1] );
595 XYZtoV( &v[4],&brush.face[3].v[2] );
596 strcpy( brush.face[3].texture,
597 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) );
598 brush.face[3].Shift[0] = (float)TexOffset[0];
599 brush.face[3].Shift[1] = (float)TexOffset[1];
600 brush.face[3].Rotate = 0.;
601 brush.face[3].Scale[0] = (float)TexScale[0];
602 brush.face[3].Scale[1] = (float)TexScale[1];
603 brush.face[3].Contents = contents;
604 brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] );
605 brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 );
607 if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) {
608 XYZVectorSubtract( v[2].p,v[0].p,t[0] );
609 XYZVectorSubtract( v[1].p,v[2].p,t[1] );
610 CrossProduct( t[0],t[1],SurfNormal );
611 VectorNormalize( SurfNormal,SurfNormal );
612 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
613 strcpy( surft,surftext2 );
618 strcpy( surft,surftext );
624 strcpy( surft,surftext );
627 XYZtoV( &v[0],&brush.face[4].v[0] );
628 XYZtoV( &v[1],&brush.face[4].v[1] );
629 XYZtoV( &v[2],&brush.face[4].v[2] );
630 strcpy( brush.face[4].texture,
631 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) );
632 brush.face[4].Shift[0] = (float)TexOffset[0];
633 brush.face[4].Shift[1] = (float)TexOffset[1];
634 brush.face[4].Rotate = 0.;
635 brush.face[4].Scale[0] = (float)TexScale[0];
636 brush.face[4].Scale[1] = (float)TexScale[1];
637 brush.face[4].Contents = contents;
638 brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf );
639 brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 );
646 if ( AddHints || GimpHints ) {
647 int detail, i1, j1, N;
653 strcpy( hint,"HINT" );
654 strcpy( skip,"HINT" );
657 strcpy( hint,"generic/misc/hint" );
658 strcpy( skip,"generic/misc/skip" );
661 strcpy( hint,"general/hint" );
662 strcpy( skip,"general/hint" ); // Heretic2 doesn't have a skip texture
665 strcpy( hint,"common/0_hint" );
666 strcpy( skip,"common/0_skip" );
669 strcpy( hint,"hint" );
670 strcpy( skip,"hint" );
673 strcpy( hint,"textures/common/hint" );
674 strcpy( skip,"textures/common/skip" );
677 strcpy( hint,"e1u1/hint" );
678 strcpy( skip,"e1u1/skip" );
683 if ( AddHints == 1 ) {
684 detail = CONTENTS_DETAIL;
686 for ( i = 0; i < NH; i++ )
690 for ( j = 0; j < NV; j++ )
693 // For detail hint brushes, no need to use a hint brush over
694 // EVERY grid square... it would be redundant. Instead use
695 // a checkerboard pattern
696 if ( ( i + j ) % 2 ) {
702 VectorCopy( xyz[i ][j ].p, v[0].p );
708 VectorCopy( xyz[i1][j ].p, v[1].p );
709 VectorCopy( xyz[i1][j1].p, v[2].p );
710 VectorCopy( xyz[i ][j1].p, v[3].p );
713 VectorCopy( xyz[i ][j1].p, v[1].p );
714 VectorCopy( xyz[i1][j1].p, v[2].p );
715 VectorCopy( xyz[i1][j ].p, v[3].p );
718 VectorCopy( v[0].p,v[4].p );
719 VectorCopy( v[1].p,v[5].p );
720 VectorCopy( v[2].p,v[6].p );
721 VectorCopy( v[3].p,v[7].p );
726 front = LessThan( zmin,32. );
727 v[4].p[2] = backface;
728 v[5].p[2] = backface;
729 v[6].p[2] = backface;
730 v[7].p[2] = backface;
733 front = MoreThan( ymax,32. );
734 v[0].p[1] = backface;
735 v[1].p[1] = backface;
736 v[2].p[1] = backface;
737 v[3].p[1] = backface;
740 front = LessThan( ymin,32. );
741 v[0].p[1] = backface;
742 v[1].p[1] = backface;
743 v[2].p[1] = backface;
744 v[3].p[1] = backface;
747 front = MoreThan( xmax,32. );
748 v[4].p[0] = backface;
749 v[5].p[0] = backface;
750 v[6].p[0] = backface;
751 v[7].p[0] = backface;
754 front = LessThan( xmin,32. );
755 v[4].p[0] = backface;
756 v[5].p[0] = backface;
757 v[6].p[0] = backface;
758 v[7].p[0] = backface;
761 front = MoreThan( zmax,32. );
762 v[4].p[2] = backface;
763 v[5].p[2] = backface;
764 v[6].p[2] = backface;
765 v[7].p[2] = backface;
773 v[5].p[1] = v[4].p[1];
774 v[6].p[1] = v[4].p[1];
775 v[7].p[1] = v[4].p[1];
780 v[1].p[0] = v[0].p[0];
781 v[2].p[0] = v[0].p[0];
782 v[3].p[0] = v[0].p[0];
786 v[1].p[2] = v[0].p[2];
787 v[2].p[2] = v[0].p[2];
788 v[3].p[2] = v[0].p[2];
793 XYZtoV( &v[0],&brush.face[0].v[0] );
794 XYZtoV( &v[1],&brush.face[0].v[1] );
795 XYZtoV( &v[2],&brush.face[0].v[2] );
796 strcpy( brush.face[0].texture,skip );
797 brush.face[0].Shift[0] = 0.;
798 brush.face[0].Shift[1] = 0.;
799 brush.face[0].Rotate = 0.;
800 brush.face[0].Scale[0] = 1.;
801 brush.face[0].Scale[1] = 1.;
802 brush.face[0].Contents = detail;
803 brush.face[0].Surface = SURF_SKIP;
804 brush.face[0].Value = 0;
806 XYZtoV( &v[4],&brush.face[1].v[0] );
807 XYZtoV( &v[7],&brush.face[1].v[1] );
808 XYZtoV( &v[6],&brush.face[1].v[2] );
809 strcpy( brush.face[1].texture,skip );
810 brush.face[1].Shift[0] = 0.;
811 brush.face[1].Shift[1] = 0.;
812 brush.face[1].Rotate = 0.;
813 brush.face[1].Scale[0] = 1.;
814 brush.face[1].Scale[1] = 1.;
815 brush.face[1].Contents = detail;
816 brush.face[1].Surface = SURF_SKIP;
817 brush.face[1].Value = 0;
819 XYZtoV( &v[0],&brush.face[2].v[0] );
820 XYZtoV( &v[4],&brush.face[2].v[1] );
821 XYZtoV( &v[5],&brush.face[2].v[2] );
822 strcpy( brush.face[2].texture,hint );
823 brush.face[2].Shift[0] = 0.;
824 brush.face[2].Shift[1] = 0.;
825 brush.face[2].Rotate = 0.;
826 brush.face[2].Scale[0] = 1.;
827 brush.face[2].Scale[1] = 1.;
828 brush.face[2].Contents = detail;
829 brush.face[2].Surface = SURF_HINT;
830 brush.face[2].Value = 0;
832 XYZtoV( &v[1],&brush.face[3].v[0] );
833 XYZtoV( &v[5],&brush.face[3].v[1] );
834 XYZtoV( &v[6],&brush.face[3].v[2] );
835 strcpy( brush.face[3].texture,hint );
836 brush.face[3].Shift[0] = 0.;
837 brush.face[3].Shift[1] = 0.;
838 brush.face[3].Rotate = 0.;
839 brush.face[3].Scale[0] = 1.;
840 brush.face[3].Scale[1] = 1.;
841 brush.face[3].Contents = detail;
842 brush.face[3].Surface = SURF_HINT;
843 brush.face[3].Value = 0;
845 XYZtoV( &v[2],&brush.face[4].v[0] );
846 XYZtoV( &v[6],&brush.face[4].v[1] );
847 XYZtoV( &v[7],&brush.face[4].v[2] );
848 strcpy( brush.face[4].texture,hint );
849 brush.face[4].Shift[0] = 0.;
850 brush.face[4].Shift[1] = 0.;
851 brush.face[4].Rotate = 0.;
852 brush.face[4].Scale[0] = 1.;
853 brush.face[4].Scale[1] = 1.;
854 brush.face[4].Contents = detail;
855 brush.face[4].Surface = SURF_HINT;
856 brush.face[4].Value = 0;
858 XYZtoV( &v[3],&brush.face[5].v[0] );
859 XYZtoV( &v[7],&brush.face[5].v[1] );
860 XYZtoV( &v[4],&brush.face[5].v[2] );
861 strcpy( brush.face[5].texture,hint );
862 brush.face[5].Shift[0] = 0.;
863 brush.face[5].Shift[1] = 0.;
864 brush.face[5].Rotate = 0.;
865 brush.face[5].Scale[0] = 1.;
866 brush.face[5].Scale[1] = 1.;
867 brush.face[5].Contents = detail;
868 brush.face[5].Surface = SURF_HINT;
869 brush.face[5].Value = 0;
878 // these brush parameters never change
880 for ( i = 0; i < 6; i++ )
882 strcpy( brush.face[i].texture,hint );
883 brush.face[i].Shift[0] = 0.;
884 brush.face[i].Shift[1] = 0.;
885 brush.face[i].Rotate = 0.;
886 brush.face[i].Scale[0] = 1.;
887 brush.face[i].Scale[1] = 1.;
888 brush.face[i].Contents = 0;
889 brush.face[i].Surface = SURF_HINT;
890 brush.face[i].Value = 0;
892 for ( i = 0; i < NH; i++ )
894 for ( j = 0; j < NV; j++ )
896 for ( k = 0; k < 2; k++ )
899 if ( ( i + j ) % 2 ) {
900 VectorCopy( xyz[i ][j ].p, v[0].p );
906 VectorCopy( xyz[i + 1][j ].p, v[1].p );
907 VectorCopy( xyz[i + 1][j + 1].p, v[2].p );
910 VectorCopy( xyz[i + 1][j + 1].p, v[1].p );
911 VectorCopy( xyz[i + 1][j ].p, v[2].p );
916 VectorCopy( xyz[i ][j ].p, v[0].p );
922 VectorCopy( xyz[i + 1][j ].p, v[1].p );
923 VectorCopy( xyz[i ][j + 1].p, v[2].p );
926 VectorCopy( xyz[i ][j + 1].p, v[1].p );
927 VectorCopy( xyz[i + 1][j ].p, v[2].p );
933 if ( ( i + j ) % 2 ) {
934 VectorCopy( xyz[i ][j + 1].p,v[0].p );
940 VectorCopy( xyz[i ][j ].p,v[1].p );
941 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
944 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
945 VectorCopy( xyz[i ][j ].p,v[2].p );
950 VectorCopy( xyz[i ][j + 1].p,v[0].p );
956 VectorCopy( xyz[i + 1][j ].p,v[1].p );
957 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
960 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
961 VectorCopy( xyz[i + 1][j ].p,v[2].p );
965 VectorCopy( v[0].p,v[3].p );
966 VectorCopy( v[1].p,v[4].p );
967 VectorCopy( v[2].p,v[5].p );
971 v[0].p[2] += HINT_OFFSET;
972 v[1].p[2] += HINT_OFFSET;
973 v[2].p[2] += HINT_OFFSET;
974 // v[3].p[2] = backface;
975 // v[4].p[2] = backface;
976 // v[5].p[2] = backface;
979 v[0].p[2] -= HINT_OFFSET;
980 v[1].p[2] -= HINT_OFFSET;
981 v[2].p[2] -= HINT_OFFSET;
982 // v[3].p[2] = backface;
983 // v[4].p[2] = backface;
984 // v[5].p[2] = backface;
987 // v[0].p[1] = backface;
988 // v[1].p[1] = backface;
989 // v[2].p[1] = backface;
990 v[3].p[1] += HINT_OFFSET;
991 v[4].p[1] += HINT_OFFSET;
992 v[5].p[1] += HINT_OFFSET;
995 // v[0].p[1] = backface;
996 // v[1].p[1] = backface;
997 // v[2].p[1] = backface;
998 v[3].p[1] -= HINT_OFFSET;
999 v[4].p[1] -= HINT_OFFSET;
1000 v[5].p[1] -= HINT_OFFSET;
1003 v[0].p[0] += HINT_OFFSET;
1004 v[1].p[0] += HINT_OFFSET;
1005 v[2].p[0] += HINT_OFFSET;
1006 // v[3].p[0] = backface;
1007 // v[4].p[0] = backface;
1008 // v[5].p[0] = backface;
1011 v[0].p[0] -= HINT_OFFSET;
1012 v[1].p[0] -= HINT_OFFSET;
1013 v[2].p[0] -= HINT_OFFSET;
1014 // v[3].p[0] = backface;
1015 // v[4].p[0] = backface;
1016 // v[5].p[0] = backface;
1020 XYZtoV( &v[0],&brush.face[0].v[0] );
1021 XYZtoV( &v[3],&brush.face[0].v[1] );
1022 XYZtoV( &v[4],&brush.face[0].v[2] );
1024 XYZtoV( &v[1],&brush.face[1].v[0] );
1025 XYZtoV( &v[4],&brush.face[1].v[1] );
1026 XYZtoV( &v[5],&brush.face[1].v[2] );
1028 XYZtoV( &v[2],&brush.face[2].v[0] );
1029 XYZtoV( &v[5],&brush.face[2].v[1] );
1030 XYZtoV( &v[3],&brush.face[2].v[2] );
1032 XYZtoV( &v[3],&brush.face[3].v[0] );
1033 XYZtoV( &v[5],&brush.face[3].v[1] );
1034 XYZtoV( &v[4],&brush.face[3].v[2] );
1036 XYZtoV( &v[0],&brush.face[4].v[0] );
1037 XYZtoV( &v[1],&brush.face[4].v[1] );
1038 XYZtoV( &v[2],&brush.face[4].v[2] );
1040 MakeBrush( &brush );
1045 } // endif AddHints==1
1051 //=============================================================
1053 extern void MapOut( int,int,NODE *,TRI * );
1054 extern bool SingleBrushSelected;
1057 if ( !ValidSurface() ) {
1065 if ( Game == QUAKE3 && UsePatches != 0 ) {
1069 if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) {
1070 MapOut( gNumNodes,gNumTris,gNode,gTri );
1075 // HL doesn't have detail property
1076 if ( ( Game != HALFLIFE ) && UseDetail ) {
1077 contents += CONTENTS_DETAIL;
1079 // HL and Q3 don't have ladder property
1080 if ( ( Game != HALFLIFE && Game != QUAKE3 ) && UseLadder ) {
1081 contents += CONTENTS_LADDER;
1083 // Genesis requires solid property to be set explicitly
1084 if ( Game == GENESIS3D ) {
1085 contents |= CONTENTS_SOLID;
1087 // Heretic 2 uses different sounds (in surface props) for different texture types
1088 if ( Game == HERETIC2 ) {
1089 surface[0] = GetDefSurfaceProps( Texture[Game][0] );
1090 surface[1] = GetDefSurfaceProps( Texture[Game][1] );
1091 surface[2] = GetDefSurfaceProps( Texture[Game][2] );
1099 if ( Game != QUAKE3 || UsePatches == 0 ) {
1104 ghCursorCurrent = ghCursorDefault;
1105 SetCursor(ghCursorCurrent);
1109 //=============================================================
1111 extern void MakeDecimatedMap( int *, int *, NODE * *, TRI * * );
1116 double delta, dr, rate;
1117 double range, maxrange;
1126 if ( !ValidSurface() ) {
1131 srand( RandomSeed );
1133 dh = ( Hur - Hll ) / NH;
1134 dv = ( Vur - Vll ) / NV;
1137 for ( i = 0; i <= NH; i++ )
1139 for ( j = 0; j <= NV; j++ )
1145 xyz[i][j].p[0] = Hll + i * dh;
1146 xyz[i][j].p[2] = Vll + j * dv;
1150 xyz[i][j].p[1] = Hll + i * dh;
1151 xyz[i][j].p[2] = Vll + j * dv;
1154 xyz[i][j].p[0] = Hll + i * dh;
1155 xyz[i][j].p[1] = Vll + j * dv;
1160 if ( WaveType == WAVE_BITMAP ) {
1161 GenerateBitmapMapping();
1164 else if(WaveType == WAVE_FORMULA)
1169 // Initialize Z values using bilinear interpolation
1170 for ( i = 0; i <= NH; i++ )
1172 zl = Z00 + i * ( Z10 - Z00 ) / NH;
1173 zu = Z01 + i * ( Z11 - Z01 ) / NH;
1178 for ( j = 0; j <= NV; j++ )
1179 xyz[i][j].p[1] = zl + j * ( zu - zl ) / NV;
1183 for ( j = 0; j <= NV; j++ )
1184 xyz[i][j].p[0] = zl + j * ( zu - zl ) / NV;
1187 for ( j = 0; j <= NV; j++ )
1188 xyz[i][j].p[2] = zl + j * ( zu - zl ) / NV;
1197 NHalfcycles = (int)( ( Hur - Hll ) / ( WaveLength / 2. ) );
1198 NHalfcycles = max( NHalfcycles,1 );
1199 wh = 2. * ( Hur - Hll ) / NHalfcycles;
1200 NHalfcycles = (int)( ( Vur - Vll ) / ( WaveLength / 2. ) );
1201 wv = 2. * ( Vur - Vll ) / NHalfcycles;
1202 NHalfcycles = max( NHalfcycles,1 );
1218 for ( i = i0; i <= i1; i++ )
1221 ha = ( ( h - Hll ) / wh ) * 2. * PI - PI / 2.;
1222 for ( j = j0; j <= j1; j++ )
1225 va = ( ( v - Vll ) / wv ) * 2. * PI;
1226 a = Amplitude * cos( ha ) * sin( va );
1230 xyz[i][j].p[2] -= a;
1233 xyz[i][j].p[1] += a;
1236 xyz[i][j].p[1] -= a;
1239 xyz[i][j].p[0] += a;
1242 xyz[i][j].p[0] -= a;
1245 xyz[i][j].p[2] += a;
1250 case WAVE_HCYLINDER:
1251 for ( i = 0; i <= NH; i++ )
1254 ha = ( ( h - Hll ) / WaveLength ) * 2. * PI - PI / 2.;
1255 for ( j = 0; j <= NV; j++ )
1257 a = Amplitude * cos( ha );
1261 xyz[i][j].p[2] -= a;
1264 xyz[i][j].p[1] += a;
1267 xyz[i][j].p[1] -= a;
1270 xyz[i][j].p[0] += a;
1273 xyz[i][j].p[0] -= a;
1276 xyz[i][j].p[2] += a;
1281 case WAVE_VCYLINDER:
1282 for ( i = 0; i <= NH; i++ )
1285 for ( j = 0; j <= NV; j++ )
1288 va = ( ( v - Vll ) / WaveLength ) * 2. * PI;
1289 a = Amplitude * sin( va );
1293 xyz[i][j].p[2] -= a;
1296 xyz[i][j].p[1] += a;
1299 xyz[i][j].p[1] -= a;
1302 xyz[i][j].p[0] += a;
1305 xyz[i][j].p[0] -= a;
1308 xyz[i][j].p[2] += a;
1313 case WAVE_ROUGH_ONLY:
1318 if ( WaveType != WAVE_ROUGH_ONLY ) {
1320 for ( i = 0; i <= NH; i++ )
1322 for ( j = 0; j <= NV; j++ )
1324 if ( xyz[i][j].fixed ) {
1329 xyz[i][j].p[1] = xyz[i][j].fixed_value;
1333 xyz[i][j].p[0] = xyz[i][j].fixed_value;
1336 xyz[i][j].p[2] = xyz[i][j].fixed_value;
1339 if ( xyz[i][j].range > 0 ) {
1340 maxrange = pow( xyz[i][j].range,2 ); // so we don't have to do sqrt's
1341 i0 = i - (int)( floor( xyz[i][j].range / dh - 0.5 ) + 1 );
1343 j0 = j - (int)( floor( xyz[i][j].range / dv - 0.5 ) + 1 );
1347 i1 = min( i1,NH - 1 );
1349 j1 = min( j1,NV - 1 );
1358 for ( ii = i0; ii <= i1; ii++ )
1360 for ( jj = j0; jj <= j1; jj++ )
1362 if ( ii == i && jj == j ) {
1365 range = pow( dh * ( i - ii ), 2 ) + pow( dv * ( j - jj ), 2 );
1366 if ( range > maxrange ) {
1369 dr = sqrt( range / maxrange );
1370 rate = max( -30.,min( xyz[i][j].rate,30. ) );
1372 delta = pow( ( 1. - dr ),-rate + 1. );
1374 else if ( rate < 0. ) {
1375 delta = ( 1 + rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) -
1376 rate*pow( ( 1. - dr ),2 );
1378 else if ( rate == 0. ) {
1379 delta = 0.5 * ( cos( dr * PI ) + 1.0 );
1381 else if ( rate <= 1. ) {
1382 delta = ( 1. - rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) +
1383 rate * ( 1. - pow( dr,2 ) );
1387 delta = 1. - pow( dr,rate + 1 );
1393 xyz[ii][jj].p[1] += ( xyz[i][j].p[1] - xyz[ii][jj].p[1] ) * delta;
1397 xyz[ii][jj].p[0] += ( xyz[i][j].p[0] - xyz[ii][jj].p[0] ) * delta;
1400 xyz[ii][jj].p[2] += ( xyz[i][j].p[2] - xyz[ii][jj].p[2] ) * delta;
1410 if ( ( Roughness > 0. ) && ( WaveType != WAVE_ROUGH_ONLY ) ) {
1411 for ( i = 0; i <= NH; i++ )
1413 for ( j = 0; j <= NV; j++ )
1415 if ( CanEdit( i,j ) && !xyz[i][j].fixed ) {
1420 xyz[i][j].p[1] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1424 xyz[i][j].p[0] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1427 xyz[i][j].p[2] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1431 r = rand(); // We still get a random number, so that fixing points
1433 // doesn't change the sequence.
1439 for ( i = 0; i <= NH; i++ )
1441 for ( j = 0; j <= NV; j++ )
1443 for ( k = 0; k < 3; k++ )
1445 xyz[i][j].p[k] = Nearest( xyz[i][j].p[k],2.0 );
1450 // Find minima and maxima
1459 ymin = xyz[0][0].p[1];
1461 for ( i = 0; i <= NH; i++ )
1463 for ( j = 0; j <= NV; j++ )
1465 ymin = min( ymin,xyz[i][j].p[1] );
1466 ymax = max( ymax,xyz[i][j].p[1] );
1476 xmin = xyz[0][0].p[0];
1478 for ( i = 0; i <= NH; i++ )
1480 for ( j = 0; j <= NV; j++ )
1482 xmin = min( xmin,xyz[i][j].p[0] );
1483 xmax = max( xmax,xyz[i][j].p[0] );
1493 zmin = xyz[0][0].p[2];
1495 for ( i = 0; i <= NH; i++ )
1497 for ( j = 0; j <= NV; j++ )
1499 zmin = min( zmin,xyz[i][j].p[2] );
1500 zmax = max( zmax,xyz[i][j].p[2] );
1505 xmin = Nearest( xmin,2. );
1506 xmax = Nearest( xmax,2. );
1507 ymin = Nearest( ymin,2. );
1508 ymax = Nearest( ymax,2. );
1509 zmin = Nearest( zmin,2. );
1510 zmax = Nearest( zmax,2. );
1515 backface = AtLeast( zmax + 32.,32. );
1518 backface = NoMoreThan( ymin - 32.,32. );
1521 backface = AtLeast( ymax + 32.,32. );
1524 backface = NoMoreThan( xmin - 32.,32. );
1527 backface = AtLeast( xmax + 32.,32. );
1530 backface = NoMoreThan( zmin - 32.,32. );
1536 gNode = (NODE *)NULL;
1539 if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) {
1540 MakeDecimatedMap( &gNumNodes,&gNumTris,&gNode,&gTri );
1544 gNumNodes = ( NH + 1 ) * ( NV + 1 );
1545 gNumTris = NH * NV * 2;
1546 gNode = (NODE *) malloc( gNumNodes * sizeof( NODE ) );
1547 gTri = (TRI *) malloc( gNumTris * sizeof( TRI ) );
1549 for ( i = 0,N = 0; i <= NH; i++ )
1551 for ( j = 0; j <= NV; j++, N++ )
1554 gNode[N].p[0] = (float)xyz[i][j].p[0];
1555 gNode[N].p[1] = (float)xyz[i][j].p[1];
1556 gNode[N].p[2] = (float)xyz[i][j].p[2];
1560 for ( i = 0; i < NH; i++ )
1562 for ( j = 0; j < NV; j++ )
1564 k = i * NV * 2 + j * 2;
1565 if ( ( i + j ) % 2 ) {
1571 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1572 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1573 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j;
1574 gTri[k + 1].v[0] = i * ( NV + 1 ) + j;
1575 gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1;
1576 gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1579 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1580 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j;
1581 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1582 gTri[k + 1].v[0] = i * ( NV + 1 ) + j;
1583 gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1584 gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1;
1594 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1595 gTri[k ].v[1] = i * ( NV + 1 ) + j + 1;
1596 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j;
1597 gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j;
1598 gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1;
1599 gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1602 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1603 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j;
1604 gTri[k ].v[2] = i * ( NV + 1 ) + j + 1;
1605 gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j;
1606 gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1607 gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1;
1614 sprintf(CSV,"csv%03d.csv",Decimate);
1616 for(i=0; i<gNumNodes; i++)
1619 fprintf(f,"%g,%g,%g\n",gNode[i].p[0],gNode[i].p[1],gNode[i].p[2]);
1623 for ( i = 0; i < gNumTris; i++ )
1624 PlaneFromPoints( gNode[gTri[i].v[0]].p,
1625 gNode[gTri[i].v[1]].p,
1626 gNode[gTri[i].v[2]].p,
1629 // Hydra: snap-to-grid begin
1630 if ( SnapToGrid > 0 ) {
1631 for ( i = 0; i < NH; i++ )
1633 for ( j = 0; j < NV; j++ )
1639 xyz[i][j].p[1] = CalculateSnapValue( xyz[i][j].p[1] );
1643 xyz[i][j].p[0] = CalculateSnapValue( xyz[i][j].p[0] );
1646 xyz[i][j].p[2] = CalculateSnapValue( xyz[i][j].p[2] );
1651 // Hydra: snap-to-grid end
1653 //=============================================================
1654 double Nearest( double x, double dx ){
1657 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1658 if ( fabs( xx ) < dx / 2 ) {
1663 //=============================================================
1664 double NoMoreThan( double x, double dx ){
1667 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1673 //=============================================================
1674 double AtLeast( double x, double dx ){
1677 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1683 //=============================================================
1684 double LessThan( double x,double dx ){
1687 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1693 //=============================================================
1694 double MoreThan( double x,double dx ){
1697 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1702 //=============================================================
1703 void SubdividePlasma( int i0,int j0,int i1,int j1 ){
1706 double r; // NOTE: This is used to keep the random number sequence the same
1707 // when we fix a point. If we did NOT do this, then simply
1708 // fixing a point at its current value would change the entire
1711 i = ( i0 + i1 ) / 2;
1712 j = ( j0 + j1 ) / 2;
1713 if ( i1 > i0 + 1 ) {
1714 if ( !xyz[i][j0].done ) {
1715 xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] +
1716 ( xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) +
1717 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1718 xyz[i][j0].done = 1;
1723 if ( ( j1 > j0 ) && ( !xyz[i][j1].done ) ) {
1724 xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] +
1725 ( xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) +
1726 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1727 xyz[i][j1].done = 1;
1733 if ( j1 > j0 + 1 ) {
1734 if ( !xyz[i0][j].done ) {
1735 xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] +
1736 ( xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) +
1737 ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1738 xyz[i0][j].done = 1;
1743 if ( ( i1 > i0 ) && ( !xyz[i1][j].done ) ) {
1744 xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] +
1745 ( xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) +
1746 ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1747 xyz[i1][j].done = 1;
1753 if ( ( i1 > i0 + 1 ) && ( j1 > j0 + 1 ) ) {
1754 if ( !xyz[i][j].done ) {
1755 z1 = xyz[i0][j].pp[2] +
1756 ( xyz[i1][j].pp[2] - xyz[i0][j].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 );
1757 z2 = xyz[i][j0].pp[2] +
1758 ( xyz[i][j1].pp[2] - xyz[i][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 );
1759 xyz[i][j].pp[2] = ( z1 + z2 ) / 2. +
1760 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1767 if ( i > i0 + 1 || j > j0 + 1 ) {
1768 SubdividePlasma( i0,j0,i,j );
1770 if ( i1 > i + 1 || j > j0 + 1 ) {
1771 SubdividePlasma( i,j0,i1,j );
1773 if ( i > i0 + 1 || j1 > j0 + 1 ) {
1774 SubdividePlasma( i0,j,i,j1 );
1776 if ( i1 > i + 1 || j1 > j0 + 1 ) {
1777 SubdividePlasma( i,j,i1,j1 );
1780 //==================================================================================
1783 /* use pp[2] values until done to avoid messing with a bunch of
1784 switch statements */
1786 for ( i = 0; i <= NH; i++ )
1788 for ( j = 0; j <= NV; j++ )
1790 if ( FixedPoint( i,j ) ) {
1803 for ( i = 0; i <= NH; i++ )
1805 for ( j = 0; j <= NV; j++ )
1807 if ( xyz[i][j].fixed ) {
1808 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1811 xyz[i][j].pp[2] = xyz[i][j].p[1];
1818 for ( i = 0; i <= NH; i++ )
1820 for ( j = 0; j <= NV; j++ )
1822 if ( xyz[i][j].fixed ) {
1823 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1826 xyz[i][j].pp[2] = xyz[i][j].p[0];
1832 for ( i = 0; i <= NH; i++ )
1834 for ( j = 0; j <= NV; j++ )
1836 if ( xyz[i][j].fixed ) {
1837 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1840 xyz[i][j].pp[2] = xyz[i][j].p[2];
1846 SubdividePlasma( 0,0,NH,NV );
1851 for ( i = 0; i <= NH; i++ )
1853 for ( j = 0; j <= NV; j++ )
1855 xyz[i][j].p[1] = xyz[i][j].pp[2];
1861 for ( i = 0; i <= NH; i++ )
1863 for ( j = 0; j <= NV; j++ )
1865 xyz[i][j].p[0] = xyz[i][j].pp[2];
1870 for ( i = 0; i <= NH; i++ )
1872 for ( j = 0; j <= NV; j++ )
1874 xyz[i][j].p[2] = xyz[i][j].pp[2];
1880 //===========================================================================
1881 bool FixedPoint( int i, int j ){
1882 if ( xyz[i][j].fixed ) {
1885 return !CanEdit( i,j );
1887 //===========================================================================
1888 bool CanEdit( int i, int j ){
1889 if ( FixBorders && ( ( WaveType == WAVE_COS_SIN ) || ( WaveType == WAVE_ROUGH_ONLY ) ) ) {
1903 if ( i == 0 && j == 0 ) {
1906 if ( i == NH && j == 0 ) {
1909 if ( i == 0 && j == NV ) {
1912 if ( i == NH && j == NV ) {
1917 /*============================================================================
1919 Determines which triangle in the gTri array bounds the input point. Doesn't
1920 do anything special with border points.
1922 int TriangleFromPoint( double x, double y ){
1929 for ( j = 0, tri = -1; j < gNumTris && tri == -1; j++ )
1932 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1],
1933 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1] ) < 0. ) {
1937 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1],
1938 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1] ) < 0. ) {
1942 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1],
1943 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1] ) < 0. ) {
1951 /*============================================================================
1953 Determines minimum height to place the player start such that he doesn't
1954 intersect any surface brushes.
1956 int PlayerStartZ( double x, double y ){
1964 t[0] = TriangleFromPoint( x,y );
1965 t[1] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[0] );
1966 t[2] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[1] );
1967 t[3] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[0] );
1968 t[4] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[1] );
1970 for ( k = 0; k < 5; k++ )
1972 zt = ( gTri[t[k]].plane.dist -
1973 gTri[t[k]].plane.normal[0] * x -
1974 gTri[t[k]].plane.normal[1] * y ) /
1975 gTri[t[k]].plane.normal[2];
1978 return (int)( AtLeast( z,2. ) - PlayerBox[Game].z[0] );
1980 //=============================================================
1981 void XYZtoV( XYZ *xyz, vec3 *v ){
1982 v[0][0] = (vec)Nearest( xyz->p[0],2. );
1983 v[0][1] = (vec)Nearest( xyz->p[1],2. );
1984 v[0][2] = (vec)Nearest( xyz->p[2],2. );
1987 //=============================================================
1988 scene::Node* MakePatch( void ){
1989 scene::Node* patch = Patch_AllocNode();
1990 Node_getTraversable( h_worldspawn )->insert( patch );
1994 //=============================================================
1995 void MakeBrush( BRUSH *brush ){
1996 NodePtr node( Brush_AllocNode() );
1997 Node_getTraversable( h_func_group )->insert( node );
1999 //=============================================================
2000 void OpenFuncGroup(){
2001 h_func_group = GlobalEntityCreator().createEntity( "func_group" );
2002 h_func_group->IncRef();
2003 if ( AddTerrainKey ) {
2004 h_func_group->m_entity->setkeyvalue( "terrain", "1" );
2007 //=============================================================
2008 void CloseFuncGroup(){
2009 h_func_group->DecRef();
2010 if ( g_FuncTable.m_pfnSysUpdateWindows != NULL ) {
2011 g_FuncTable.m_pfnSysUpdateWindows( W_ALL );