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];
33 LPVOID terrainkey; // ^Fishman - Add terrain key to func_group.
35 //=============================================================
36 // Hydra : snap-to-grid begin
37 double CalculateSnapValue( double value ){
40 // simple uncomplicated snapping, rounding both UP and DOWN to the nearest
42 if ( SnapToGrid > 0 ) {
43 snapvalue = (int)value / SnapToGrid;
44 if ( (long)value % SnapToGrid < ( SnapToGrid / 2 ) ) { // Snap Downwards if less than halfway between to grid units
45 value = snapvalue * SnapToGrid;
47 else{ // Snap Upwards if more than halfway between to grid units
48 value = ( snapvalue + 1 ) * SnapToGrid;
53 // Hydra : snap-to-grid end
55 //=============================================================
57 if ( WaveType == WAVE_BITMAP && !gbmp.colors ) {
63 if ( NH > MAX_ROWS ) {
69 if ( NV > MAX_ROWS ) {
81 //=============================================================
93 dh = ( Hur - Hll ) / NH;
94 dv = ( Vur - Vll ) / NV;
95 memset( &p,0,sizeof( patchMesh_t ) );
97 // Generate control points in pp array to give desired values currently
120 for ( i = 0; i <= NH; i++ )
122 for ( j = 0; j <= NV; j++ )
124 xyz[i][j].pp[k1] = xyz[i][j].p[k1];
125 xyz[i][j].pp[k2] = xyz[i][j].p[k2];
128 for ( i = 0; i <= NH; i += 2 )
130 for ( j = 0; j <= NV; j += 2 )
131 xyz[i][j].pp[k3] = xyz[i][j].p[k3];
133 for ( i = 1; i < NH; i += 2 )
135 for ( j = 0; j <= NV; j += 2 )
137 xyz[i][j].pp[k3] = ( 4 * xyz[i][j].p[k3] - xyz[i - 1][j].p[k3] - xyz[i + 1][j].p[k3] ) / 2;
140 for ( j = 1; j < NV; j += 2 )
142 for ( i = 0; i <= NH; i += 2 )
144 xyz[i][j].pp[k3] = ( 4 * xyz[i][j].p[k3] - xyz[i][j - 1].p[k3] - xyz[i][j + 1].p[k3] ) / 2;
147 for ( i = 1; i < NH; i += 2 )
149 for ( j = 1; j < NV; j += 2 )
151 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]
152 - xyz[i + 1][j - 1].p[k3] - 2 * xyz[i - 1][j].p[k3] - 2 * xyz[i + 1][j].p[k3]
153 - xyz[i - 1][j + 1].p[k3] - 2 * xyz[i][j + 1].p[k3] - xyz[i + 1][j + 1].p[k3] ) / 4;
159 while ( NH_remain > 1 )
161 if ( ( ( NH_remain - 1 ) % 14 ) == 0 ) {
164 else if ( ( ( NH_remain - 1 ) % 12 ) == 0 ) {
167 else if ( ( ( NH_remain - 1 ) % 10 ) == 0 ) {
170 else if ( ( ( NH_remain - 1 ) % 8 ) == 0 ) {
173 else if ( ( ( NH_remain - 1 ) % 6 ) == 0 ) {
176 else if ( ( ( NH_remain - 1 ) % 4 ) == 0 ) {
179 else if ( ( ( NH_remain - 1 ) % 2 ) == 0 ) {
182 else if ( NH_remain > 16 ) {
185 else if ( NH_remain > 4 ) {
191 while ( NH_patch > 3 && ( NH_patch - 1 ) * dh > 512 )
193 NH_remain -= ( NH_patch - 1 );
194 if ( NH_remain < 0 ) {
195 sprintf( szOops,"Oops... screwed up with NH=%d",NH );
196 g_FuncTable.m_pfnMessageBox( NULL,szOops,"Uh oh", 0, NULL );
200 while ( NV_remain > 1 )
202 if ( ( ( NV_remain - 1 ) % 14 ) == 0 ) {
205 else if ( ( ( NV_remain - 1 ) % 12 ) == 0 ) {
208 else if ( ( ( NV_remain - 1 ) % 10 ) == 0 ) {
211 else if ( ( ( NV_remain - 1 ) % 8 ) == 0 ) {
214 else if ( ( ( NV_remain - 1 ) % 6 ) == 0 ) {
217 else if ( ( ( NV_remain - 1 ) % 4 ) == 0 ) {
220 else if ( ( ( NV_remain - 1 ) % 2 ) == 0 ) {
223 else if ( NV_remain > 16 ) {
226 else if ( NV_remain > 4 ) {
232 while ( NV_patch > 3 && ( NV_patch - 1 ) * dh > 512 )
234 NV_remain -= ( NV_patch - 1 );
235 if ( NV_remain < 0 ) {
236 sprintf( szOops,"Oops... screwed up with NV=%d",NV );
237 g_FuncTable.m_pfnMessageBox( NULL,szOops,"Uh oh", 0, NULL );
242 p.type = PATCH_GENERIC;
243 for ( i = 0; i < NH_patch; i++ )
250 ii = i0 + NH_patch - 1 - i;
255 for ( j = 0; j < NV_patch; j++ )
257 p.ctrl[i][j].xyz[0] = (float)xyz[ii][j0 + j].pp[0];
258 p.ctrl[i][j].xyz[1] = (float)xyz[ii][j0 + j].pp[1];
259 p.ctrl[i][j].xyz[2] = (float)xyz[ii][j0 + j].pp[2];
260 p.ctrl[i][j].st[0] = (float)i;
261 p.ctrl[i][j].st[1] = (float)j;
273 //=============================================================
282 vec3_t PlaneNormal,SurfNormal;
290 strcpy( surftext,Texture[Game][0] );
291 strcpy( sidetext,( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
292 strcpy( surftext2,( strlen( Texture[Game][2] ) ? Texture[Game][2] : Texture[Game][0] ) );
294 // if surftext2 is identical to surftext, there's no need to
295 // check surface angle
296 if ( !g_strcasecmp( surftext,surftext2 ) ) {
302 Steep = (float)cos( (double)SlantAngle / 57.2957795 );
305 case PLANE_XY0: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
306 case PLANE_XY1: PlaneNormal[0] = 0.; PlaneNormal[1] = 0.; PlaneNormal[2] = -1.; break;
307 case PLANE_XZ0: PlaneNormal[0] = 0.; PlaneNormal[1] = 1.; PlaneNormal[2] = 1.; break;
308 case PLANE_XZ1: PlaneNormal[0] = 0.; PlaneNormal[1] = -1.; PlaneNormal[2] = 1.; break;
309 case PLANE_YZ0: PlaneNormal[0] = 1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
310 case PLANE_YZ1: PlaneNormal[0] = -1.; PlaneNormal[1] = 0.; PlaneNormal[2] = 1.; break;
316 for ( i = 0; i < NH; i++ )
318 for ( j = 0; j < NV; j++ )
320 if ( ( i + j ) % 2 ) {
321 VectorCopy( xyz[i ][j ].p, v[0].p );
327 VectorCopy( xyz[i + 1][j ].p, v[1].p );
328 VectorCopy( xyz[i + 1][j + 1].p, v[2].p );
331 VectorCopy( xyz[i + 1][j + 1].p, v[1].p );
332 VectorCopy( xyz[i + 1][j ].p, v[2].p );
337 VectorCopy( xyz[i ][j ].p, v[0].p );
343 VectorCopy( xyz[i + 1][j ].p, v[1].p );
344 VectorCopy( xyz[i ][j + 1].p, v[2].p );
347 VectorCopy( xyz[i ][j + 1].p, v[1].p );
348 VectorCopy( xyz[i + 1][j ].p, v[2].p );
351 VectorCopy( v[0].p,v[3].p );
352 VectorCopy( v[1].p,v[4].p );
353 VectorCopy( v[2].p,v[5].p );
358 v[0].p[1] = backface;
359 v[1].p[1] = backface;
360 v[2].p[1] = backface;
364 v[3].p[0] = backface;
365 v[4].p[0] = backface;
366 v[5].p[0] = backface;
369 v[3].p[2] = backface;
370 v[4].p[2] = backface;
371 v[5].p[2] = backface;
374 brush.Number = i * NV * 2 + j * 2;
376 XYZtoV( &v[0],&brush.face[0].v[0] );
377 XYZtoV( &v[3],&brush.face[0].v[1] );
378 XYZtoV( &v[4],&brush.face[0].v[2] );
379 strcpy( brush.face[0].texture,
380 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
381 brush.face[0].Shift[0] = (float)TexOffset[0];
382 brush.face[0].Shift[1] = (float)TexOffset[1];
383 brush.face[0].Rotate = 0.;
384 brush.face[0].Scale[0] = (float)TexScale[0];
385 brush.face[0].Scale[1] = (float)TexScale[1];
386 brush.face[0].Contents = contents;
387 brush.face[0].Surface = surface[1];
388 brush.face[0].Value = 0;
390 XYZtoV( &v[1],&brush.face[1].v[0] );
391 XYZtoV( &v[4],&brush.face[1].v[1] );
392 XYZtoV( &v[5],&brush.face[1].v[2] );
393 strcpy( brush.face[1].texture,
394 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
395 brush.face[1].Shift[0] = (float)TexOffset[0];
396 brush.face[1].Shift[1] = (float)TexOffset[1];
397 brush.face[1].Rotate = 0.;
398 brush.face[1].Scale[0] = (float)TexScale[0];
399 brush.face[1].Scale[1] = (float)TexScale[1];
400 brush.face[1].Contents = contents;
401 brush.face[1].Surface = surface[1];
402 brush.face[1].Value = 0;
404 XYZtoV( &v[2],&brush.face[2].v[0] );
405 XYZtoV( &v[5],&brush.face[2].v[1] );
406 XYZtoV( &v[3],&brush.face[2].v[2] );
407 strcpy( brush.face[2].texture,
408 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
409 brush.face[2].Shift[0] = (float)TexOffset[0];
410 brush.face[2].Shift[1] = (float)TexOffset[1];
411 brush.face[2].Rotate = 0.;
412 brush.face[2].Scale[0] = (float)TexScale[0];
413 brush.face[2].Scale[1] = (float)TexScale[1];
414 brush.face[2].Contents = contents;
415 brush.face[2].Surface = surface[1];
416 brush.face[2].Value = 0;
418 if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) {
419 XYZVectorSubtract( v[4].p,v[3].p,t[0] );
420 XYZVectorSubtract( v[5].p,v[4].p,t[1] );
421 CrossProduct( t[0],t[1],SurfNormal );
422 VectorNormalize( SurfNormal,SurfNormal );
423 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
424 strcpy( surft,surftext2 );
429 strcpy( surft,surftext );
435 strcpy( surft,surftext );
439 XYZtoV( &v[3],&brush.face[3].v[0] );
440 XYZtoV( &v[5],&brush.face[3].v[1] );
441 XYZtoV( &v[4],&brush.face[3].v[2] );
442 strcpy( brush.face[3].texture,
443 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) );
444 brush.face[3].Shift[0] = (float)TexOffset[0];
445 brush.face[3].Shift[1] = (float)TexOffset[1];
446 brush.face[3].Rotate = 0.;
447 brush.face[3].Scale[0] = (float)TexScale[0];
448 brush.face[3].Scale[1] = (float)TexScale[1];
449 brush.face[3].Contents = contents;
450 brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] );
451 brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 );
453 if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) {
454 XYZVectorSubtract( v[2].p,v[0].p,t[0] );
455 XYZVectorSubtract( v[1].p,v[2].p,t[1] );
456 CrossProduct( t[0],t[1],SurfNormal );
457 VectorNormalize( SurfNormal,SurfNormal );
458 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
459 strcpy( surft,surftext2 );
464 strcpy( surft,surftext );
470 strcpy( surft,surftext );
474 XYZtoV( &v[0],&brush.face[4].v[0] );
475 XYZtoV( &v[1],&brush.face[4].v[1] );
476 XYZtoV( &v[2],&brush.face[4].v[2] );
477 strcpy( brush.face[4].texture,
478 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) );
479 brush.face[4].Shift[0] = (float)TexOffset[0];
480 brush.face[4].Shift[1] = (float)TexOffset[1];
481 brush.face[4].Rotate = 0.;
482 brush.face[4].Scale[0] = (float)TexScale[0];
483 brush.face[4].Scale[1] = (float)TexScale[1];
484 brush.face[4].Contents = contents;
485 brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf );
486 brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 );
489 if ( ( i + j ) % 2 ) {
490 VectorCopy( xyz[i ][j + 1].p,v[0].p );
496 VectorCopy( xyz[i ][j ].p,v[1].p );
497 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
500 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
501 VectorCopy( xyz[i ][j ].p,v[2].p );
506 VectorCopy( xyz[i ][j + 1].p,v[0].p );
512 VectorCopy( xyz[i + 1][j ].p,v[1].p );
513 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
516 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
517 VectorCopy( xyz[i + 1][j ].p,v[2].p );
520 VectorCopy( v[0].p,v[3].p );
521 VectorCopy( v[1].p,v[4].p );
522 VectorCopy( v[2].p,v[5].p );
527 v[0].p[1] = backface;
528 v[1].p[1] = backface;
529 v[2].p[1] = backface;
533 v[3].p[0] = backface;
534 v[4].p[0] = backface;
535 v[5].p[0] = backface;
538 v[3].p[2] = backface;
539 v[4].p[2] = backface;
540 v[5].p[2] = backface;
542 brush.Number = i * NV * 2 + j * 2 + 1;
544 XYZtoV( &v[0],&brush.face[0].v[0] );
545 XYZtoV( &v[3],&brush.face[0].v[1] );
546 XYZtoV( &v[4],&brush.face[0].v[2] );
547 strcpy( brush.face[0].texture,
548 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
549 brush.face[0].Shift[0] = (float)TexOffset[0];
550 brush.face[0].Shift[1] = (float)TexOffset[1];
551 brush.face[0].Rotate = 0.;
552 brush.face[0].Scale[0] = (float)TexScale[0];
553 brush.face[0].Scale[1] = (float)TexScale[1];
554 brush.face[0].Contents = contents;
555 brush.face[0].Surface = surface[1];
556 brush.face[0].Value = 0;
558 XYZtoV( &v[1],&brush.face[1].v[0] );
559 XYZtoV( &v[4],&brush.face[1].v[1] );
560 XYZtoV( &v[5],&brush.face[1].v[2] );
561 strcpy( brush.face[1].texture,
562 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
563 brush.face[1].Shift[0] = (float)TexOffset[0];
564 brush.face[1].Shift[1] = (float)TexOffset[1];
565 brush.face[1].Rotate = 0.;
566 brush.face[1].Scale[0] = (float)TexScale[0];
567 brush.face[1].Scale[1] = (float)TexScale[1];
568 brush.face[1].Contents = contents;
569 brush.face[1].Surface = surface[1];
570 brush.face[1].Value = 0;
572 XYZtoV( &v[2],&brush.face[2].v[0] );
573 XYZtoV( &v[5],&brush.face[2].v[1] );
574 XYZtoV( &v[3],&brush.face[2].v[2] );
575 strcpy( brush.face[2].texture,
576 ( strlen( Texture[Game][1] ) ? Texture[Game][1] : Texture[Game][0] ) );
577 brush.face[2].Shift[0] = (float)TexOffset[0];
578 brush.face[2].Shift[1] = (float)TexOffset[1];
579 brush.face[2].Rotate = 0.;
580 brush.face[2].Scale[0] = (float)TexScale[0];
581 brush.face[2].Scale[1] = (float)TexScale[1];
582 brush.face[2].Contents = contents;
583 brush.face[2].Surface = surface[1];
584 brush.face[2].Value = 0;
586 if ( CheckAngle && ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ) ) {
587 XYZVectorSubtract( v[4].p,v[3].p,t[0] );
588 XYZVectorSubtract( v[5].p,v[4].p,t[1] );
589 CrossProduct( t[0],t[1],SurfNormal );
590 VectorNormalize( SurfNormal,SurfNormal );
591 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
592 strcpy( surft,surftext2 );
597 strcpy( surft,surftext );
603 strcpy( surft,surftext );
606 XYZtoV( &v[3],&brush.face[3].v[0] );
607 XYZtoV( &v[5],&brush.face[3].v[1] );
608 XYZtoV( &v[4],&brush.face[3].v[2] );
609 strcpy( brush.face[3].texture,
610 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surft : sidetext ) );
611 brush.face[3].Shift[0] = (float)TexOffset[0];
612 brush.face[3].Shift[1] = (float)TexOffset[1];
613 brush.face[3].Rotate = 0.;
614 brush.face[3].Scale[0] = (float)TexScale[0];
615 brush.face[3].Scale[1] = (float)TexScale[1];
616 brush.face[3].Contents = contents;
617 brush.face[3].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surf : surface[1] );
618 brush.face[3].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? ArghRad2 : 0 );
620 if ( CheckAngle && Plane != PLANE_XZ0 && Plane != PLANE_XZ1 ) {
621 XYZVectorSubtract( v[2].p,v[0].p,t[0] );
622 XYZVectorSubtract( v[1].p,v[2].p,t[1] );
623 CrossProduct( t[0],t[1],SurfNormal );
624 VectorNormalize( SurfNormal,SurfNormal );
625 if ( DotProduct( SurfNormal,PlaneNormal ) < Steep ) {
626 strcpy( surft,surftext2 );
631 strcpy( surft,surftext );
637 strcpy( surft,surftext );
640 XYZtoV( &v[0],&brush.face[4].v[0] );
641 XYZtoV( &v[1],&brush.face[4].v[1] );
642 XYZtoV( &v[2],&brush.face[4].v[2] );
643 strcpy( brush.face[4].texture,
644 ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? sidetext : surft ) );
645 brush.face[4].Shift[0] = (float)TexOffset[0];
646 brush.face[4].Shift[1] = (float)TexOffset[1];
647 brush.face[4].Rotate = 0.;
648 brush.face[4].Scale[0] = (float)TexScale[0];
649 brush.face[4].Scale[1] = (float)TexScale[1];
650 brush.face[4].Contents = contents;
651 brush.face[4].Surface = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? surface[1] : surf );
652 brush.face[4].Value = ( Plane == PLANE_XZ0 || Plane == PLANE_XZ1 ? 0 : ArghRad2 );
659 if ( AddHints || GimpHints ) {
660 int detail, i1, j1, N;
666 strcpy( hint,"HINT" );
667 strcpy( skip,"HINT" );
670 strcpy( hint,"generic/misc/hint" );
671 strcpy( skip,"generic/misc/skip" );
674 strcpy( hint,"general/hint" );
675 strcpy( skip,"general/hint" ); // Heretic2 doesn't have a skip texture
678 strcpy( hint,"common/0_hint" );
679 strcpy( skip,"common/0_skip" );
682 strcpy( hint,"hint" );
683 strcpy( skip,"hint" );
686 strcpy( hint,"textures/common/hint" );
687 strcpy( skip,"textures/common/skip" );
690 strcpy( hint,"e1u1/hint" );
691 strcpy( skip,"e1u1/skip" );
696 if ( AddHints == 1 ) {
697 detail = CONTENTS_DETAIL;
699 for ( i = 0; i < NH; i++ )
703 for ( j = 0; j < NV; j++ )
706 // For detail hint brushes, no need to use a hint brush over
707 // EVERY grid square... it would be redundant. Instead use
708 // a checkerboard pattern
709 if ( ( i + j ) % 2 ) {
715 VectorCopy( xyz[i ][j ].p, v[0].p );
721 VectorCopy( xyz[i1][j ].p, v[1].p );
722 VectorCopy( xyz[i1][j1].p, v[2].p );
723 VectorCopy( xyz[i ][j1].p, v[3].p );
726 VectorCopy( xyz[i ][j1].p, v[1].p );
727 VectorCopy( xyz[i1][j1].p, v[2].p );
728 VectorCopy( xyz[i1][j ].p, v[3].p );
731 VectorCopy( v[0].p,v[4].p );
732 VectorCopy( v[1].p,v[5].p );
733 VectorCopy( v[2].p,v[6].p );
734 VectorCopy( v[3].p,v[7].p );
739 front = LessThan( zmin,32. );
740 v[4].p[2] = backface;
741 v[5].p[2] = backface;
742 v[6].p[2] = backface;
743 v[7].p[2] = backface;
746 front = MoreThan( ymax,32. );
747 v[0].p[1] = backface;
748 v[1].p[1] = backface;
749 v[2].p[1] = backface;
750 v[3].p[1] = backface;
753 front = LessThan( ymin,32. );
754 v[0].p[1] = backface;
755 v[1].p[1] = backface;
756 v[2].p[1] = backface;
757 v[3].p[1] = backface;
760 front = MoreThan( xmax,32. );
761 v[4].p[0] = backface;
762 v[5].p[0] = backface;
763 v[6].p[0] = backface;
764 v[7].p[0] = backface;
767 front = LessThan( xmin,32. );
768 v[4].p[0] = backface;
769 v[5].p[0] = backface;
770 v[6].p[0] = backface;
771 v[7].p[0] = backface;
774 front = MoreThan( zmax,32. );
775 v[4].p[2] = backface;
776 v[5].p[2] = backface;
777 v[6].p[2] = backface;
778 v[7].p[2] = backface;
786 v[5].p[1] = v[4].p[1];
787 v[6].p[1] = v[4].p[1];
788 v[7].p[1] = v[4].p[1];
793 v[1].p[0] = v[0].p[0];
794 v[2].p[0] = v[0].p[0];
795 v[3].p[0] = v[0].p[0];
799 v[1].p[2] = v[0].p[2];
800 v[2].p[2] = v[0].p[2];
801 v[3].p[2] = v[0].p[2];
806 XYZtoV( &v[0],&brush.face[0].v[0] );
807 XYZtoV( &v[1],&brush.face[0].v[1] );
808 XYZtoV( &v[2],&brush.face[0].v[2] );
809 strcpy( brush.face[0].texture,skip );
810 brush.face[0].Shift[0] = 0.;
811 brush.face[0].Shift[1] = 0.;
812 brush.face[0].Rotate = 0.;
813 brush.face[0].Scale[0] = 1.;
814 brush.face[0].Scale[1] = 1.;
815 brush.face[0].Contents = detail;
816 brush.face[0].Surface = SURF_SKIP;
817 brush.face[0].Value = 0;
819 XYZtoV( &v[4],&brush.face[1].v[0] );
820 XYZtoV( &v[7],&brush.face[1].v[1] );
821 XYZtoV( &v[6],&brush.face[1].v[2] );
822 strcpy( brush.face[1].texture,skip );
823 brush.face[1].Shift[0] = 0.;
824 brush.face[1].Shift[1] = 0.;
825 brush.face[1].Rotate = 0.;
826 brush.face[1].Scale[0] = 1.;
827 brush.face[1].Scale[1] = 1.;
828 brush.face[1].Contents = detail;
829 brush.face[1].Surface = SURF_SKIP;
830 brush.face[1].Value = 0;
832 XYZtoV( &v[0],&brush.face[2].v[0] );
833 XYZtoV( &v[4],&brush.face[2].v[1] );
834 XYZtoV( &v[5],&brush.face[2].v[2] );
835 strcpy( brush.face[2].texture,hint );
836 brush.face[2].Shift[0] = 0.;
837 brush.face[2].Shift[1] = 0.;
838 brush.face[2].Rotate = 0.;
839 brush.face[2].Scale[0] = 1.;
840 brush.face[2].Scale[1] = 1.;
841 brush.face[2].Contents = detail;
842 brush.face[2].Surface = SURF_HINT;
843 brush.face[2].Value = 0;
845 XYZtoV( &v[1],&brush.face[3].v[0] );
846 XYZtoV( &v[5],&brush.face[3].v[1] );
847 XYZtoV( &v[6],&brush.face[3].v[2] );
848 strcpy( brush.face[3].texture,hint );
849 brush.face[3].Shift[0] = 0.;
850 brush.face[3].Shift[1] = 0.;
851 brush.face[3].Rotate = 0.;
852 brush.face[3].Scale[0] = 1.;
853 brush.face[3].Scale[1] = 1.;
854 brush.face[3].Contents = detail;
855 brush.face[3].Surface = SURF_HINT;
856 brush.face[3].Value = 0;
858 XYZtoV( &v[2],&brush.face[4].v[0] );
859 XYZtoV( &v[6],&brush.face[4].v[1] );
860 XYZtoV( &v[7],&brush.face[4].v[2] );
861 strcpy( brush.face[4].texture,hint );
862 brush.face[4].Shift[0] = 0.;
863 brush.face[4].Shift[1] = 0.;
864 brush.face[4].Rotate = 0.;
865 brush.face[4].Scale[0] = 1.;
866 brush.face[4].Scale[1] = 1.;
867 brush.face[4].Contents = detail;
868 brush.face[4].Surface = SURF_HINT;
869 brush.face[4].Value = 0;
871 XYZtoV( &v[3],&brush.face[5].v[0] );
872 XYZtoV( &v[7],&brush.face[5].v[1] );
873 XYZtoV( &v[4],&brush.face[5].v[2] );
874 strcpy( brush.face[5].texture,hint );
875 brush.face[5].Shift[0] = 0.;
876 brush.face[5].Shift[1] = 0.;
877 brush.face[5].Rotate = 0.;
878 brush.face[5].Scale[0] = 1.;
879 brush.face[5].Scale[1] = 1.;
880 brush.face[5].Contents = detail;
881 brush.face[5].Surface = SURF_HINT;
882 brush.face[5].Value = 0;
891 // these brush parameters never change
893 for ( i = 0; i < 6; i++ )
895 strcpy( brush.face[i].texture,hint );
896 brush.face[i].Shift[0] = 0.;
897 brush.face[i].Shift[1] = 0.;
898 brush.face[i].Rotate = 0.;
899 brush.face[i].Scale[0] = 1.;
900 brush.face[i].Scale[1] = 1.;
901 brush.face[i].Contents = 0;
902 brush.face[i].Surface = SURF_HINT;
903 brush.face[i].Value = 0;
905 for ( i = 0; i < NH; i++ )
907 for ( j = 0; j < NV; j++ )
909 for ( k = 0; k < 2; k++ )
912 if ( ( i + j ) % 2 ) {
913 VectorCopy( xyz[i ][j ].p, v[0].p );
919 VectorCopy( xyz[i + 1][j ].p, v[1].p );
920 VectorCopy( xyz[i + 1][j + 1].p, v[2].p );
923 VectorCopy( xyz[i + 1][j + 1].p, v[1].p );
924 VectorCopy( xyz[i + 1][j ].p, v[2].p );
929 VectorCopy( xyz[i ][j ].p, v[0].p );
935 VectorCopy( xyz[i + 1][j ].p, v[1].p );
936 VectorCopy( xyz[i ][j + 1].p, v[2].p );
939 VectorCopy( xyz[i ][j + 1].p, v[1].p );
940 VectorCopy( xyz[i + 1][j ].p, v[2].p );
946 if ( ( i + j ) % 2 ) {
947 VectorCopy( xyz[i ][j + 1].p,v[0].p );
953 VectorCopy( xyz[i ][j ].p,v[1].p );
954 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
957 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
958 VectorCopy( xyz[i ][j ].p,v[2].p );
963 VectorCopy( xyz[i ][j + 1].p,v[0].p );
969 VectorCopy( xyz[i + 1][j ].p,v[1].p );
970 VectorCopy( xyz[i + 1][j + 1].p,v[2].p );
973 VectorCopy( xyz[i + 1][j + 1].p,v[1].p );
974 VectorCopy( xyz[i + 1][j ].p,v[2].p );
978 VectorCopy( v[0].p,v[3].p );
979 VectorCopy( v[1].p,v[4].p );
980 VectorCopy( v[2].p,v[5].p );
984 v[0].p[2] += HINT_OFFSET;
985 v[1].p[2] += HINT_OFFSET;
986 v[2].p[2] += HINT_OFFSET;
987 // v[3].p[2] = backface;
988 // v[4].p[2] = backface;
989 // v[5].p[2] = backface;
992 v[0].p[2] -= HINT_OFFSET;
993 v[1].p[2] -= HINT_OFFSET;
994 v[2].p[2] -= HINT_OFFSET;
995 // v[3].p[2] = backface;
996 // v[4].p[2] = backface;
997 // v[5].p[2] = backface;
1000 // v[0].p[1] = backface;
1001 // v[1].p[1] = backface;
1002 // v[2].p[1] = backface;
1003 v[3].p[1] += HINT_OFFSET;
1004 v[4].p[1] += HINT_OFFSET;
1005 v[5].p[1] += HINT_OFFSET;
1008 // v[0].p[1] = backface;
1009 // v[1].p[1] = backface;
1010 // v[2].p[1] = backface;
1011 v[3].p[1] -= HINT_OFFSET;
1012 v[4].p[1] -= HINT_OFFSET;
1013 v[5].p[1] -= HINT_OFFSET;
1016 v[0].p[0] += HINT_OFFSET;
1017 v[1].p[0] += HINT_OFFSET;
1018 v[2].p[0] += HINT_OFFSET;
1019 // v[3].p[0] = backface;
1020 // v[4].p[0] = backface;
1021 // v[5].p[0] = backface;
1024 v[0].p[0] -= HINT_OFFSET;
1025 v[1].p[0] -= HINT_OFFSET;
1026 v[2].p[0] -= HINT_OFFSET;
1027 // v[3].p[0] = backface;
1028 // v[4].p[0] = backface;
1029 // v[5].p[0] = backface;
1033 XYZtoV( &v[0],&brush.face[0].v[0] );
1034 XYZtoV( &v[3],&brush.face[0].v[1] );
1035 XYZtoV( &v[4],&brush.face[0].v[2] );
1037 XYZtoV( &v[1],&brush.face[1].v[0] );
1038 XYZtoV( &v[4],&brush.face[1].v[1] );
1039 XYZtoV( &v[5],&brush.face[1].v[2] );
1041 XYZtoV( &v[2],&brush.face[2].v[0] );
1042 XYZtoV( &v[5],&brush.face[2].v[1] );
1043 XYZtoV( &v[3],&brush.face[2].v[2] );
1045 XYZtoV( &v[3],&brush.face[3].v[0] );
1046 XYZtoV( &v[5],&brush.face[3].v[1] );
1047 XYZtoV( &v[4],&brush.face[3].v[2] );
1049 XYZtoV( &v[0],&brush.face[4].v[0] );
1050 XYZtoV( &v[1],&brush.face[4].v[1] );
1051 XYZtoV( &v[2],&brush.face[4].v[2] );
1053 MakeBrush( &brush );
1058 } // endif AddHints==1
1064 //=============================================================
1066 extern void MapOut( int,int,NODE *,TRI * );
1067 extern bool SingleBrushSelected;
1070 if ( !ValidSurface() ) {
1074 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
1075 SetCursor(ghCursorCurrent);
1077 if ( SingleBrushSelected ) {
1078 g_FuncTable.m_pfnDeleteSelection();
1084 if ( Game == QUAKE3 && UsePatches != 0 ) {
1088 if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) {
1089 MapOut( gNumNodes,gNumTris,gNode,gTri );
1091 ghCursorCurrent = ghCursorDefault;
1092 SetCursor(ghCursorCurrent);
1098 // HL doesn't have detail property
1099 if ( ( Game != HALFLIFE ) && UseDetail ) {
1100 contents += CONTENTS_DETAIL;
1102 // HL and Q3 don't have ladder property
1103 if ( ( Game != HALFLIFE && Game != QUAKE3 ) && UseLadder ) {
1104 contents += CONTENTS_LADDER;
1106 // Genesis requires solid property to be set explicitly
1107 if ( Game == GENESIS3D ) {
1108 contents |= CONTENTS_SOLID;
1110 // Heretic 2 uses different sounds (in surface props) for different texture types
1111 if ( Game == HERETIC2 ) {
1112 surface[0] = GetDefSurfaceProps( Texture[Game][0] );
1113 surface[1] = GetDefSurfaceProps( Texture[Game][1] );
1114 surface[2] = GetDefSurfaceProps( Texture[Game][2] );
1122 if ( Game != QUAKE3 || UsePatches == 0 ) {
1127 ghCursorCurrent = ghCursorDefault;
1128 SetCursor(ghCursorCurrent);
1132 //=============================================================
1134 extern void MakeDecimatedMap( int *, int *, NODE * *, TRI * * );
1139 double delta, dr, rate;
1140 double range, maxrange;
1149 if ( !ValidSurface() ) {
1154 srand( RandomSeed );
1156 dh = ( Hur - Hll ) / NH;
1157 dv = ( Vur - Vll ) / NV;
1160 for ( i = 0; i <= NH; i++ )
1162 for ( j = 0; j <= NV; j++ )
1168 xyz[i][j].p[0] = Hll + i * dh;
1169 xyz[i][j].p[2] = Vll + j * dv;
1173 xyz[i][j].p[1] = Hll + i * dh;
1174 xyz[i][j].p[2] = Vll + j * dv;
1177 xyz[i][j].p[0] = Hll + i * dh;
1178 xyz[i][j].p[1] = Vll + j * dv;
1183 if ( WaveType == WAVE_BITMAP ) {
1184 GenerateBitmapMapping();
1187 else if(WaveType == WAVE_FORMULA)
1192 // Initialize Z values using bilinear interpolation
1193 for ( i = 0; i <= NH; i++ )
1195 zl = Z00 + i * ( Z10 - Z00 ) / NH;
1196 zu = Z01 + i * ( Z11 - Z01 ) / NH;
1201 for ( j = 0; j <= NV; j++ )
1202 xyz[i][j].p[1] = zl + j * ( zu - zl ) / NV;
1206 for ( j = 0; j <= NV; j++ )
1207 xyz[i][j].p[0] = zl + j * ( zu - zl ) / NV;
1210 for ( j = 0; j <= NV; j++ )
1211 xyz[i][j].p[2] = zl + j * ( zu - zl ) / NV;
1220 NHalfcycles = (int)( ( Hur - Hll ) / ( WaveLength / 2. ) );
1221 NHalfcycles = max( NHalfcycles,1 );
1222 wh = 2. * ( Hur - Hll ) / NHalfcycles;
1223 NHalfcycles = (int)( ( Vur - Vll ) / ( WaveLength / 2. ) );
1224 wv = 2. * ( Vur - Vll ) / NHalfcycles;
1225 NHalfcycles = max( NHalfcycles,1 );
1241 for ( i = i0; i <= i1; i++ )
1244 ha = ( ( h - Hll ) / wh ) * 2. * PI - PI / 2.;
1245 for ( j = j0; j <= j1; j++ )
1248 va = ( ( v - Vll ) / wv ) * 2. * PI;
1249 a = Amplitude * cos( ha ) * sin( va );
1253 xyz[i][j].p[2] -= a;
1256 xyz[i][j].p[1] += a;
1259 xyz[i][j].p[1] -= a;
1262 xyz[i][j].p[0] += a;
1265 xyz[i][j].p[0] -= a;
1268 xyz[i][j].p[2] += a;
1273 case WAVE_HCYLINDER:
1274 for ( i = 0; i <= NH; i++ )
1277 ha = ( ( h - Hll ) / WaveLength ) * 2. * PI - PI / 2.;
1278 for ( j = 0; j <= NV; j++ )
1280 a = Amplitude * cos( ha );
1284 xyz[i][j].p[2] -= a;
1287 xyz[i][j].p[1] += a;
1290 xyz[i][j].p[1] -= a;
1293 xyz[i][j].p[0] += a;
1296 xyz[i][j].p[0] -= a;
1299 xyz[i][j].p[2] += a;
1304 case WAVE_VCYLINDER:
1305 for ( i = 0; i <= NH; i++ )
1308 for ( j = 0; j <= NV; j++ )
1311 va = ( ( v - Vll ) / WaveLength ) * 2. * PI;
1312 a = Amplitude * sin( va );
1316 xyz[i][j].p[2] -= a;
1319 xyz[i][j].p[1] += a;
1322 xyz[i][j].p[1] -= a;
1325 xyz[i][j].p[0] += a;
1328 xyz[i][j].p[0] -= a;
1331 xyz[i][j].p[2] += a;
1336 case WAVE_ROUGH_ONLY:
1341 if ( WaveType != WAVE_ROUGH_ONLY ) {
1343 for ( i = 0; i <= NH; i++ )
1345 for ( j = 0; j <= NV; j++ )
1347 if ( xyz[i][j].fixed ) {
1352 xyz[i][j].p[1] = xyz[i][j].fixed_value;
1356 xyz[i][j].p[0] = xyz[i][j].fixed_value;
1359 xyz[i][j].p[2] = xyz[i][j].fixed_value;
1362 if ( xyz[i][j].range > 0 ) {
1363 maxrange = pow( xyz[i][j].range,2 ); // so we don't have to do sqrt's
1364 i0 = i - (int)( floor( xyz[i][j].range / dh - 0.5 ) + 1 );
1366 j0 = j - (int)( floor( xyz[i][j].range / dv - 0.5 ) + 1 );
1370 i1 = min( i1,NH - 1 );
1372 j1 = min( j1,NV - 1 );
1381 for ( ii = i0; ii <= i1; ii++ )
1383 for ( jj = j0; jj <= j1; jj++ )
1385 if ( ii == i && jj == j ) {
1388 range = pow( dh * ( i - ii ), 2 ) + pow( dv * ( j - jj ), 2 );
1389 if ( range > maxrange ) {
1392 dr = sqrt( range / maxrange );
1393 rate = max( -30.,min( xyz[i][j].rate,30. ) );
1395 delta = pow( ( 1. - dr ),-rate + 1. );
1397 else if ( rate < 0. ) {
1398 delta = ( 1 + rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) -
1399 rate*pow( ( 1. - dr ),2 );
1401 else if ( rate == 0. ) {
1402 delta = 0.5 * ( cos( dr * PI ) + 1.0 );
1404 else if ( rate <= 1. ) {
1405 delta = ( 1. - rate ) * 0.5 * ( cos( dr * PI ) + 1.0 ) +
1406 rate * ( 1. - pow( dr,2 ) );
1410 delta = 1. - pow( dr,rate + 1 );
1416 xyz[ii][jj].p[1] += ( xyz[i][j].p[1] - xyz[ii][jj].p[1] ) * delta;
1420 xyz[ii][jj].p[0] += ( xyz[i][j].p[0] - xyz[ii][jj].p[0] ) * delta;
1423 xyz[ii][jj].p[2] += ( xyz[i][j].p[2] - xyz[ii][jj].p[2] ) * delta;
1433 if ( ( Roughness > 0. ) && ( WaveType != WAVE_ROUGH_ONLY ) ) {
1434 for ( i = 0; i <= NH; i++ )
1436 for ( j = 0; j <= NV; j++ )
1438 if ( CanEdit( i,j ) && !xyz[i][j].fixed ) {
1443 xyz[i][j].p[1] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1447 xyz[i][j].p[0] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1450 xyz[i][j].p[2] += -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX );
1454 r = rand(); // We still get a random number, so that fixing points
1456 // doesn't change the sequence.
1462 for ( i = 0; i <= NH; i++ )
1464 for ( j = 0; j <= NV; j++ )
1466 for ( k = 0; k < 3; k++ )
1468 xyz[i][j].p[k] = Nearest( xyz[i][j].p[k],2.0 );
1473 // Find minima and maxima
1482 ymin = xyz[0][0].p[1];
1484 for ( i = 0; i <= NH; i++ )
1486 for ( j = 0; j <= NV; j++ )
1488 ymin = min( ymin,xyz[i][j].p[1] );
1489 ymax = max( ymax,xyz[i][j].p[1] );
1499 xmin = xyz[0][0].p[0];
1501 for ( i = 0; i <= NH; i++ )
1503 for ( j = 0; j <= NV; j++ )
1505 xmin = min( xmin,xyz[i][j].p[0] );
1506 xmax = max( xmax,xyz[i][j].p[0] );
1516 zmin = xyz[0][0].p[2];
1518 for ( i = 0; i <= NH; i++ )
1520 for ( j = 0; j <= NV; j++ )
1522 zmin = min( zmin,xyz[i][j].p[2] );
1523 zmax = max( zmax,xyz[i][j].p[2] );
1528 xmin = Nearest( xmin,2. );
1529 xmax = Nearest( xmax,2. );
1530 ymin = Nearest( ymin,2. );
1531 ymax = Nearest( ymax,2. );
1532 zmin = Nearest( zmin,2. );
1533 zmax = Nearest( zmax,2. );
1538 backface = AtLeast( zmax + 32.,32. );
1541 backface = NoMoreThan( ymin - 32.,32. );
1544 backface = AtLeast( ymax + 32.,32. );
1547 backface = NoMoreThan( xmin - 32.,32. );
1550 backface = AtLeast( xmax + 32.,32. );
1553 backface = NoMoreThan( zmin - 32.,32. );
1559 gNode = (NODE *)NULL;
1562 if ( Decimate > 0 && ( Game != QUAKE3 || UsePatches == 0 ) ) {
1563 MakeDecimatedMap( &gNumNodes,&gNumTris,&gNode,&gTri );
1567 gNumNodes = ( NH + 1 ) * ( NV + 1 );
1568 gNumTris = NH * NV * 2;
1569 gNode = (NODE *) malloc( gNumNodes * sizeof( NODE ) );
1570 gTri = (TRI *) malloc( gNumTris * sizeof( TRI ) );
1572 for ( i = 0,N = 0; i <= NH; i++ )
1574 for ( j = 0; j <= NV; j++, N++ )
1577 gNode[N].p[0] = (float)xyz[i][j].p[0];
1578 gNode[N].p[1] = (float)xyz[i][j].p[1];
1579 gNode[N].p[2] = (float)xyz[i][j].p[2];
1583 for ( i = 0; i < NH; i++ )
1585 for ( j = 0; j < NV; j++ )
1587 k = i * NV * 2 + j * 2;
1588 if ( ( i + j ) % 2 ) {
1594 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1595 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1596 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j;
1597 gTri[k + 1].v[0] = i * ( 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 + 1 ) * ( NV + 1 ) + j + 1;
1605 gTri[k + 1].v[0] = i * ( 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;
1617 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1618 gTri[k ].v[1] = i * ( NV + 1 ) + j + 1;
1619 gTri[k ].v[2] = ( i + 1 ) * ( NV + 1 ) + j;
1620 gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j;
1621 gTri[k + 1].v[1] = i * ( NV + 1 ) + j + 1;
1622 gTri[k + 1].v[2] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1625 gTri[k ].v[0] = i * ( NV + 1 ) + j;
1626 gTri[k ].v[1] = ( i + 1 ) * ( NV + 1 ) + j;
1627 gTri[k ].v[2] = i * ( NV + 1 ) + j + 1;
1628 gTri[k + 1].v[0] = ( i + 1 ) * ( NV + 1 ) + j;
1629 gTri[k + 1].v[1] = ( i + 1 ) * ( NV + 1 ) + j + 1;
1630 gTri[k + 1].v[2] = i * ( NV + 1 ) + j + 1;
1637 sprintf(CSV,"csv%03d.csv",Decimate);
1639 for(i=0; i<gNumNodes; i++)
1642 fprintf(f,"%g,%g,%g\n",gNode[i].p[0],gNode[i].p[1],gNode[i].p[2]);
1646 for ( i = 0; i < gNumTris; i++ )
1647 PlaneFromPoints( gNode[gTri[i].v[0]].p,
1648 gNode[gTri[i].v[1]].p,
1649 gNode[gTri[i].v[2]].p,
1652 // Hydra: snap-to-grid begin
1653 if ( SnapToGrid > 0 ) {
1654 for ( i = 0; i < NH; i++ )
1656 for ( j = 0; j < NV; j++ )
1662 xyz[i][j].p[1] = CalculateSnapValue( xyz[i][j].p[1] );
1666 xyz[i][j].p[0] = CalculateSnapValue( xyz[i][j].p[0] );
1669 xyz[i][j].p[2] = CalculateSnapValue( xyz[i][j].p[2] );
1674 // Hydra: snap-to-grid end
1676 //=============================================================
1677 double Nearest( double x, double dx ){
1680 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1681 if ( fabs( xx ) < dx / 2 ) {
1686 //=============================================================
1687 double NoMoreThan( double x, double dx ){
1690 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1696 //=============================================================
1697 double AtLeast( double x, double dx ){
1700 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1706 //=============================================================
1707 double LessThan( double x,double dx ){
1710 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1716 //=============================================================
1717 double MoreThan( double x,double dx ){
1720 xx = (double)( floor( x / dx - 0.5 ) + 1. ) * dx;
1725 //=============================================================
1726 void SubdividePlasma( int i0,int j0,int i1,int j1 ){
1729 double r; // NOTE: This is used to keep the random number sequence the same
1730 // when we fix a point. If we did NOT do this, then simply
1731 // fixing a point at its current value would change the entire
1734 i = ( i0 + i1 ) / 2;
1735 j = ( j0 + j1 ) / 2;
1736 if ( i1 > i0 + 1 ) {
1737 if ( !xyz[i][j0].done ) {
1738 xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] +
1739 ( xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) +
1740 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1741 xyz[i][j0].done = 1;
1746 if ( ( j1 > j0 ) && ( !xyz[i][j1].done ) ) {
1747 xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] +
1748 ( xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 ) +
1749 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1750 xyz[i][j1].done = 1;
1756 if ( j1 > j0 + 1 ) {
1757 if ( !xyz[i0][j].done ) {
1758 xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] +
1759 ( xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) +
1760 ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1761 xyz[i0][j].done = 1;
1766 if ( ( i1 > i0 ) && ( !xyz[i1][j].done ) ) {
1767 xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] +
1768 ( xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 ) +
1769 ( (double)( j - j0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1770 xyz[i1][j].done = 1;
1776 if ( ( i1 > i0 + 1 ) && ( j1 > j0 + 1 ) ) {
1777 if ( !xyz[i][j].done ) {
1778 z1 = xyz[i0][j].pp[2] +
1779 ( xyz[i1][j].pp[2] - xyz[i0][j].pp[2] ) * (double)( i - i0 ) / (double)( i1 - i0 );
1780 z2 = xyz[i][j0].pp[2] +
1781 ( xyz[i][j1].pp[2] - xyz[i][j0].pp[2] ) * (double)( j - j0 ) / (double)( j1 - j0 );
1782 xyz[i][j].pp[2] = ( z1 + z2 ) / 2. +
1783 ( (double)( i - i0 ) ) * ( -Roughness / 2. + Roughness * ( (double)rand() / (double)RAND_MAX ) );
1790 if ( i > i0 + 1 || j > j0 + 1 ) {
1791 SubdividePlasma( i0,j0,i,j );
1793 if ( i1 > i + 1 || j > j0 + 1 ) {
1794 SubdividePlasma( i,j0,i1,j );
1796 if ( i > i0 + 1 || j1 > j0 + 1 ) {
1797 SubdividePlasma( i0,j,i,j1 );
1799 if ( i1 > i + 1 || j1 > j0 + 1 ) {
1800 SubdividePlasma( i,j,i1,j1 );
1803 //==================================================================================
1806 /* use pp[2] values until done to avoid messing with a bunch of
1807 switch statements */
1809 for ( i = 0; i <= NH; i++ )
1811 for ( j = 0; j <= NV; j++ )
1813 if ( FixedPoint( i,j ) ) {
1826 for ( i = 0; i <= NH; i++ )
1828 for ( j = 0; j <= NV; j++ )
1830 if ( xyz[i][j].fixed ) {
1831 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1834 xyz[i][j].pp[2] = xyz[i][j].p[1];
1841 for ( i = 0; i <= NH; i++ )
1843 for ( j = 0; j <= NV; j++ )
1845 if ( xyz[i][j].fixed ) {
1846 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1849 xyz[i][j].pp[2] = xyz[i][j].p[0];
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[2];
1869 SubdividePlasma( 0,0,NH,NV );
1874 for ( i = 0; i <= NH; i++ )
1876 for ( j = 0; j <= NV; j++ )
1878 xyz[i][j].p[1] = xyz[i][j].pp[2];
1884 for ( i = 0; i <= NH; i++ )
1886 for ( j = 0; j <= NV; j++ )
1888 xyz[i][j].p[0] = xyz[i][j].pp[2];
1893 for ( i = 0; i <= NH; i++ )
1895 for ( j = 0; j <= NV; j++ )
1897 xyz[i][j].p[2] = xyz[i][j].pp[2];
1903 //===========================================================================
1904 bool FixedPoint( int i, int j ){
1905 if ( xyz[i][j].fixed ) {
1908 return !CanEdit( i,j );
1910 //===========================================================================
1911 bool CanEdit( int i, int j ){
1912 if ( FixBorders && ( ( WaveType == WAVE_COS_SIN ) || ( WaveType == WAVE_ROUGH_ONLY ) ) ) {
1926 if ( i == 0 && j == 0 ) {
1929 if ( i == NH && j == 0 ) {
1932 if ( i == 0 && j == NV ) {
1935 if ( i == NH && j == NV ) {
1940 /*============================================================================
1942 Determines which triangle in the gTri array bounds the input point. Doesn't
1943 do anything special with border points.
1945 int TriangleFromPoint( double x, double y ){
1952 for ( j = 0, tri = -1; j < gNumTris && tri == -1; j++ )
1955 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1],
1956 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1] ) < 0. ) {
1960 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1],
1961 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1] ) < 0. ) {
1965 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1],
1966 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1] ) < 0. ) {
1974 /*============================================================================
1976 Determines minimum height to place the player start such that he doesn't
1977 intersect any surface brushes.
1979 int PlayerStartZ( double x, double y ){
1987 t[0] = TriangleFromPoint( x,y );
1988 t[1] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[0] );
1989 t[2] = TriangleFromPoint( x + PlayerBox[Game].x[0],y + PlayerBox[Game].y[1] );
1990 t[3] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[0] );
1991 t[4] = TriangleFromPoint( x + PlayerBox[Game].x[1],y + PlayerBox[Game].y[1] );
1993 for ( k = 0; k < 5; k++ )
1995 zt = ( gTri[t[k]].plane.dist -
1996 gTri[t[k]].plane.normal[0] * x -
1997 gTri[t[k]].plane.normal[1] * y ) /
1998 gTri[t[k]].plane.normal[2];
2001 return (int)( AtLeast( z,2. ) - PlayerBox[Game].z[0] );
2003 //=============================================================
2004 void XYZtoV( XYZ *xyz, vec3 *v ){
2005 v[0][0] = (vec)Nearest( xyz->p[0],2. );
2006 v[0][1] = (vec)Nearest( xyz->p[1],2. );
2007 v[0][2] = (vec)Nearest( xyz->p[2],2. );
2010 //=============================================================
2011 void MakePatch( patchMesh_t *p ){
2013 char shadername[64 + 9];
2015 ret = g_FuncTable.m_pfnCreatePatchHandle();
2016 // strcpy(shadername, "textures/");
2017 // strcpy(shadername+9, Texture[Game][0]);
2018 strcpy( shadername, Texture[Game][0] );
2019 g_FuncTable.m_pfnCommitPatchHandleToMap( ret,p,shadername );
2020 g_FuncTable.m_pfnReleasePatchHandles();
2023 //=============================================================
2024 void MakeBrush( BRUSH *brush ){
2027 _QERFaceData QERFaceData;
2029 if ( g_FuncTable.m_pfnCreateBrushHandle == NULL ) {
2030 g_FuncTable.m_pfnMessageBox( g_pRadiantWnd,"m_pfnCreateBrushHandle==NULL","Aw damn",0, NULL );
2033 vp = ( g_FuncTable.m_pfnCreateBrushHandle )();
2037 for ( i = 0; i < brush->NumFaces; i++ )
2039 if ( !strncmp( brush->face[i].texture, "textures/", 9 ) ) {
2040 strcpy( QERFaceData.m_TextureName,brush->face[i].texture );
2044 strcpy( QERFaceData.m_TextureName,"textures/" );
2045 strcpy( QERFaceData.m_TextureName + 9,brush->face[i].texture );
2047 QERFaceData.m_nContents = brush->face[i].Contents;
2048 QERFaceData.m_nFlags = brush->face[i].Surface;
2049 QERFaceData.m_nValue = brush->face[i].Value;
2050 QERFaceData.m_fShift[0] = brush->face[i].Shift[0];
2051 QERFaceData.m_fShift[1] = brush->face[i].Shift[1];
2052 QERFaceData.m_fRotate = brush->face[i].Rotate;
2053 QERFaceData.m_fScale[0] = brush->face[i].Scale[0];
2054 QERFaceData.m_fScale[1] = brush->face[i].Scale[1];
2055 QERFaceData.m_v1[0] = brush->face[i].v[0][0];
2056 QERFaceData.m_v1[1] = brush->face[i].v[0][1];
2057 QERFaceData.m_v1[2] = brush->face[i].v[0][2];
2058 QERFaceData.m_v2[0] = brush->face[i].v[1][0];
2059 QERFaceData.m_v2[1] = brush->face[i].v[1][1];
2060 QERFaceData.m_v2[2] = brush->face[i].v[1][2];
2061 QERFaceData.m_v3[0] = brush->face[i].v[2][0];
2062 QERFaceData.m_v3[1] = brush->face[i].v[2][1];
2063 QERFaceData.m_v3[2] = brush->face[i].v[2][2];
2064 QERFaceData.m_bBPrimit = false;
2065 ( g_FuncTable.m_pfnAddFaceData )( vp,&QERFaceData );
2067 if ( g_FuncTable.m_pfnCommitBrushHandle != NULL ) {
2068 if ( h_func_group ) {
2069 g_FuncTable.m_pfnCommitBrushHandleToEntity( vp,h_func_group );
2072 g_FuncTable.m_pfnCommitBrushHandle( vp );
2076 //=============================================================
2077 void OpenFuncGroup(){
2078 if ( g_FuncTable.m_pfnAllocateEpair != NULL ) {
2081 h_func_group = g_FuncTable.m_pfnCreateEntityHandle();
2082 ep = g_EntityTable.m_pfnAllocateEpair( "classname","func_group" );
2083 g_EntityTable.m_pfnSetEntityKeyValList( (entity_t *)h_func_group,ep );
2085 if ( AddTerrainKey ) { // ^Fishman - Add terrain key to func_group.
2087 terrainkey = g_FuncTable.m_pfnCreateEntityHandle();
2088 ep2 = g_EntityTable.m_pfnAllocateEpair( "terrain","1" );
2090 g_EntityTable.m_pfnSetEntityKeyValList( (entity_t *)h_func_group,ep );
2094 h_func_group = NULL;
2097 //=============================================================
2098 void CloseFuncGroup(){
2099 if ( h_func_group ) {
2100 g_FuncTable.m_pfnCommitEntityHandleToMap( h_func_group );
2102 if ( g_FuncTable.m_pfnSysUpdateWindows != NULL ) {
2103 g_FuncTable.m_pfnSysUpdateWindows( W_ALL );