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();
253 b->pPatch->setDims( NH_patch, NV_patch );
254 for ( i = 0; i < NH_patch; i++ )
261 ii = i0 + NH_patch - 1 - i;
266 for ( j = 0; j < NV_patch; j++ )
268 b->pPatch->ctrlAt( COL,i,j )[0] = (float)xyz[ii][j0 + j].pp[0];
269 b->pPatch->ctrlAt( COL,i,j )[1] = (float)xyz[ii][j0 + j].pp[1];
270 b->pPatch->ctrlAt( COL,i,j )[2] = (float)xyz[ii][j0 + j].pp[2];
271 b->pPatch->ctrlAt( COL,i,j )[3] = (float)i;
272 b->pPatch->ctrlAt( COL,i,j )[4] = (float)j;
275 b->pPatch->UpdateCachedData();
285 //=============================================================
294 vec3_t PlaneNormal,SurfNormal;
302 strcpy( surftext,Texture[Game][0] );
303 strcpy( sidetext,( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
304 strcpy( surftext2,( strlen( Texture[Game][2] ) ? Texture[Game][2] : Texture[Game][0] ) );
306 // if surftext2 is identical to surftext, there's no need to
307 // check surface angle
308 if ( !g_strcasecmp( surftext,surftext2 ) ) {
314 Steep = (float)cos( (double)SlantAngle / 57.2957795 );
317 case PLANE_XY0: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
318 case PLANE_XY1: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = -1.; break;
319 case PLANE_XZ0: PlaneNormal[0] = 0.; PlaneNormal[1] = 1.; PlaneNormal[2] = 1.; break;
320 case PLANE_XZ1: PlaneNormal[0] = 0.; PlaneNormal[1] = -1.; PlaneNormal[2] = 1.; break;
321 case PLANE_YZ0: PlaneNormal[0] = 1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
322 case PLANE_YZ1: PlaneNormal[0] = -1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
328 for ( i = 0; i < NH; i++ )
330 for ( j = 0; j < NV; j++ )
332 if ( ( i + j ) % 2 ) {
333 VectorCopy( xyz[i ][j ].p, v[0].p );
339 VectorCopy( xyz[i + 1][j ].p, v[1].p );
340 VectorCopy( xyz[i + 1][j + 1].p, v[2].p );
343 VectorCopy( xyz[i + 1][j + 1].p, v[1].p );
344 VectorCopy( xyz[i + 1][j ].p, v[2].p );
349 VectorCopy( xyz[i ][j ].p, v[0].p );
355 VectorCopy( xyz[i + 1][j ].p, v[1].p );
356 VectorCopy( xyz[i ][j + 1].p, v[2].p );
359 VectorCopy( xyz[i ][j + 1].p, v[1].p );
360 VectorCopy( xyz[i + 1][j ].p, v[2].p );
363 VectorCopy( v[0].p,v[3].p );
364 VectorCopy( v[1].p,v[4].p );
365 VectorCopy( v[2].p,v[5].p );
370 v[0].p[1] = backface;
371 v[1].p[1] = backface;
372 v[2].p[1] = backface;
376 v[3].p[0] = backface;
377 v[4].p[0] = backface;
378 v[5].p[0] = backface;
381 v[3].p[2] = backface;
382 v[4].p[2] = backface;
383 v[5].p[2] = backface;
386 brush.Number = i * NV * 2 + j * 2;
388 XYZtoV( &v[0],&brush.face[0].v[0] );
389 XYZtoV( &v[3],&brush.face[0].v[1] );
390 XYZtoV( &v[4],&brush.face[0].v[2] );
391 strcpy( brush.face[0].texture,
392 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
393 brush.face[0].Shift[0] = (float)TexOffset[0];
394 brush.face[0].Shift[1] = (float)TexOffset[1];
395 brush.face[0].Rotate = 0.;
396 brush.face[0].Scale[0] = (float)TexScale[0];
397 brush.face[0].Scale[1] = (float)TexScale[1];
398 brush.face[0].Contents = contents;
399 brush.face[0].Surface = surface[1];
400 brush.face[0].Value = 0;
402 XYZtoV( &v[1],&brush.face[1].v[0] );
403 XYZtoV( &v[4],&brush.face[1].v[1] );
404 XYZtoV( &v[5],&brush.face[1].v[2] );
405 strcpy( brush.face[1].texture,
406 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
407 brush.face[1].Shift[0] = (float)TexOffset[0];
408 brush.face[1].Shift[1] = (float)TexOffset[1];
409 brush.face[1].Rotate = 0.;
410 brush.face[1].Scale[0] = (float)TexScale[0];
411 brush.face[1].Scale[1] = (float)TexScale[1];
412 brush.face[1].Contents = contents;
413 brush.face[1].Surface = surface[1];
414 brush.face[1].Value = 0;
416 XYZtoV( &v[2],&brush.face[2].v[0] );
417 XYZtoV( &v[5],&brush.face[2].v[1] );
418 XYZtoV( &v[3],&brush.face[2].v[2] );
419 strcpy( brush.face[2].texture,
420 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
421 brush.face[2].Shift[0] = (float)TexOffset[0];
422 brush.face[2].Shift[1] = (float)TexOffset[1];
423 brush.face[2].Rotate = 0.;
424 brush.face[2].Scale[0] = (float)TexScale[0];
425 brush.face[2].Scale[1] = (float)TexScale[1];
426 brush.face[2].Contents = contents;
427 brush.face[2].Surface = surface[1];
428 brush.face[2].Value = 0;
430 if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) {
431 XYZVectorSubtract( v[4].p,v[3].p,t[0] );
432 XYZVectorSubtract( v[5].p,v[4].p,t[1] );
433 CrossProduct( t[0],t[1],SurfNormal );
434 VectorNormalize( SurfNormal,SurfNormal );
435 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
436 strcpy( surft,surftext2 );
441 strcpy( surft,surftext );
447 strcpy( surft,surftext );
451 XYZtoV( &v[3],&brush.face[3].v[0] );
452 XYZtoV( &v[5],&brush.face[3].v[1] );
453 XYZtoV( &v[4],&brush.face[3].v[2] );
454 strcpy( brush.face[3].texture,
455 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) );
456 brush.face[3].Shift[0] = (float)TexOffset[0];
457 brush.face[3].Shift[1] = (float)TexOffset[1];
458 brush.face[3].Rotate = 0.;
459 brush.face[3].Scale[0] = (float)TexScale[0];
460 brush.face[3].Scale[1] = (float)TexScale[1];
461 brush.face[3].Contents = contents;
462 brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] );
463 brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 );
465 if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) {
466 XYZVectorSubtract( v[2].p,v[0].p,t[0] );
467 XYZVectorSubtract( v[1].p,v[2].p,t[1] );
468 CrossProduct( t[0],t[1],SurfNormal );
469 VectorNormalize( SurfNormal,SurfNormal );
470 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
471 strcpy( surft,surftext2 );
476 strcpy( surft,surftext );
482 strcpy( surft,surftext );
486 XYZtoV( &v[0],&brush.face[4].v[0] );
487 XYZtoV( &v[1],&brush.face[4].v[1] );
488 XYZtoV( &v[2],&brush.face[4].v[2] );
489 strcpy( brush.face[4].texture,
490 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) );
491 brush.face[4].Shift[0] = (float)TexOffset[0];
492 brush.face[4].Shift[1] = (float)TexOffset[1];
493 brush.face[4].Rotate = 0.;
494 brush.face[4].Scale[0] = (float)TexScale[0];
495 brush.face[4].Scale[1] = (float)TexScale[1];
496 brush.face[4].Contents = contents;
497 brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf );
498 brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 );
501 if ( ( i + j ) % 2 ) {
502 VectorCopy( xyz[i ][j + 1].p,v[0].p );
508 VectorCopy( xyz[i ][j ].p,v[1].p );
509 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
512 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
513 VectorCopy( xyz[i ][j ].p,v[2].p );
518 VectorCopy( xyz[i ][j + 1].p,v[0].p );
524 VectorCopy( xyz[i + 1][j ].p,v[1].p );
525 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
528 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
529 VectorCopy( xyz[i + 1][j ].p,v[2].p );
532 VectorCopy( v[0].p,v[3].p );
533 VectorCopy( v[1].p,v[4].p );
534 VectorCopy( v[2].p,v[5].p );
539 v[0].p[1] = backface;
540 v[1].p[1] = backface;
541 v[2].p[1] = backface;
545 v[3].p[0] = backface;
546 v[4].p[0] = backface;
547 v[5].p[0] = backface;
550 v[3].p[2] = backface;
551 v[4].p[2] = backface;
552 v[5].p[2] = backface;
554 brush.Number = i * NV * 2 + j * 2 + 1;
556 XYZtoV( &v[0],&brush.face[0].v[0] );
557 XYZtoV( &v[3],&brush.face[0].v[1] );
558 XYZtoV( &v[4],&brush.face[0].v[2] );
559 strcpy( brush.face[0].texture,
560 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
561 brush.face[0].Shift[0] = (float)TexOffset[0];
562 brush.face[0].Shift[1] = (float)TexOffset[1];
563 brush.face[0].Rotate = 0.;
564 brush.face[0].Scale[0] = (float)TexScale[0];
565 brush.face[0].Scale[1] = (float)TexScale[1];
566 brush.face[0].Contents = contents;
567 brush.face[0].Surface = surface[1];
568 brush.face[0].Value = 0;
570 XYZtoV( &v[1],&brush.face[1].v[0] );
571 XYZtoV( &v[4],&brush.face[1].v[1] );
572 XYZtoV( &v[5],&brush.face[1].v[2] );
573 strcpy( brush.face[1].texture,
574 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
575 brush.face[1].Shift[0] = (float)TexOffset[0];
576 brush.face[1].Shift[1] = (float)TexOffset[1];
577 brush.face[1].Rotate = 0.;
578 brush.face[1].Scale[0] = (float)TexScale[0];
579 brush.face[1].Scale[1] = (float)TexScale[1];
580 brush.face[1].Contents = contents;
581 brush.face[1].Surface = surface[1];
582 brush.face[1].Value = 0;
584 XYZtoV( &v[2],&brush.face[2].v[0] );
585 XYZtoV( &v[5],&brush.face[2].v[1] );
586 XYZtoV( &v[3],&brush.face[2].v[2] );
587 strcpy( brush.face[2].texture,
588 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
589 brush.face[2].Shift[0] = (float)TexOffset[0];
590 brush.face[2].Shift[1] = (float)TexOffset[1];
591 brush.face[2].Rotate = 0.;
592 brush.face[2].Scale[0] = (float)TexScale[0];
593 brush.face[2].Scale[1] = (float)TexScale[1];
594 brush.face[2].Contents = contents;
595 brush.face[2].Surface = surface[1];
596 brush.face[2].Value = 0;
598 if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) {
599 XYZVectorSubtract( v[4].p,v[3].p,t[0] );
600 XYZVectorSubtract( v[5].p,v[4].p,t[1] );
601 CrossProduct( t[0],t[1],SurfNormal );
602 VectorNormalize( SurfNormal,SurfNormal );
603 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
604 strcpy( surft,surftext2 );
609 strcpy( surft,surftext );
615 strcpy( surft,surftext );
618 XYZtoV( &v[3],&brush.face[3].v[0] );
619 XYZtoV( &v[5],&brush.face[3].v[1] );
620 XYZtoV( &v[4],&brush.face[3].v[2] );
621 strcpy( brush.face[3].texture,
622 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) );
623 brush.face[3].Shift[0] = (float)TexOffset[0];
624 brush.face[3].Shift[1] = (float)TexOffset[1];
625 brush.face[3].Rotate = 0.;
626 brush.face[3].Scale[0] = (float)TexScale[0];
627 brush.face[3].Scale[1] = (float)TexScale[1];
628 brush.face[3].Contents = contents;
629 brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] );
630 brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 );
632 if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) {
633 XYZVectorSubtract( v[2].p,v[0].p,t[0] );
634 XYZVectorSubtract( v[1].p,v[2].p,t[1] );
635 CrossProduct( t[0],t[1],SurfNormal );
636 VectorNormalize( SurfNormal,SurfNormal );
637 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
638 strcpy( surft,surftext2 );
643 strcpy( surft,surftext );
649 strcpy( surft,surftext );
652 XYZtoV( &v[0],&brush.face[4].v[0] );
653 XYZtoV( &v[1],&brush.face[4].v[1] );
654 XYZtoV( &v[2],&brush.face[4].v[2] );
655 strcpy( brush.face[4].texture,
656 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) );
657 brush.face[4].Shift[0] = (float)TexOffset[0];
658 brush.face[4].Shift[1] = (float)TexOffset[1];
659 brush.face[4].Rotate = 0.;
660 brush.face[4].Scale[0] = (float)TexScale[0];
661 brush.face[4].Scale[1] = (float)TexScale[1];
662 brush.face[4].Contents = contents;
663 brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf );
664 brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 );
671 if ( AddHints || GimpHints ) {
672 int detail, i1, j1, N;
678 strcpy( hint,"HINT" );
679 strcpy( skip,"HINT" );
682 strcpy( hint,"generic/misc/hint" );
683 strcpy( skip,"generic/misc/skip" );
686 strcpy( hint,"general/hint" );
687 strcpy( skip,"general/hint" ); // Heretic2 doesn't have a skip texture
690 strcpy( hint,"common/0_hint" );
691 strcpy( skip,"common/0_skip" );
694 strcpy( hint,"hint" );
695 strcpy( skip,"hint" );
698 strcpy( hint,"textures/common/hint" );
699 strcpy( skip,"textures/common/skip" );
702 strcpy( hint,"e1u1/hint" );
703 strcpy( skip,"e1u1/skip" );
708 if ( AddHints == 1 ) {
709 detail = CONTENTS_DETAIL;
711 for ( i = 0; i < NH; i++ )
715 for ( j = 0; j < NV; j++ )
718 // For detail hint brushes, no need to use a hint brush over
719 // EVERY grid square... it would be redundant. Instead use
720 // a checkerboard pattern
721 if ( ( i + j ) % 2 ) {
727 VectorCopy( xyz[i ][j ].p, v[0].p );
733 VectorCopy( xyz[i1][j ].p, v[1].p );
734 VectorCopy( xyz[i1][j1].p, v[2].p );
735 VectorCopy( xyz[i ][j1].p, v[3].p );
738 VectorCopy( xyz[i ][j1].p, v[1].p );
739 VectorCopy( xyz[i1][j1].p, v[2].p );
740 VectorCopy( xyz[i1][j ].p, v[3].p );
743 VectorCopy( v[0].p,v[4].p );
744 VectorCopy( v[1].p,v[5].p );
745 VectorCopy( v[2].p,v[6].p );
746 VectorCopy( v[3].p,v[7].p );
751 front = LessThan( zmin,32. );
752 v[4].p[2] = backface;
753 v[5].p[2] = backface;
754 v[6].p[2] = backface;
755 v[7].p[2] = backface;
758 front = MoreThan( ymax,32. );
759 v[0].p[1] = backface;
760 v[1].p[1] = backface;
761 v[2].p[1] = backface;
762 v[3].p[1] = backface;
765 front = LessThan( ymin,32. );
766 v[0].p[1] = backface;
767 v[1].p[1] = backface;
768 v[2].p[1] = backface;
769 v[3].p[1] = backface;
772 front = MoreThan( xmax,32. );
773 v[4].p[0] = backface;
774 v[5].p[0] = backface;
775 v[6].p[0] = backface;
776 v[7].p[0] = backface;
779 front = LessThan( xmin,32. );
780 v[4].p[0] = backface;
781 v[5].p[0] = backface;
782 v[6].p[0] = backface;
783 v[7].p[0] = backface;
786 front = MoreThan( zmax,32. );
787 v[4].p[2] = backface;
788 v[5].p[2] = backface;
789 v[6].p[2] = backface;
790 v[7].p[2] = backface;
798 v[5].p[1] = v[4].p[1];
799 v[6].p[1] = v[4].p[1];
800 v[7].p[1] = v[4].p[1];
805 v[1].p[0] = v[0].p[0];
806 v[2].p[0] = v[0].p[0];
807 v[3].p[0] = v[0].p[0];
811 v[1].p[2] = v[0].p[2];
812 v[2].p[2] = v[0].p[2];
813 v[3].p[2] = v[0].p[2];
818 XYZtoV( &v[0],&brush.face[0].v[0] );
819 XYZtoV( &v[1],&brush.face[0].v[1] );
820 XYZtoV( &v[2],&brush.face[0].v[2] );
821 strcpy( brush.face[0].texture,skip );
822 brush.face[0].Shift[0] = 0.;
823 brush.face[0].Shift[1] = 0.;
824 brush.face[0].Rotate = 0.;
825 brush.face[0].Scale[0] = 1.;
826 brush.face[0].Scale[1] = 1.;
827 brush.face[0].Contents = detail;
828 brush.face[0].Surface = SURF_SKIP;
829 brush.face[0].Value = 0;
831 XYZtoV( &v[4],&brush.face[1].v[0] );
832 XYZtoV( &v[7],&brush.face[1].v[1] );
833 XYZtoV( &v[6],&brush.face[1].v[2] );
834 strcpy( brush.face[1].texture,skip );
835 brush.face[1].Shift[0] = 0.;
836 brush.face[1].Shift[1] = 0.;
837 brush.face[1].Rotate = 0.;
838 brush.face[1].Scale[0] = 1.;
839 brush.face[1].Scale[1] = 1.;
840 brush.face[1].Contents = detail;
841 brush.face[1].Surface = SURF_SKIP;
842 brush.face[1].Value = 0;
844 XYZtoV( &v[0],&brush.face[2].v[0] );
845 XYZtoV( &v[4],&brush.face[2].v[1] );
846 XYZtoV( &v[5],&brush.face[2].v[2] );
847 strcpy( brush.face[2].texture,hint );
848 brush.face[2].Shift[0] = 0.;
849 brush.face[2].Shift[1] = 0.;
850 brush.face[2].Rotate = 0.;
851 brush.face[2].Scale[0] = 1.;
852 brush.face[2].Scale[1] = 1.;
853 brush.face[2].Contents = detail;
854 brush.face[2].Surface = SURF_HINT;
855 brush.face[2].Value = 0;
857 XYZtoV( &v[1],&brush.face[3].v[0] );
858 XYZtoV( &v[5],&brush.face[3].v[1] );
859 XYZtoV( &v[6],&brush.face[3].v[2] );
860 strcpy( brush.face[3].texture,hint );
861 brush.face[3].Shift[0] = 0.;
862 brush.face[3].Shift[1] = 0.;
863 brush.face[3].Rotate = 0.;
864 brush.face[3].Scale[0] = 1.;
865 brush.face[3].Scale[1] = 1.;
866 brush.face[3].Contents = detail;
867 brush.face[3].Surface = SURF_HINT;
868 brush.face[3].Value = 0;
870 XYZtoV( &v[2],&brush.face[4].v[0] );
871 XYZtoV( &v[6],&brush.face[4].v[1] );
872 XYZtoV( &v[7],&brush.face[4].v[2] );
873 strcpy( brush.face[4].texture,hint );
874 brush.face[4].Shift[0] = 0.;
875 brush.face[4].Shift[1] = 0.;
876 brush.face[4].Rotate = 0.;
877 brush.face[4].Scale[0] = 1.;
878 brush.face[4].Scale[1] = 1.;
879 brush.face[4].Contents = detail;
880 brush.face[4].Surface = SURF_HINT;
881 brush.face[4].Value = 0;
883 XYZtoV( &v[3],&brush.face[5].v[0] );
884 XYZtoV( &v[7],&brush.face[5].v[1] );
885 XYZtoV( &v[4],&brush.face[5].v[2] );
886 strcpy( brush.face[5].texture,hint );
887 brush.face[5].Shift[0] = 0.;
888 brush.face[5].Shift[1] = 0.;
889 brush.face[5].Rotate = 0.;
890 brush.face[5].Scale[0] = 1.;
891 brush.face[5].Scale[1] = 1.;
892 brush.face[5].Contents = detail;
893 brush.face[5].Surface = SURF_HINT;
894 brush.face[5].Value = 0;
903 // these brush parameters never change
905 for ( i = 0; i < 6; i++ )
907 strcpy( brush.face[i].texture,hint );
908 brush.face[i].Shift[0] = 0.;
909 brush.face[i].Shift[1] = 0.;
910 brush.face[i].Rotate = 0.;
911 brush.face[i].Scale[0] = 1.;
912 brush.face[i].Scale[1] = 1.;
913 brush.face[i].Contents = 0;
914 brush.face[i].Surface = SURF_HINT;
915 brush.face[i].Value = 0;
917 for ( i = 0; i < NH; i++ )
919 for ( j = 0; j < NV; j++ )
921 for ( k = 0; k < 2; k++ )
924 if ( ( i + j ) % 2 ) {
925 VectorCopy( xyz[i ][j ].p, v[0].p );
931 VectorCopy( xyz[i + 1][j ].p, v[1].p );
932 VectorCopy( xyz[i + 1][j + 1].p, v[2].p );
935 VectorCopy( xyz[i + 1][j + 1].p, v[1].p );
936 VectorCopy( xyz[i + 1][j ].p, v[2].p );
941 VectorCopy( xyz[i ][j ].p, v[0].p );
947 VectorCopy( xyz[i + 1][j ].p, v[1].p );
948 VectorCopy( xyz[i ][j + 1].p, v[2].p );
951 VectorCopy( xyz[i ][j + 1].p, v[1].p );
952 VectorCopy( xyz[i + 1][j ].p, v[2].p );
958 if ( ( i + j ) % 2 ) {
959 VectorCopy( xyz[i ][j + 1].p,v[0].p );
965 VectorCopy( xyz[i ][j ].p,v[1].p );
966 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
969 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
970 VectorCopy( xyz[i ][j ].p,v[2].p );
975 VectorCopy( xyz[i ][j + 1].p,v[0].p );
981 VectorCopy( xyz[i + 1][j ].p,v[1].p );
982 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
985 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
986 VectorCopy( xyz[i + 1][j ].p,v[2].p );
990 VectorCopy( v[0].p,v[3].p );
991 VectorCopy( v[1].p,v[4].p );
992 VectorCopy( v[2].p,v[5].p );
996 v[0].p[2] += HINT_OFFSET;
997 v[1].p[2] += HINT_OFFSET;
998 v[2].p[2] += HINT_OFFSET;
999 // v[3].p[2] = backface;
1000 // v[4].p[2] = backface;
1001 // v[5].p[2] = backface;
1004 v[0].p[2] -= HINT_OFFSET;
1005 v[1].p[2] -= HINT_OFFSET;
1006 v[2].p[2] -= HINT_OFFSET;
1007 // v[3].p[2] = backface;
1008 // v[4].p[2] = backface;
1009 // v[5].p[2] = backface;
1012 // v[0].p[1] = backface;
1013 // v[1].p[1] = backface;
1014 // v[2].p[1] = backface;
1015 v[3].p[1] += HINT_OFFSET;
1016 v[4].p[1] += HINT_OFFSET;
1017 v[5].p[1] += HINT_OFFSET;
1020 // v[0].p[1] = backface;
1021 // v[1].p[1] = backface;
1022 // v[2].p[1] = backface;
1023 v[3].p[1] -= HINT_OFFSET;
1024 v[4].p[1] -= HINT_OFFSET;
1025 v[5].p[1] -= HINT_OFFSET;
1028 v[0].p[0] += HINT_OFFSET;
1029 v[1].p[0] += HINT_OFFSET;
1030 v[2].p[0] += HINT_OFFSET;
1031 // v[3].p[0] = backface;
1032 // v[4].p[0] = backface;
1033 // v[5].p[0] = backface;
1036 v[0].p[0] -= HINT_OFFSET;
1037 v[1].p[0] -= HINT_OFFSET;
1038 v[2].p[0] -= HINT_OFFSET;
1039 // v[3].p[0] = backface;
1040 // v[4].p[0] = backface;
1041 // v[5].p[0] = backface;
1045 XYZtoV( &v[0],&brush.face[0].v[0] );
1046 XYZtoV( &v[3],&brush.face[0].v[1] );
1047 XYZtoV( &v[4],&brush.face[0].v[2] );
1049 XYZtoV( &v[1],&brush.face[1].v[0] );
1050 XYZtoV( &v[4],&brush.face[1].v[1] );
1051 XYZtoV( &v[5],&brush.face[1].v[2] );
1053 XYZtoV( &v[2],&brush.face[2].v[0] );
1054 XYZtoV( &v[5],&brush.face[2].v[1] );
1055 XYZtoV( &v[3],&brush.face[2].v[2] );
1057 XYZtoV( &v[3],&brush.face[3].v[0] );
1058 XYZtoV( &v[5],&brush.face[3].v[1] );
1059 XYZtoV( &v[4],&brush.face[3].v[2] );
1061 XYZtoV( &v[0],&brush.face[4].v[0] );
1062 XYZtoV( &v[1],&brush.face[4].v[1] );
1063 XYZtoV( &v[2],&brush.face[4].v[2] );
1065 MakeBrush( &brush );
1070 } // endif AddHints==1
1076 //=============================================================
1078 extern void MapOut( int,int,NODE *,TRI * );
1079 extern bool SingleBrushSelected;
1082 if ( !ValidSurface() ) {
1086 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
1087 SetCursor(ghCursorCurrent);
1090 if ( SingleBrushSelected ) {
1091 g_FuncTable.m_pfnDeleteSelection();
1098 if ( Game == QUAKE3 && UsePatches != 0 ) {
1102 if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) {
1103 MapOut( gNumNodes,gNumTris,gNode,gTri );
1105 ghCursorCurrent = ghCursorDefault;
1106 SetCursor(ghCursorCurrent);
1112 // HL doesn't have detail property
1113 if ( ( Game != HALFLIFE ) && UseDetail ) {
1114 contents += CONTENTS_DETAIL;
1116 // HL and Q3 don't have ladder property
1117 if ( ( Game != HALFLIFE && Game != QUAKE3 ) && UseLadder ) {
1118 contents += CONTENTS_LADDER;
1120 // Genesis requires solid property to be set explicitly
1121 if ( Game == GENESIS3D ) {
1122 contents |= CONTENTS_SOLID;
1124 // Heretic 2 uses different sounds (in surface props) for different texture types
1125 if ( Game == HERETIC2 ) {
1126 surface[0] = GetDefSurfaceProps( Texture[Game][0] );
1127 surface[1] = GetDefSurfaceProps( Texture[Game][1] );
1128 surface[2] = GetDefSurfaceProps( Texture[Game][2] );
1136 if ( Game != QUAKE3 || UsePatches == 0 ) {
1141 ghCursorCurrent = ghCursorDefault;
1142 SetCursor(ghCursorCurrent);
1146 //=============================================================
1148 extern void MakeDecimatedMap( int *, int *, NODE * *, TRI * * );
1153 double delta, dr, rate;
1154 double range, maxrange;
1163 if ( !ValidSurface() ) {
1168 srand( RandomSeed );
1170 dh = ( Hur - Hll ) / NH;
1171 dv = ( Vur - Vll ) / NV;
1174 for ( i = 0; i <= NH; i++ )
1176 for ( j = 0; j <= NV; j++ )
1182 xyz[i][j].p[0] = Hll + i * dh;
1183 xyz[i][j].p[2] = Vll + j * dv;
1187 xyz[i][j].p[1] = Hll + i * dh;
1188 xyz[i][j].p[2] = Vll + j * dv;
1191 xyz[i][j].p[0] = Hll + i * dh;
1192 xyz[i][j].p[1] = Vll + j * dv;
1197 if ( WaveType == WAVE_BITMAP ) {
1198 GenerateBitmapMapping();
1201 else if(WaveType == WAVE_FORMULA)
1206 // Initialize Z values using bilinear interpolation
1207 for ( i = 0; i <= NH; i++ )
1209 zl = Z00 + i * ( Z10 - Z00 ) / NH;
1210 zu = Z01 + i * ( Z11 - Z01 ) / NH;
1215 for ( j = 0; j <= NV; j++ )
1216 xyz[i][j].p[1] = zl + j * ( zu - zl ) / NV;
1220 for ( j = 0; j <= NV; j++ )
1221 xyz[i][j].p[0] = zl + j * ( zu - zl ) / NV;
1224 for ( j = 0; j <= NV; j++ )
1225 xyz[i][j].p[2] = zl + j * ( zu - zl ) / NV;
1234 NHalfcycles = (int)( ( Hur - Hll ) / ( WaveLength / 2. ) );
1235 NHalfcycles = max( NHalfcycles,1 );
1236 wh = 2. * ( Hur - Hll ) / NHalfcycles;
1237 NHalfcycles = (int)( ( Vur - Vll ) / ( WaveLength / 2. ) );
1238 wv = 2. * ( Vur - Vll ) / NHalfcycles;
1239 NHalfcycles = max( NHalfcycles,1 );
1255 for ( i = i0; i <= i1; i++ )
1258 ha = ( ( h - Hll ) / wh ) * 2. * PI - PI / 2.;
1259 for ( j = j0; j <= j1; j++ )
1262 va = ( ( v - Vll ) / wv ) * 2. * PI;
1263 a = Amplitude * cos( ha ) * sin( va );
1267 xyz[i][j].p[2] -= a;
1270 xyz[i][j].p[1] += a;
1273 xyz[i][j].p[1] -= a;
1276 xyz[i][j].p[0] += a;
1279 xyz[i][j].p[0] -= a;
1282 xyz[i][j].p[2] += a;
1287 case WAVE_HCYLINDER:
1288 for ( i = 0; i <= NH; i++ )
1291 ha = ( ( h - Hll ) / WaveLength ) * 2. * PI - PI / 2.;
1292 for ( j = 0; j <= NV; j++ )
1294 a = Amplitude * cos( ha );
1298 xyz[i][j].p[2] -= a;
1301 xyz[i][j].p[1] += a;
1304 xyz[i][j].p[1] -= a;
1307 xyz[i][j].p[0] += a;
1310 xyz[i][j].p[0] -= a;
1313 xyz[i][j].p[2] += a;
1318 case WAVE_VCYLINDER:
1319 for ( i = 0; i <= NH; i++ )
1322 for ( j = 0; j <= NV; j++ )
1325 va = ( ( v - Vll ) / WaveLength ) * 2. * PI;
1326 a = Amplitude * sin( va );
1330 xyz[i][j].p[2] -= a;
1333 xyz[i][j].p[1] += a;
1336 xyz[i][j].p[1] -= a;
1339 xyz[i][j].p[0] += a;
1342 xyz[i][j].p[0] -= a;
1345 xyz[i][j].p[2] += a;
1350 case WAVE_ROUGH_ONLY:
1355 if ( WaveType != WAVE_ROUGH_ONLY ) {
1357 for ( i = 0; i <= NH; i++ )
1359 for ( j = 0; j <= NV; j++ )
1361 if ( xyz[i][j].fixed ) {
1366 xyz[i][j].p[1] = xyz[i][j].fixed_value;
1370 xyz[i][j].p[0] = xyz[i][j].fixed_value;
1373 xyz[i][j].p[2] = xyz[i][j].fixed_value;
1376 if ( xyz[i][j].range > 0 ) {
1377 maxrange = pow( xyz[i][j].range,2 ); // so we don't have to do sqrt's
1378 i0 = i - (int)( floor( xyz[i][j].range / dh - 0.5 ) + 1 );
1380 j0 = j - (int)( floor( xyz[i][j].range / dv - 0.5 ) + 1 );
1384 i1 = min( i1,NH - 1 );
1386 j1 = min( j1,NV - 1 );
1395 for ( ii = i0; ii <= i1; ii++ )
1397 for ( jj = j0; jj <= j1; jj++ )
1399 if ( ii == i && jj == j ) {
1402 range = pow( dh * ( i - ii ), 2 ) + pow( dv * ( j - jj ), 2 );
1403 if ( range > maxrange ) {
1406 dr = sqrt( range / maxrange );
1407 rate = max( -30.,min( xyz[i][j].rate,30. ) );
1409 delta = pow( ( 1. - dr ),-rate + 1. );
1411 else if ( rate < 0. ) {
1412 delta = ( 1 + rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) -
1413 rate*pow( ( 1. - dr ),2 );
1415 else if ( rate == 0. ) {
1416 delta = 0.5 * ( cos( dr * PI ) + 1.0 );
1418 else if ( rate <= 1. ) {
1419 delta = ( 1. - rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) +
1420 rate * ( 1. - pow( dr,2 ) );
1424 delta = 1. - pow( dr,rate + 1 );
1430 xyz[ii][jj].p[1] += ( xyz[i][j].p[1] - xyz[ii][jj].p[1] ) * delta;
1434 xyz[ii][jj].p[0] += ( xyz[i][j].p[0] - xyz[ii][jj].p[0] ) * delta;
1437 xyz[ii][jj].p[2] += ( xyz[i][j].p[2] - xyz[ii][jj].p[2] ) * delta;
1447 if ( ( Roughness > 0. ) && ( WaveType != WAVE_ROUGH_ONLY ) ) {
1448 for ( i = 0; i <= NH; i++ )
1450 for ( j = 0; j <= NV; j++ )
1452 if ( CanEdit( i,j ) && !xyz[i][j].fixed ) {
1457 xyz[i][j].p[1] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1461 xyz[i][j].p[0] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1464 xyz[i][j].p[2] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1468 r = rand(); // We still get a random number, so that fixing points
1470 // doesn't change the sequence.
1476 for ( i = 0; i <= NH; i++ )
1478 for ( j = 0; j <= NV; j++ )
1480 for ( k = 0; k < 3; k++ )
1482 xyz[i][j].p[k] = Nearest( xyz[i][j].p[k],2.0 );
1487 // Find minima and maxima
1496 ymin = xyz[0][0].p[1];
1498 for ( i = 0; i <= NH; i++ )
1500 for ( j = 0; j <= NV; j++ )
1502 ymin = min( ymin,xyz[i][j].p[1] );
1503 ymax = max( ymax,xyz[i][j].p[1] );
1513 xmin = xyz[0][0].p[0];
1515 for ( i = 0; i <= NH; i++ )
1517 for ( j = 0; j <= NV; j++ )
1519 xmin = min( xmin,xyz[i][j].p[0] );
1520 xmax = max( xmax,xyz[i][j].p[0] );
1530 zmin = xyz[0][0].p[2];
1532 for ( i = 0; i <= NH; i++ )
1534 for ( j = 0; j <= NV; j++ )
1536 zmin = min( zmin,xyz[i][j].p[2] );
1537 zmax = max( zmax,xyz[i][j].p[2] );
1542 xmin = Nearest( xmin,2. );
1543 xmax = Nearest( xmax,2. );
1544 ymin = Nearest( ymin,2. );
1545 ymax = Nearest( ymax,2. );
1546 zmin = Nearest( zmin,2. );
1547 zmax = Nearest( zmax,2. );
1552 backface = AtLeast( zmax + 32.,32. );
1555 backface = NoMoreThan( ymin - 32.,32. );
1558 backface = AtLeast( ymax + 32.,32. );
1561 backface = NoMoreThan( xmin - 32.,32. );
1564 backface = AtLeast( xmax + 32.,32. );
1567 backface = NoMoreThan( zmin - 32.,32. );
1573 gNode = (NODE *)NULL;
1576 if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) {
1577 MakeDecimatedMap( &gNumNodes,&gNumTris,&gNode,&gTri );
1581 gNumNodes = ( NH + 1 ) * ( NV + 1 );
1582 gNumTris = NH * NV * 2;
1583 gNode = (NODE *) malloc( gNumNodes * sizeof( NODE ) );
1584 gTri = (TRI *) malloc( gNumTris * sizeof( TRI ) );
1586 for ( i = 0,N = 0; i <= NH; i++ )
1588 for ( j = 0; j <= NV; j++, N++ )
1591 gNode[N].p[0] = (float)xyz[i][j].p[0];
1592 gNode[N].p[1] = (float)xyz[i][j].p[1];
1593 gNode[N].p[2] = (float)xyz[i][j].p[2];
1597 for ( i = 0; i < NH; i++ )
1599 for ( j = 0; j < NV; j++ )
1601 k = i * NV * 2 + j * 2;
1602 if ( ( i + j ) % 2 ) {
1608 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1609 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1610 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j;
1611 gTri[k + 1].v[0] = i * ( NV + 1 ) + j;
1612 gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1;
1613 gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1616 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1617 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j;
1618 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1619 gTri[k + 1].v[0] = i * ( NV + 1 ) + j;
1620 gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1621 gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1;
1631 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1632 gTri[k ].v[1] = i * ( NV + 1 ) + j + 1;
1633 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j;
1634 gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j;
1635 gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1;
1636 gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1639 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1640 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j;
1641 gTri[k ].v[2] = i * ( NV + 1 ) + j + 1;
1642 gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j;
1643 gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1644 gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1;
1651 sprintf(CSV,"csv%03d.csv",Decimate);
1653 for(i=0; i<gNumNodes; i++)
1656 fprintf(f,"%g,%g,%g\n",gNode[i].p[0],gNode[i].p[1],gNode[i].p[2]);
1660 for ( i = 0; i < gNumTris; i++ )
1661 PlaneFromPoints( gNode[gTri[i].v[0]].p,
1662 gNode[gTri[i].v[1]].p,
1663 gNode[gTri[i].v[2]].p,
1666 // Hydra: snap-to-grid begin
1667 if ( SnapToGrid > 0 ) {
1668 for ( i = 0; i < NH; i++ )
1670 for ( j = 0; j < NV; j++ )
1676 xyz[i][j].p[1] = CalculateSnapValue( xyz[i][j].p[1] );
1680 xyz[i][j].p[0] = CalculateSnapValue( xyz[i][j].p[0] );
1683 xyz[i][j].p[2] = CalculateSnapValue( xyz[i][j].p[2] );
1688 // Hydra: snap-to-grid end
1690 //=============================================================
1691 double Nearest( double x, double dx ){
1694 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1695 if ( fabs( xx ) < dx / 2 ) {
1700 //=============================================================
1701 double NoMoreThan( double x, double dx ){
1704 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1710 //=============================================================
1711 double AtLeast( double x, double dx ){
1714 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1720 //=============================================================
1721 double LessThan( double x,double dx ){
1724 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1730 //=============================================================
1731 double MoreThan( double x,double dx ){
1734 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1739 //=============================================================
1740 void SubdividePlasma( int i0,int j0,int i1,int j1 ){
1743 double r; // NOTE: This is used to keep the random number sequence the same
1744 // when we fix a point. If we did NOT do this, then simply
1745 // fixing a point at its current value would change the entire
1748 i = ( i0 + i1 ) / 2;
1749 j = ( j0 + j1 ) / 2;
1750 if ( i1 > i0 + 1 ) {
1751 if ( !xyz[i][j0].done ) {
1752 xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] +
1753 ( xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) +
1754 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1755 xyz[i][j0].done = 1;
1760 if ( ( j1 > j0 ) && ( !xyz[i][j1].done ) ) {
1761 xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] +
1762 ( xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) +
1763 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1764 xyz[i][j1].done = 1;
1770 if ( j1 > j0 + 1 ) {
1771 if ( !xyz[i0][j].done ) {
1772 xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] +
1773 ( xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) +
1774 ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1775 xyz[i0][j].done = 1;
1780 if ( ( i1 > i0 ) && ( !xyz[i1][j].done ) ) {
1781 xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] +
1782 ( xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) +
1783 ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1784 xyz[i1][j].done = 1;
1790 if ( ( i1 > i0 + 1 ) && ( j1 > j0 + 1 ) ) {
1791 if ( !xyz[i][j].done ) {
1792 z1 = xyz[i0][j].pp[2] +
1793 ( xyz[i1][j].pp[2] - xyz[i0][j].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 );
1794 z2 = xyz[i][j0].pp[2] +
1795 ( xyz[i][j1].pp[2] - xyz[i][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 );
1796 xyz[i][j].pp[2] = ( z1 + z2 ) / 2. +
1797 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1804 if ( i > i0 + 1 || j > j0 + 1 ) {
1805 SubdividePlasma( i0,j0,i,j );
1807 if ( i1 > i + 1 || j > j0 + 1 ) {
1808 SubdividePlasma( i,j0,i1,j );
1810 if ( i > i0 + 1 || j1 > j0 + 1 ) {
1811 SubdividePlasma( i0,j,i,j1 );
1813 if ( i1 > i + 1 || j1 > j0 + 1 ) {
1814 SubdividePlasma( i,j,i1,j1 );
1817 //==================================================================================
1820 /* use pp[2] values until done to avoid messing with a bunch of
1821 switch statements */
1823 for ( i = 0; i <= NH; i++ )
1825 for ( j = 0; j <= NV; j++ )
1827 if ( FixedPoint( i,j ) ) {
1840 for ( i = 0; i <= NH; i++ )
1842 for ( j = 0; j <= NV; j++ )
1844 if ( xyz[i][j].fixed ) {
1845 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1848 xyz[i][j].pp[2] = xyz[i][j].p[1];
1855 for ( i = 0; i <= NH; i++ )
1857 for ( j = 0; j <= NV; j++ )
1859 if ( xyz[i][j].fixed ) {
1860 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1863 xyz[i][j].pp[2] = xyz[i][j].p[0];
1869 for ( i = 0; i <= NH; i++ )
1871 for ( j = 0; j <= NV; j++ )
1873 if ( xyz[i][j].fixed ) {
1874 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1877 xyz[i][j].pp[2] = xyz[i][j].p[2];
1883 SubdividePlasma( 0,0,NH,NV );
1888 for ( i = 0; i <= NH; i++ )
1890 for ( j = 0; j <= NV; j++ )
1892 xyz[i][j].p[1] = xyz[i][j].pp[2];
1898 for ( i = 0; i <= NH; i++ )
1900 for ( j = 0; j <= NV; j++ )
1902 xyz[i][j].p[0] = xyz[i][j].pp[2];
1907 for ( i = 0; i <= NH; i++ )
1909 for ( j = 0; j <= NV; j++ )
1911 xyz[i][j].p[2] = xyz[i][j].pp[2];
1917 //===========================================================================
1918 bool FixedPoint( int i, int j ){
1919 if ( xyz[i][j].fixed ) {
1922 return !CanEdit( i,j );
1924 //===========================================================================
1925 bool CanEdit( int i, int j ){
1926 if ( FixBorders && ( ( WaveType == WAVE_COS_SIN ) || ( WaveType == WAVE_ROUGH_ONLY ) ) ) {
1940 if ( i == 0 && j == 0 ) {
1943 if ( i == NH && j == 0 ) {
1946 if ( i == 0 && j == NV ) {
1949 if ( i == NH && j == NV ) {
1954 /*============================================================================
1956 Determines which triangle in the gTri array bounds the input point. Doesn't
1957 do anything special with border points.
1959 int TriangleFromPoint( double x, double y ){
1966 for ( j = 0, tri = -1; j < gNumTris && tri == -1; j++ )
1969 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1],
1970 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1] ) < 0. ) {
1974 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1],
1975 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1] ) < 0. ) {
1979 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1],
1980 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1] ) < 0. ) {
1988 /*============================================================================
1990 Determines minimum height to place the player start such that he doesn't
1991 intersect any surface brushes.
1993 int PlayerStartZ( double x, double y ){
2001 t[0] = TriangleFromPoint( x,y );
2002 t[1] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[0] );
2003 t[2] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[1] );
2004 t[3] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[0] );
2005 t[4] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[1] );
2007 for ( k = 0; k < 5; k++ )
2009 zt = ( gTri[t[k]].plane.dist -
2010 gTri[t[k]].plane.normal[0] * x -
2011 gTri[t[k]].plane.normal[1] * y ) /
2012 gTri[t[k]].plane.normal[2];
2015 return (int)( AtLeast( z,2. ) - PlayerBox[Game].z[0] );
2017 //=============================================================
2018 void XYZtoV( XYZ *xyz, vec3 *v ){
2019 v[0][0] = (vec)Nearest( xyz->p[0],2. );
2020 v[0][1] = (vec)Nearest( xyz->p[1],2. );
2021 v[0][2] = (vec)Nearest( xyz->p[2],2. );
2024 //=============================================================
2025 scene::Node* MakePatch( void ){
2026 scene::Node* patch = Patch_AllocNode();
2028 patch->m_patch->SetShader( Texture[Game][0] );
2030 Node_getTraversable( h_worldspawn )->insert( patch );
2034 //=============================================================
2035 void MakeBrush( BRUSH *brush ){
2036 NodePtr node( Brush_AllocNode() );
2039 for ( int i = 0; i < brush->NumFaces; i++ )
2041 _QERFaceData QERFaceData;
2042 if ( !strncmp( brush->face[i].texture, "textures/", 9 ) ) {
2043 strcpy( QERFaceData.m_TextureName,brush->face[i].texture );
2047 strcpy( QERFaceData.m_TextureName,"textures/" );
2048 strcpy( QERFaceData.m_TextureName + 9,brush->face[i].texture );
2050 QERFaceData.m_nContents = brush->face[i].Contents;
2051 QERFaceData.m_nFlags = brush->face[i].Surface;
2052 QERFaceData.m_nValue = brush->face[i].Value;
2053 QERFaceData.m_fShift[0] = brush->face[i].Shift[0];
2054 QERFaceData.m_fShift[1] = brush->face[i].Shift[1];
2055 QERFaceData.m_fRotate = brush->face[i].Rotate;
2056 QERFaceData.m_fScale[0] = brush->face[i].Scale[0];
2057 QERFaceData.m_fScale[1] = brush->face[i].Scale[1];
2058 QERFaceData.m_v1[0] = brush->face[i].v[0][0];
2059 QERFaceData.m_v1[1] = brush->face[i].v[0][1];
2060 QERFaceData.m_v1[2] = brush->face[i].v[0][2];
2061 QERFaceData.m_v2[0] = brush->face[i].v[1][0];
2062 QERFaceData.m_v2[1] = brush->face[i].v[1][1];
2063 QERFaceData.m_v2[2] = brush->face[i].v[1][2];
2064 QERFaceData.m_v3[0] = brush->face[i].v[2][0];
2065 QERFaceData.m_v3[1] = brush->face[i].v[2][1];
2066 QERFaceData.m_v3[2] = brush->face[i].v[2][2];
2067 QERFaceData.m_bBPrimit = false;
2068 ( g_FuncTable.m_pfnAddFaceData )( vp,&QERFaceData );
2072 Node_getTraversable( h_func_group )->insert( node );
2074 //=============================================================
2075 void OpenFuncGroup(){
2076 h_func_group = GlobalEntityCreator().createEntity( "func_group" );
2077 h_func_group->IncRef();
2078 if ( AddTerrainKey ) {
2079 h_func_group->m_entity->setkeyvalue( "terrain", "1" );
2082 //=============================================================
2083 void CloseFuncGroup(){
2084 h_func_group->DecRef();
2085 if ( g_FuncTable.m_pfnSysUpdateWindows != NULL ) {
2086 g_FuncTable.m_pfnSysUpdateWindows( W_ALL );