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)
41 // simple uncomplicated snapping, rounding both UP and DOWN to the nearest
45 snapvalue = (int)value / SnapToGrid;
46 if ((long)value % SnapToGrid < (SnapToGrid / 2)) // Snap Downwards if less than halfway between to grid units
47 value = snapvalue * SnapToGrid;
48 else // Snap Upwards if more than halfway between to grid units
49 value = (snapvalue+1) * SnapToGrid;
53 // Hydra : snap-to-grid end
55 //=============================================================
58 if(WaveType == WAVE_BITMAP && !gbmp.colors) return FALSE;
59 if(NH < 1) return FALSE;
60 if(NH > MAX_ROWS) return FALSE;
61 if(NV < 1) return FALSE;
62 if(NV > MAX_ROWS) return FALSE;
63 if(Hll >= Hur) return FALSE;
64 if(Vll >= Vur) return FALSE;
68 //=============================================================
83 memset(&p,0,sizeof(patchMesh_t));
85 // Generate control points in pp array to give desired values currently
112 xyz[i][j].pp[k1] = xyz[i][j].p[k1];
113 xyz[i][j].pp[k2] = xyz[i][j].p[k2];
116 for(i=0; i<=NH; i+=2)
118 for(j=0; j<=NV; j+=2)
119 xyz[i][j].pp[k3] = xyz[i][j].p[k3];
123 for(j=0; j<=NV; j+=2)
125 xyz[i][j].pp[k3] = (4*xyz[i][j].p[k3] - xyz[i-1][j].p[k3] - xyz[i+1][j].p[k3])/2;
130 for(i=0; i<=NH; i+=2)
132 xyz[i][j].pp[k3] = (4*xyz[i][j].p[k3] - xyz[i][j-1].p[k3] - xyz[i][j+1].p[k3])/2;
139 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]
140 - xyz[i+1][j-1].p[k3] - 2*xyz[i-1][j].p[k3] - 2*xyz[i+1][j].p[k3]
141 - xyz[i-1][j+1].p[k3] - 2*xyz[i][j+1].p[k3] - xyz[i+1][j+1].p[k3])/4;
149 if(( (NH_remain-1) % 14) == 0)
151 else if(( (NH_remain-1) % 12) == 0)
153 else if(( (NH_remain-1) % 10) == 0)
155 else if(( (NH_remain-1) % 8) == 0)
157 else if(( (NH_remain-1) % 6) == 0)
159 else if(( (NH_remain-1) % 4) == 0)
161 else if(( (NH_remain-1) % 2) == 0)
163 else if(NH_remain > 16)
165 else if(NH_remain > 4)
169 while( NH_patch > 3 && (NH_patch-1)*dh > 512 )
171 NH_remain -= (NH_patch-1);
174 sprintf(szOops,"Oops... screwed up with NH=%d",NH);
175 g_FuncTable.m_pfnMessageBox(NULL,szOops,"Uh oh");
181 if(( (NV_remain-1) % 14) == 0)
183 else if(( (NV_remain-1) % 12) == 0)
185 else if(( (NV_remain-1) % 10) == 0)
187 else if(( (NV_remain-1) % 8) == 0)
189 else if(( (NV_remain-1) % 6) == 0)
191 else if(( (NV_remain-1) % 4) == 0)
193 else if(( (NV_remain-1) % 2) == 0)
195 else if(NV_remain > 16)
197 else if(NV_remain > 4)
201 while( NV_patch > 3 && (NV_patch-1)*dh > 512 )
203 NV_remain -= (NV_patch-1);
206 sprintf(szOops,"Oops... screwed up with NV=%d",NV);
207 g_FuncTable.m_pfnMessageBox(NULL,szOops,"Uh oh");
212 p.type = PATCH_GENERIC;
213 for(i=0; i<NH_patch; i++)
220 ii = i0 + NH_patch - 1 - i;
225 for(j=0; j<NV_patch; j++)
227 p.ctrl[i][j].xyz[0] = (float)xyz[ii][j0+j].pp[0];
228 p.ctrl[i][j].xyz[1] = (float)xyz[ii][j0+j].pp[1];
229 p.ctrl[i][j].xyz[2] = (float)xyz[ii][j0+j].pp[2];
230 p.ctrl[i][j].st[0] = (float)i;
231 p.ctrl[i][j].st[1] = (float)j;
243 //=============================================================
253 vec3_t PlaneNormal,SurfNormal;
261 strcpy(surftext,Texture[Game][0]);
262 strcpy(sidetext,(strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
263 strcpy(surftext2,(strlen(Texture[Game][2]) ? Texture[Game][2] : Texture[Game][0]));
265 // if surftext2 is identical to surftext, there's no need to
266 // check surface angle
267 if(!g_strcasecmp(surftext,surftext2))
272 Steep = (float)cos((double)SlantAngle/57.2957795);
275 case PLANE_XY0: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
276 case PLANE_XY1: PlaneNormal[0]= 0.;PlaneNormal[1]= 0.;PlaneNormal[2]=-1.;break;
277 case PLANE_XZ0: PlaneNormal[0]= 0.;PlaneNormal[1]= 1.;PlaneNormal[2]= 1.;break;
278 case PLANE_XZ1: PlaneNormal[0]= 0.;PlaneNormal[1]=-1.;PlaneNormal[2]= 1.;break;
279 case PLANE_YZ0: PlaneNormal[0]= 1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
280 case PLANE_YZ1: PlaneNormal[0]=-1.;PlaneNormal[1]= 0.;PlaneNormal[2]= 1.;break;
292 VectorCopy(xyz[i ][j ].p, v[0].p);
298 VectorCopy(xyz[i+1][j ].p, v[1].p);
299 VectorCopy(xyz[i+1][j+1].p, v[2].p);
302 VectorCopy(xyz[i+1][j+1].p, v[1].p);
303 VectorCopy(xyz[i+1][j ].p, v[2].p);
308 VectorCopy(xyz[i ][j ].p, v[0].p);
314 VectorCopy(xyz[i+1][j ].p, v[1].p);
315 VectorCopy(xyz[i ][j+1].p, v[2].p);
318 VectorCopy(xyz[i ][j+1].p, v[1].p);
319 VectorCopy(xyz[i+1][j ].p, v[2].p);
322 VectorCopy(v[0].p,v[3].p);
323 VectorCopy(v[1].p,v[4].p);
324 VectorCopy(v[2].p,v[5].p);
329 v[0].p[1] = backface;
330 v[1].p[1] = backface;
331 v[2].p[1] = backface;
335 v[3].p[0] = backface;
336 v[4].p[0] = backface;
337 v[5].p[0] = backface;
340 v[3].p[2] = backface;
341 v[4].p[2] = backface;
342 v[5].p[2] = backface;
345 brush.Number = i*NV*2+j*2;
347 XYZtoV(&v[0],&brush.face[0].v[0]);
348 XYZtoV(&v[3],&brush.face[0].v[1]);
349 XYZtoV(&v[4],&brush.face[0].v[2]);
350 strcpy(brush.face[0].texture,
351 (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
352 brush.face[0].Shift[0] = (float)TexOffset[0];
353 brush.face[0].Shift[1] = (float)TexOffset[1];
354 brush.face[0].Rotate = 0.;
355 brush.face[0].Scale[0] = (float)TexScale[0];
356 brush.face[0].Scale[1] = (float)TexScale[1];
357 brush.face[0].Contents = contents;
358 brush.face[0].Surface = surface[1];
359 brush.face[0].Value = 0;
361 XYZtoV(&v[1],&brush.face[1].v[0]);
362 XYZtoV(&v[4],&brush.face[1].v[1]);
363 XYZtoV(&v[5],&brush.face[1].v[2]);
364 strcpy(brush.face[1].texture,
365 (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
366 brush.face[1].Shift[0] = (float)TexOffset[0];
367 brush.face[1].Shift[1] = (float)TexOffset[1];
368 brush.face[1].Rotate = 0.;
369 brush.face[1].Scale[0] = (float)TexScale[0];
370 brush.face[1].Scale[1] = (float)TexScale[1];
371 brush.face[1].Contents = contents;
372 brush.face[1].Surface = surface[1];
373 brush.face[1].Value = 0;
375 XYZtoV(&v[2],&brush.face[2].v[0]);
376 XYZtoV(&v[5],&brush.face[2].v[1]);
377 XYZtoV(&v[3],&brush.face[2].v[2]);
378 strcpy(brush.face[2].texture,
379 (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
380 brush.face[2].Shift[0] = (float)TexOffset[0];
381 brush.face[2].Shift[1] = (float)TexOffset[1];
382 brush.face[2].Rotate = 0.;
383 brush.face[2].Scale[0] = (float)TexScale[0];
384 brush.face[2].Scale[1] = (float)TexScale[1];
385 brush.face[2].Contents = contents;
386 brush.face[2].Surface = surface[1];
387 brush.face[2].Value = 0;
389 if(CheckAngle && (Plane==PLANE_XZ0 || Plane==PLANE_XZ1))
391 XYZVectorSubtract(v[4].p,v[3].p,t[0]);
392 XYZVectorSubtract(v[5].p,v[4].p,t[1]);
393 CrossProduct(t[0],t[1],SurfNormal);
394 VectorNormalize(SurfNormal,SurfNormal);
395 if(DotProduct(SurfNormal,PlaneNormal) < Steep)
397 strcpy(surft,surftext2);
402 strcpy(surft,surftext);
408 strcpy(surft,surftext);
412 XYZtoV(&v[3],&brush.face[3].v[0]);
413 XYZtoV(&v[5],&brush.face[3].v[1]);
414 XYZtoV(&v[4],&brush.face[3].v[2]);
415 strcpy(brush.face[3].texture,
416 (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surft : sidetext));
417 brush.face[3].Shift[0] = (float)TexOffset[0];
418 brush.face[3].Shift[1] = (float)TexOffset[1];
419 brush.face[3].Rotate = 0.;
420 brush.face[3].Scale[0] = (float)TexScale[0];
421 brush.face[3].Scale[1] = (float)TexScale[1];
422 brush.face[3].Contents = contents;
423 brush.face[3].Surface = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surf : surface[1]);
424 brush.face[3].Value = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? ArghRad2 : 0);
426 if(CheckAngle && Plane!=PLANE_XZ0 && Plane!=PLANE_XZ1)
428 XYZVectorSubtract(v[2].p,v[0].p,t[0]);
429 XYZVectorSubtract(v[1].p,v[2].p,t[1]);
430 CrossProduct(t[0],t[1],SurfNormal);
431 VectorNormalize(SurfNormal,SurfNormal);
432 if(DotProduct(SurfNormal,PlaneNormal) < Steep)
434 strcpy(surft,surftext2);
439 strcpy(surft,surftext);
445 strcpy(surft,surftext);
449 XYZtoV(&v[0],&brush.face[4].v[0]);
450 XYZtoV(&v[1],&brush.face[4].v[1]);
451 XYZtoV(&v[2],&brush.face[4].v[2]);
452 strcpy(brush.face[4].texture,
453 (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? sidetext : surft));
454 brush.face[4].Shift[0] = (float)TexOffset[0];
455 brush.face[4].Shift[1] = (float)TexOffset[1];
456 brush.face[4].Rotate = 0.;
457 brush.face[4].Scale[0] = (float)TexScale[0];
458 brush.face[4].Scale[1] = (float)TexScale[1];
459 brush.face[4].Contents = contents;
460 brush.face[4].Surface = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surface[1] : surf);
461 brush.face[4].Value = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? 0 : ArghRad2);
466 VectorCopy(xyz[i ][j+1].p,v[0].p);
472 VectorCopy(xyz[i ][j ].p,v[1].p);
473 VectorCopy(xyz[i+1][j+1].p,v[2].p);
476 VectorCopy(xyz[i+1][j+1].p,v[1].p);
477 VectorCopy(xyz[i ][j ].p,v[2].p);
482 VectorCopy(xyz[i ][j+1].p,v[0].p);
488 VectorCopy(xyz[i+1][j ].p,v[1].p);
489 VectorCopy(xyz[i+1][j+1].p,v[2].p);
492 VectorCopy(xyz[i+1][j+1].p,v[1].p);
493 VectorCopy(xyz[i+1][j ].p,v[2].p);
496 VectorCopy(v[0].p,v[3].p);
497 VectorCopy(v[1].p,v[4].p);
498 VectorCopy(v[2].p,v[5].p);
503 v[0].p[1] = backface;
504 v[1].p[1] = backface;
505 v[2].p[1] = backface;
509 v[3].p[0] = backface;
510 v[4].p[0] = backface;
511 v[5].p[0] = backface;
514 v[3].p[2] = backface;
515 v[4].p[2] = backface;
516 v[5].p[2] = backface;
518 brush.Number = i*NV*2+j*2+1;
520 XYZtoV(&v[0],&brush.face[0].v[0]);
521 XYZtoV(&v[3],&brush.face[0].v[1]);
522 XYZtoV(&v[4],&brush.face[0].v[2]);
523 strcpy(brush.face[0].texture,
524 (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
525 brush.face[0].Shift[0] = (float)TexOffset[0];
526 brush.face[0].Shift[1] = (float)TexOffset[1];
527 brush.face[0].Rotate = 0.;
528 brush.face[0].Scale[0] = (float)TexScale[0];
529 brush.face[0].Scale[1] = (float)TexScale[1];
530 brush.face[0].Contents = contents;
531 brush.face[0].Surface = surface[1];
532 brush.face[0].Value = 0;
534 XYZtoV(&v[1],&brush.face[1].v[0]);
535 XYZtoV(&v[4],&brush.face[1].v[1]);
536 XYZtoV(&v[5],&brush.face[1].v[2]);
537 strcpy(brush.face[1].texture,
538 (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
539 brush.face[1].Shift[0] = (float)TexOffset[0];
540 brush.face[1].Shift[1] = (float)TexOffset[1];
541 brush.face[1].Rotate = 0.;
542 brush.face[1].Scale[0] = (float)TexScale[0];
543 brush.face[1].Scale[1] = (float)TexScale[1];
544 brush.face[1].Contents = contents;
545 brush.face[1].Surface = surface[1];
546 brush.face[1].Value = 0;
548 XYZtoV(&v[2],&brush.face[2].v[0]);
549 XYZtoV(&v[5],&brush.face[2].v[1]);
550 XYZtoV(&v[3],&brush.face[2].v[2]);
551 strcpy(brush.face[2].texture,
552 (strlen(Texture[Game][1]) ? Texture[Game][1] : Texture[Game][0]));
553 brush.face[2].Shift[0] = (float)TexOffset[0];
554 brush.face[2].Shift[1] = (float)TexOffset[1];
555 brush.face[2].Rotate = 0.;
556 brush.face[2].Scale[0] = (float)TexScale[0];
557 brush.face[2].Scale[1] = (float)TexScale[1];
558 brush.face[2].Contents = contents;
559 brush.face[2].Surface = surface[1];
560 brush.face[2].Value = 0;
562 if(CheckAngle && (Plane==PLANE_XZ0 || Plane==PLANE_XZ1))
564 XYZVectorSubtract(v[4].p,v[3].p,t[0]);
565 XYZVectorSubtract(v[5].p,v[4].p,t[1]);
566 CrossProduct(t[0],t[1],SurfNormal);
567 VectorNormalize(SurfNormal,SurfNormal);
568 if(DotProduct(SurfNormal,PlaneNormal) < Steep)
570 strcpy(surft,surftext2);
575 strcpy(surft,surftext);
581 strcpy(surft,surftext);
584 XYZtoV(&v[3],&brush.face[3].v[0]);
585 XYZtoV(&v[5],&brush.face[3].v[1]);
586 XYZtoV(&v[4],&brush.face[3].v[2]);
587 strcpy(brush.face[3].texture,
588 (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surft : sidetext));
589 brush.face[3].Shift[0] = (float)TexOffset[0];
590 brush.face[3].Shift[1] = (float)TexOffset[1];
591 brush.face[3].Rotate = 0.;
592 brush.face[3].Scale[0] = (float)TexScale[0];
593 brush.face[3].Scale[1] = (float)TexScale[1];
594 brush.face[3].Contents = contents;
595 brush.face[3].Surface = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surf : surface[1]);
596 brush.face[3].Value = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? ArghRad2 : 0);
598 if(CheckAngle && Plane!=PLANE_XZ0 && Plane!=PLANE_XZ1)
600 XYZVectorSubtract(v[2].p,v[0].p,t[0]);
601 XYZVectorSubtract(v[1].p,v[2].p,t[1]);
602 CrossProduct(t[0],t[1],SurfNormal);
603 VectorNormalize(SurfNormal,SurfNormal);
604 if(DotProduct(SurfNormal,PlaneNormal) < Steep)
606 strcpy(surft,surftext2);
611 strcpy(surft,surftext);
617 strcpy(surft,surftext);
620 XYZtoV(&v[0],&brush.face[4].v[0]);
621 XYZtoV(&v[1],&brush.face[4].v[1]);
622 XYZtoV(&v[2],&brush.face[4].v[2]);
623 strcpy(brush.face[4].texture,
624 (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? sidetext : surft));
625 brush.face[4].Shift[0] = (float)TexOffset[0];
626 brush.face[4].Shift[1] = (float)TexOffset[1];
627 brush.face[4].Rotate = 0.;
628 brush.face[4].Scale[0] = (float)TexScale[0];
629 brush.face[4].Scale[1] = (float)TexScale[1];
630 brush.face[4].Contents = contents;
631 brush.face[4].Surface = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? surface[1] : surf);
632 brush.face[4].Value = (Plane==PLANE_XZ0 || Plane==PLANE_XZ1 ? 0 : ArghRad2);
639 if( AddHints || GimpHints )
641 int detail, i1, j1, N;
651 strcpy(hint,"generic/misc/hint");
652 strcpy(skip,"generic/misc/skip");
655 strcpy(hint,"general/hint");
656 strcpy(skip,"general/hint"); // Heretic2 doesn't have a skip texture
659 strcpy(hint,"common/0_hint");
660 strcpy(skip,"common/0_skip");
667 strcpy(hint,"textures/common/hint");
668 strcpy(skip,"textures/common/skip");
671 strcpy(hint,"e1u1/hint");
672 strcpy(skip,"e1u1/skip");
679 detail = CONTENTS_DETAIL;
688 // For detail hint brushes, no need to use a hint brush over
689 // EVERY grid square... it would be redundant. Instead use
690 // a checkerboard pattern
691 if((i+j)%2) continue;
695 VectorCopy(xyz[i ][j ].p, v[0].p);
701 VectorCopy(xyz[i1][j ].p, v[1].p);
702 VectorCopy(xyz[i1][j1].p, v[2].p);
703 VectorCopy(xyz[i ][j1].p, v[3].p);
706 VectorCopy(xyz[i ][j1].p, v[1].p);
707 VectorCopy(xyz[i1][j1].p, v[2].p);
708 VectorCopy(xyz[i1][j ].p, v[3].p);
711 VectorCopy(v[0].p,v[4].p);
712 VectorCopy(v[1].p,v[5].p);
713 VectorCopy(v[2].p,v[6].p);
714 VectorCopy(v[3].p,v[7].p);
719 front = LessThan(zmin,32.);
720 v[4].p[2] = backface;
721 v[5].p[2] = backface;
722 v[6].p[2] = backface;
723 v[7].p[2] = backface;
726 front = MoreThan(ymax,32.);
727 v[0].p[1] = backface;
728 v[1].p[1] = backface;
729 v[2].p[1] = backface;
730 v[3].p[1] = backface;
733 front = LessThan(ymin,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 = MoreThan(xmax,32.);
741 v[4].p[0] = backface;
742 v[5].p[0] = backface;
743 v[6].p[0] = backface;
744 v[7].p[0] = backface;
747 front = LessThan(xmin,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 = MoreThan(zmax,32.);
755 v[4].p[2] = backface;
756 v[5].p[2] = backface;
757 v[6].p[2] = backface;
758 v[7].p[2] = backface;
766 v[5].p[1] = v[4].p[1];
767 v[6].p[1] = v[4].p[1];
768 v[7].p[1] = v[4].p[1];
773 v[1].p[0] = v[0].p[0];
774 v[2].p[0] = v[0].p[0];
775 v[3].p[0] = v[0].p[0];
779 v[1].p[2] = v[0].p[2];
780 v[2].p[2] = v[0].p[2];
781 v[3].p[2] = v[0].p[2];
786 XYZtoV(&v[0],&brush.face[0].v[0]);
787 XYZtoV(&v[1],&brush.face[0].v[1]);
788 XYZtoV(&v[2],&brush.face[0].v[2]);
789 strcpy(brush.face[0].texture,skip);
790 brush.face[0].Shift[0] = 0.;
791 brush.face[0].Shift[1] = 0.;
792 brush.face[0].Rotate = 0.;
793 brush.face[0].Scale[0] = 1.;
794 brush.face[0].Scale[1] = 1.;
795 brush.face[0].Contents = detail;
796 brush.face[0].Surface = SURF_SKIP;
797 brush.face[0].Value = 0;
799 XYZtoV(&v[4],&brush.face[1].v[0]);
800 XYZtoV(&v[7],&brush.face[1].v[1]);
801 XYZtoV(&v[6],&brush.face[1].v[2]);
802 strcpy(brush.face[1].texture,skip);
803 brush.face[1].Shift[0] = 0.;
804 brush.face[1].Shift[1] = 0.;
805 brush.face[1].Rotate = 0.;
806 brush.face[1].Scale[0] = 1.;
807 brush.face[1].Scale[1] = 1.;
808 brush.face[1].Contents = detail;
809 brush.face[1].Surface = SURF_SKIP;
810 brush.face[1].Value = 0;
812 XYZtoV(&v[0],&brush.face[2].v[0]);
813 XYZtoV(&v[4],&brush.face[2].v[1]);
814 XYZtoV(&v[5],&brush.face[2].v[2]);
815 strcpy(brush.face[2].texture,hint);
816 brush.face[2].Shift[0] = 0.;
817 brush.face[2].Shift[1] = 0.;
818 brush.face[2].Rotate = 0.;
819 brush.face[2].Scale[0] = 1.;
820 brush.face[2].Scale[1] = 1.;
821 brush.face[2].Contents = detail;
822 brush.face[2].Surface = SURF_HINT;
823 brush.face[2].Value = 0;
825 XYZtoV(&v[1],&brush.face[3].v[0]);
826 XYZtoV(&v[5],&brush.face[3].v[1]);
827 XYZtoV(&v[6],&brush.face[3].v[2]);
828 strcpy(brush.face[3].texture,hint);
829 brush.face[3].Shift[0] = 0.;
830 brush.face[3].Shift[1] = 0.;
831 brush.face[3].Rotate = 0.;
832 brush.face[3].Scale[0] = 1.;
833 brush.face[3].Scale[1] = 1.;
834 brush.face[3].Contents = detail;
835 brush.face[3].Surface = SURF_HINT;
836 brush.face[3].Value = 0;
838 XYZtoV(&v[2],&brush.face[4].v[0]);
839 XYZtoV(&v[6],&brush.face[4].v[1]);
840 XYZtoV(&v[7],&brush.face[4].v[2]);
841 strcpy(brush.face[4].texture,hint);
842 brush.face[4].Shift[0] = 0.;
843 brush.face[4].Shift[1] = 0.;
844 brush.face[4].Rotate = 0.;
845 brush.face[4].Scale[0] = 1.;
846 brush.face[4].Scale[1] = 1.;
847 brush.face[4].Contents = detail;
848 brush.face[4].Surface = SURF_HINT;
849 brush.face[4].Value = 0;
851 XYZtoV(&v[3],&brush.face[5].v[0]);
852 XYZtoV(&v[7],&brush.face[5].v[1]);
853 XYZtoV(&v[4],&brush.face[5].v[2]);
854 strcpy(brush.face[5].texture,hint);
855 brush.face[5].Shift[0] = 0.;
856 brush.face[5].Shift[1] = 0.;
857 brush.face[5].Rotate = 0.;
858 brush.face[5].Scale[0] = 1.;
859 brush.face[5].Scale[1] = 1.;
860 brush.face[5].Contents = detail;
861 brush.face[5].Surface = SURF_HINT;
862 brush.face[5].Value = 0;
872 // these brush parameters never change
876 strcpy(brush.face[i].texture,hint);
877 brush.face[i].Shift[0] = 0.;
878 brush.face[i].Shift[1] = 0.;
879 brush.face[i].Rotate = 0.;
880 brush.face[i].Scale[0] = 1.;
881 brush.face[i].Scale[1] = 1.;
882 brush.face[i].Contents = 0;
883 brush.face[i].Surface = SURF_HINT;
884 brush.face[i].Value = 0;
896 VectorCopy(xyz[i ][j ].p, v[0].p);
902 VectorCopy(xyz[i+1][j ].p, v[1].p);
903 VectorCopy(xyz[i+1][j+1].p, v[2].p);
906 VectorCopy(xyz[i+1][j+1].p, v[1].p);
907 VectorCopy(xyz[i+1][j ].p, v[2].p);
912 VectorCopy(xyz[i ][j ].p, v[0].p);
918 VectorCopy(xyz[i+1][j ].p, v[1].p);
919 VectorCopy(xyz[i ][j+1].p, v[2].p);
922 VectorCopy(xyz[i ][j+1].p, v[1].p);
923 VectorCopy(xyz[i+1][j ].p, v[2].p);
931 VectorCopy(xyz[i ][j+1].p,v[0].p);
937 VectorCopy(xyz[i ][j ].p,v[1].p);
938 VectorCopy(xyz[i+1][j+1].p,v[2].p);
941 VectorCopy(xyz[i+1][j+1].p,v[1].p);
942 VectorCopy(xyz[i ][j ].p,v[2].p);
947 VectorCopy(xyz[i ][j+1].p,v[0].p);
953 VectorCopy(xyz[i+1][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+1][j ].p,v[2].p);
962 VectorCopy(v[0].p,v[3].p);
963 VectorCopy(v[1].p,v[4].p);
964 VectorCopy(v[2].p,v[5].p);
968 v[0].p[2] += HINT_OFFSET;
969 v[1].p[2] += HINT_OFFSET;
970 v[2].p[2] += HINT_OFFSET;
971 // v[3].p[2] = backface;
972 // v[4].p[2] = backface;
973 // v[5].p[2] = backface;
976 v[0].p[2] -= HINT_OFFSET;
977 v[1].p[2] -= HINT_OFFSET;
978 v[2].p[2] -= HINT_OFFSET;
979 // v[3].p[2] = backface;
980 // v[4].p[2] = backface;
981 // v[5].p[2] = backface;
984 // v[0].p[1] = backface;
985 // v[1].p[1] = backface;
986 // v[2].p[1] = backface;
987 v[3].p[1] += HINT_OFFSET;
988 v[4].p[1] += HINT_OFFSET;
989 v[5].p[1] += HINT_OFFSET;
992 // v[0].p[1] = backface;
993 // v[1].p[1] = backface;
994 // v[2].p[1] = backface;
995 v[3].p[1] -= HINT_OFFSET;
996 v[4].p[1] -= HINT_OFFSET;
997 v[5].p[1] -= HINT_OFFSET;
1000 v[0].p[0] += HINT_OFFSET;
1001 v[1].p[0] += HINT_OFFSET;
1002 v[2].p[0] += HINT_OFFSET;
1003 // v[3].p[0] = backface;
1004 // v[4].p[0] = backface;
1005 // v[5].p[0] = backface;
1008 v[0].p[0] -= HINT_OFFSET;
1009 v[1].p[0] -= HINT_OFFSET;
1010 v[2].p[0] -= HINT_OFFSET;
1011 // v[3].p[0] = backface;
1012 // v[4].p[0] = backface;
1013 // v[5].p[0] = backface;
1017 XYZtoV(&v[0],&brush.face[0].v[0]);
1018 XYZtoV(&v[3],&brush.face[0].v[1]);
1019 XYZtoV(&v[4],&brush.face[0].v[2]);
1021 XYZtoV(&v[1],&brush.face[1].v[0]);
1022 XYZtoV(&v[4],&brush.face[1].v[1]);
1023 XYZtoV(&v[5],&brush.face[1].v[2]);
1025 XYZtoV(&v[2],&brush.face[2].v[0]);
1026 XYZtoV(&v[5],&brush.face[2].v[1]);
1027 XYZtoV(&v[3],&brush.face[2].v[2]);
1029 XYZtoV(&v[3],&brush.face[3].v[0]);
1030 XYZtoV(&v[5],&brush.face[3].v[1]);
1031 XYZtoV(&v[4],&brush.face[3].v[2]);
1033 XYZtoV(&v[0],&brush.face[4].v[0]);
1034 XYZtoV(&v[1],&brush.face[4].v[1]);
1035 XYZtoV(&v[2],&brush.face[4].v[2]);
1042 } // endif AddHints==1
1048 //=============================================================
1051 extern void MapOut(int,int,NODE *,TRI *);
1052 extern bool SingleBrushSelected;
1055 if(!ValidSurface()) return;
1057 ghCursorCurrent = LoadCursor(NULL,IDC_WAIT);
1058 SetCursor(ghCursorCurrent);
1060 if(SingleBrushSelected) g_FuncTable.m_pfnDeleteSelection();
1065 if(Game==QUAKE3 && UsePatches != 0)
1068 if(Decimate > 0 && (Game != QUAKE3 || UsePatches==0) )
1070 MapOut(gNumNodes,gNumTris,gNode,gTri);
1072 ghCursorCurrent = ghCursorDefault;
1073 SetCursor(ghCursorCurrent);
1079 // HL doesn't have detail property
1080 if((Game != HALFLIFE) && UseDetail) contents += CONTENTS_DETAIL;
1081 // HL and Q3 don't have ladder property
1082 if((Game != HALFLIFE && Game != QUAKE3) && UseLadder) contents += CONTENTS_LADDER;
1083 // Genesis requires solid property to be set explicitly
1084 if(Game == GENESIS3D) contents |= CONTENTS_SOLID;
1085 // Heretic 2 uses different sounds (in surface props) for different texture types
1086 if(Game == HERETIC2)
1088 surface[0] = GetDefSurfaceProps(Texture[Game][0]);
1089 surface[1] = GetDefSurfaceProps(Texture[Game][1]);
1090 surface[2] = GetDefSurfaceProps(Texture[Game][2]);
1098 if(Game!=QUAKE3 || UsePatches == 0)
1102 ghCursorCurrent = ghCursorDefault;
1103 SetCursor(ghCursorCurrent);
1107 //=============================================================
1110 extern void MakeDecimatedMap(int *, int *, NODE **, TRI **);
1115 double delta, dr, rate;
1116 double range, maxrange;
1125 if(!ValidSurface()) return;
1134 for(i=0; i<=NH; i++)
1142 xyz[i][j].p[0] = Hll + i*dh;
1143 xyz[i][j].p[2] = Vll + j*dv;
1147 xyz[i][j].p[1] = Hll + i*dh;
1148 xyz[i][j].p[2] = Vll + j*dv;
1151 xyz[i][j].p[0] = Hll + i*dh;
1152 xyz[i][j].p[1] = Vll + j*dv;
1157 if(WaveType == WAVE_BITMAP)
1158 GenerateBitmapMapping();
1160 else if(WaveType == WAVE_FORMULA)
1165 // Initialize Z values using bilinear interpolation
1166 for(i=0; i<=NH; i++)
1168 zl = Z00 + i*(Z10 - Z00)/NH;
1169 zu = Z01 + i*(Z11 - Z01)/NH;
1174 for(j=0; j<=NV; j++)
1175 xyz[i][j].p[1] = zl + j*(zu-zl)/NV;
1179 for(j=0; j<=NV; j++)
1180 xyz[i][j].p[0] = zl + j*(zu-zl)/NV;
1183 for(j=0; j<=NV; j++)
1184 xyz[i][j].p[2] = zl + j*(zu-zl)/NV;
1194 NHalfcycles = (int)((Hur-Hll)/(WaveLength/2.));
1195 NHalfcycles = max(NHalfcycles,1);
1196 wh = 2.*(Hur-Hll)/NHalfcycles;
1197 NHalfcycles = (int)((Vur-Vll)/(WaveLength/2.));
1198 wv = 2.*(Vur-Vll)/NHalfcycles;
1199 NHalfcycles = max(NHalfcycles,1);
1215 for(i=i0; i<=i1; i++)
1218 ha = ((h-Hll)/wh)*2.*PI - PI/2.;
1219 for(j=j0; j<=j1; j++)
1222 va = ((v-Vll)/wv)*2.*PI;
1223 a = Amplitude * cos( ha ) * sin( va );
1227 xyz[i][j].p[2] -= a;
1230 xyz[i][j].p[1] += a;
1233 xyz[i][j].p[1] -= a;
1236 xyz[i][j].p[0] += a;
1239 xyz[i][j].p[0] -= a;
1242 xyz[i][j].p[2] += a;
1247 case WAVE_HCYLINDER:
1248 for(i=0; i<=NH; i++)
1251 ha = ((h-Hll)/WaveLength)*2.*PI - PI/2.;
1252 for(j=0; j<=NV; j++)
1254 a = Amplitude * cos( ha );
1258 xyz[i][j].p[2] -= a;
1261 xyz[i][j].p[1] += a;
1264 xyz[i][j].p[1] -= a;
1267 xyz[i][j].p[0] += a;
1270 xyz[i][j].p[0] -= a;
1273 xyz[i][j].p[2] += a;
1278 case WAVE_VCYLINDER:
1279 for(i=0; i<=NH; i++)
1282 for(j=0; j<=NV; j++)
1285 va = ((v-Vll)/WaveLength)*2.*PI;
1286 a = Amplitude * sin( va );
1290 xyz[i][j].p[2] -= a;
1293 xyz[i][j].p[1] += a;
1296 xyz[i][j].p[1] -= a;
1299 xyz[i][j].p[0] += a;
1302 xyz[i][j].p[0] -= a;
1305 xyz[i][j].p[2] += a;
1310 case WAVE_ROUGH_ONLY:
1315 if(WaveType != WAVE_ROUGH_ONLY)
1318 for(i=0; i<=NH; i++)
1320 for(j=0; j<=NV; j++)
1328 xyz[i][j].p[1] = xyz[i][j].fixed_value;
1332 xyz[i][j].p[0] = xyz[i][j].fixed_value;
1335 xyz[i][j].p[2] = xyz[i][j].fixed_value;
1338 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 );
1359 for(ii=i0; ii<=i1; ii++)
1361 for(jj=j0; jj<=j1; jj++)
1363 if(ii==i && jj==j) continue;
1364 range = pow( dh*(i-ii), 2) + pow( dv*(j-jj), 2);
1365 if(range > maxrange) continue;
1366 dr = sqrt(range/maxrange);
1367 rate = max(-30.,min(xyz[i][j].rate,30.));
1370 delta = pow((1.-dr),-rate+1.);
1374 delta = (1+rate)*0.5*(cos(dr*PI)+1.0) -
1375 rate*pow((1.-dr),2);
1379 delta = 0.5*(cos(dr*PI)+1.0);
1383 delta = (1.-rate)*0.5*(cos(dr*PI)+1.0) +
1384 rate*(1.-pow(dr,2));
1388 delta = 1.-pow(dr,rate+1);
1394 xyz[ii][jj].p[1] += (xyz[i][j].p[1] - xyz[ii][jj].p[1])*delta;
1398 xyz[ii][jj].p[0] += (xyz[i][j].p[0] - xyz[ii][jj].p[0])*delta;
1401 xyz[ii][jj].p[2] += (xyz[i][j].p[2] - xyz[ii][jj].p[2])*delta;
1411 if((Roughness > 0.) && (WaveType != WAVE_ROUGH_ONLY) )
1413 for(i=0; i<=NH; i++)
1415 for(j=0; j<=NV; j++)
1417 if(CanEdit(i,j) && !xyz[i][j].fixed)
1423 xyz[i][j].p[1] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX);
1427 xyz[i][j].p[0] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX);
1430 xyz[i][j].p[2] += -Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX);
1434 r = rand(); // We still get a random number, so that fixing points
1435 // doesn't change the sequence.
1441 for(i=0; i<=NH; i++)
1443 for(j=0; j<=NV; j++)
1447 xyz[i][j].p[k] = Nearest(xyz[i][j].p[k],2.0);
1452 // Find minima and maxima
1461 ymin = xyz[0][0].p[1];
1463 for(i=0; i<=NH; i++)
1465 for(j=0; j<=NV; j++)
1467 ymin = min(ymin,xyz[i][j].p[1]);
1468 ymax = max(ymax,xyz[i][j].p[1]);
1478 xmin = xyz[0][0].p[0];
1480 for(i=0; i<=NH; i++)
1482 for(j=0; j<=NV; j++)
1484 xmin = min(xmin,xyz[i][j].p[0]);
1485 xmax = max(xmax,xyz[i][j].p[0]);
1495 zmin = xyz[0][0].p[2];
1497 for(i=0; i<=NH; i++)
1499 for(j=0; j<=NV; j++)
1501 zmin = min(zmin,xyz[i][j].p[2]);
1502 zmax = max(zmax,xyz[i][j].p[2]);
1507 xmin = Nearest(xmin,2.);
1508 xmax = Nearest(xmax,2.);
1509 ymin = Nearest(ymin,2.);
1510 ymax = Nearest(ymax,2.);
1511 zmin = Nearest(zmin,2.);
1512 zmax = Nearest(zmax,2.);
1517 backface = AtLeast(zmax+32.,32.);
1520 backface = NoMoreThan(ymin-32.,32.);
1523 backface = AtLeast(ymax+32.,32.);
1526 backface = NoMoreThan(xmin-32.,32.);
1529 backface = AtLeast(xmax+32.,32.);
1532 backface = NoMoreThan(zmin-32.,32.);
1539 gNode = (NODE *)NULL;
1542 if(Decimate > 0 && (Game != QUAKE3 || UsePatches==0) )
1544 MakeDecimatedMap(&gNumNodes,&gNumTris,&gNode,&gTri);
1548 gNumNodes = (NH+1)*(NV+1);
1550 gNode = (NODE *) malloc(gNumNodes * sizeof(NODE));
1551 gTri = (TRI *) malloc(gNumTris * sizeof(TRI));
1553 for(i=0,N=0; i<=NH; i++)
1555 for(j=0; j<=NV; j++, N++)
1558 gNode[N].p[0] = (float)xyz[i][j].p[0];
1559 gNode[N].p[1] = (float)xyz[i][j].p[1];
1560 gNode[N].p[2] = (float)xyz[i][j].p[2];
1576 gTri[k ].v[0] = i*(NV+1)+j;
1577 gTri[k ].v[1] = (i+1)*(NV+1)+j+1;
1578 gTri[k ].v[2] = (i+1)*(NV+1)+j;
1579 gTri[k+1].v[0] = i*(NV+1)+j;
1580 gTri[k+1].v[1] = i*(NV+1)+j+1;
1581 gTri[k+1].v[2] = (i+1)*(NV+1)+j+1;
1584 gTri[k ].v[0] = i*(NV+1)+j;
1585 gTri[k ].v[1] = (i+1)*(NV+1)+j;
1586 gTri[k ].v[2] = (i+1)*(NV+1)+j+1;
1587 gTri[k+1].v[0] = i*(NV+1)+j;
1588 gTri[k+1].v[1] = (i+1)*(NV+1)+j+1;
1589 gTri[k+1].v[2] = i*(NV+1)+j+1;
1599 gTri[k ].v[0] = i*(NV+1)+j;
1600 gTri[k ].v[1] = i*(NV+1)+j+1;
1601 gTri[k ].v[2] = (i+1)*(NV+1)+j;
1602 gTri[k+1].v[0] = (i+1)*(NV+1)+j;
1603 gTri[k+1].v[1] = i*(NV+1)+j+1;
1604 gTri[k+1].v[2] = (i+1)*(NV+1)+j+1;
1607 gTri[k ].v[0] = i*(NV+1)+j;
1608 gTri[k ].v[1] = (i+1)*(NV+1)+j;
1609 gTri[k ].v[2] = i*(NV+1)+j+1;
1610 gTri[k+1].v[0] = (i+1)*(NV+1)+j;
1611 gTri[k+1].v[1] = (i+1)*(NV+1)+j+1;
1612 gTri[k+1].v[2] = i*(NV+1)+j+1;
1619 sprintf(CSV,"csv%03d.csv",Decimate);
1621 for(i=0; i<gNumNodes; i++)
1624 fprintf(f,"%g,%g,%g\n",gNode[i].p[0],gNode[i].p[1],gNode[i].p[2]);
1628 for(i=0; i<gNumTris; i++)
1629 PlaneFromPoints(gNode[gTri[i].v[0]].p,
1630 gNode[gTri[i].v[1]].p,
1631 gNode[gTri[i].v[2]].p,
1634 // Hydra: snap-to-grid begin
1645 xyz[i][j].p[1] = CalculateSnapValue(xyz[i][j].p[1]);
1649 xyz[i][j].p[0] = CalculateSnapValue(xyz[i][j].p[0]);
1652 xyz[i][j].p[2] = CalculateSnapValue(xyz[i][j].p[2]);
1657 // Hydra: snap-to-grid end
1659 //=============================================================
1660 double Nearest(double x, double dx)
1664 xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1665 if(fabs(xx) < dx/2) xx = 0.;
1668 //=============================================================
1669 double NoMoreThan(double x, double dx)
1673 xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1674 if(xx > x) xx -= dx;
1677 //=============================================================
1678 double AtLeast(double x, double dx)
1682 xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1683 if(xx < x) xx += dx;
1686 //=============================================================
1687 double LessThan(double x,double dx)
1691 xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1692 if(xx >= x) xx -= dx;
1695 //=============================================================
1696 double MoreThan(double x,double dx)
1700 xx = (double)(floor(x/dx - 0.5)+1.)*dx;
1705 //=============================================================
1706 void SubdividePlasma(int i0,int j0,int i1,int j1)
1710 double r; // NOTE: This is used to keep the random number sequence the same
1711 // when we fix a point. If we did NOT do this, then simply
1712 // fixing a point at its current value would change the entire
1719 if(!xyz[i][j0].done)
1721 xyz[i][j0].pp[2] = xyz[i0][j0].pp[2] +
1722 (xyz[i1][j0].pp[2] - xyz[i0][j0].pp[2])*(double)(i-i0)/(double)(i1-i0) +
1723 ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1724 xyz[i][j0].done = 1;
1728 if((j1 > j0) && (!xyz[i][j1].done) )
1730 xyz[i][j1].pp[2] = xyz[i0][j1].pp[2] +
1731 (xyz[i1][j1].pp[2] - xyz[i0][j1].pp[2])*(double)(i-i0)/(double)(i1-i0) +
1732 ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1733 xyz[i][j1].done = 1;
1740 if(!xyz[i0][j].done)
1742 xyz[i0][j].pp[2] = xyz[i0][j0].pp[2] +
1743 (xyz[i0][j1].pp[2] - xyz[i0][j0].pp[2])*(double)(j-j0)/(double)(j1-j0) +
1744 ((double)(j-j0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1745 xyz[i0][j].done = 1;
1749 if((i1 > i0) && (!xyz[i1][j].done))
1751 xyz[i1][j].pp[2] = xyz[i1][j0].pp[2] +
1752 (xyz[i1][j1].pp[2] - xyz[i1][j0].pp[2])*(double)(j-j0)/(double)(j1-j0) +
1753 ((double)(j-j0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1754 xyz[i1][j].done = 1;
1759 if((i1 > i0+1) && (j1 > j0+1))
1763 z1 = xyz[i0][j].pp[2] +
1764 (xyz[i1][j].pp[2] - xyz[i0][j].pp[2])*(double)(i-i0)/(double)(i1-i0);
1765 z2 = xyz[i][j0].pp[2] +
1766 (xyz[i][j1].pp[2] - xyz[i][j0].pp[2])*(double)(j-j0)/(double)(j1-j0);
1767 xyz[i][j].pp[2] = (z1+z2)/2. +
1768 ((double)(i-i0))*(-Roughness/2. + Roughness*((double)rand()/(double)RAND_MAX));
1774 if(i > i0+1 || j > j0+1)
1775 SubdividePlasma(i0,j0,i,j);
1776 if(i1 > i+1 || j > j0+1)
1777 SubdividePlasma(i,j0,i1,j);
1778 if(i > i0+1 || j1 > j0+1)
1779 SubdividePlasma(i0,j,i,j1);
1780 if(i1 > i+1 || j1 > j0+1)
1781 SubdividePlasma(i,j,i1,j1);
1783 //==================================================================================
1787 /* use pp[2] values until done to avoid messing with a bunch of
1788 switch statements */
1790 for(i=0; i<=NH; i++)
1792 for(j=0; j<=NV; j++)
1805 for(i=0; i<=NH; i++)
1807 for(j=0; j<=NV; j++)
1810 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1812 xyz[i][j].pp[2] = xyz[i][j].p[1];
1818 for(i=0; i<=NH; i++)
1820 for(j=0; j<=NV; j++)
1823 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1825 xyz[i][j].pp[2] = xyz[i][j].p[0];
1830 for(i=0; i<=NH; i++)
1832 for(j=0; j<=NV; j++)
1835 xyz[i][j].pp[2] = xyz[i][j].fixed_value;
1837 xyz[i][j].pp[2] = xyz[i][j].p[2];
1842 SubdividePlasma(0,0,NH,NV);
1847 for(i=0; i<=NH; i++)
1849 for(j=0; j<=NV; j++)
1851 xyz[i][j].p[1] = xyz[i][j].pp[2];
1857 for(i=0; i<=NH; i++)
1859 for(j=0; j<=NV; j++)
1861 xyz[i][j].p[0] = xyz[i][j].pp[2];
1866 for(i=0; i<=NH; i++)
1868 for(j=0; j<=NV; j++)
1870 xyz[i][j].p[2] = xyz[i][j].pp[2];
1876 //===========================================================================
1877 bool FixedPoint(int i, int j)
1879 if(xyz[i][j].fixed) return TRUE;
1880 return !CanEdit(i,j);
1882 //===========================================================================
1883 bool CanEdit(int i, int j)
1885 if(FixBorders && ( (WaveType==WAVE_COS_SIN) || (WaveType==WAVE_ROUGH_ONLY) ) )
1887 if(i== 0) return FALSE;
1888 if(i==NH) return FALSE;
1889 if(j== 0) return FALSE;
1890 if(j==NV) return FALSE;
1892 if(i== 0 && j== 0) return FALSE;
1893 if(i==NH && j== 0) return FALSE;
1894 if(i== 0 && j==NV) return FALSE;
1895 if(i==NH && j==NV) return FALSE;
1898 /*============================================================================
1900 Determines which triangle in the gTri array bounds the input point. Doesn't
1901 do anything special with border points.
1903 int TriangleFromPoint(double x, double y)
1907 if(!gTri) return -1;
1909 for(j=0, tri=-1; j<gNumTris && tri==-1; j++)
1912 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1],
1913 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1]) < 0. ) continue;
1915 gNode[gTri[j].v[1]].p[0],gNode[gTri[j].v[1]].p[1],
1916 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1]) < 0. ) continue;
1918 gNode[gTri[j].v[2]].p[0],gNode[gTri[j].v[2]].p[1],
1919 gNode[gTri[j].v[0]].p[0],gNode[gTri[j].v[0]].p[1]) < 0. ) continue;
1925 /*============================================================================
1927 Determines minimum height to place the player start such that he doesn't
1928 intersect any surface brushes.
1930 int PlayerStartZ(double x, double y)
1935 if(!gTri) return (int)zmax;
1937 t[0] = TriangleFromPoint(x,y);
1938 t[1] = TriangleFromPoint(x+PlayerBox[Game].x[0],y+PlayerBox[Game].y[0]);
1939 t[2] = TriangleFromPoint(x+PlayerBox[Game].x[0],y+PlayerBox[Game].y[1]);
1940 t[3] = TriangleFromPoint(x+PlayerBox[Game].x[1],y+PlayerBox[Game].y[0]);
1941 t[4] = TriangleFromPoint(x+PlayerBox[Game].x[1],y+PlayerBox[Game].y[1]);
1945 zt = (gTri[t[k]].plane.dist -
1946 gTri[t[k]].plane.normal[0]*x -
1947 gTri[t[k]].plane.normal[1]*y )/
1948 gTri[t[k]].plane.normal[2];
1951 return (int)(AtLeast(z,2.) - PlayerBox[Game].z[0]);
1953 //=============================================================
1954 void XYZtoV(XYZ *xyz, vec3 *v)
1956 v[0][0] = (vec)Nearest(xyz->p[0],2.);
1957 v[0][1] = (vec)Nearest(xyz->p[1],2.);
1958 v[0][2] = (vec)Nearest(xyz->p[2],2.);
1961 //=============================================================
1962 void MakePatch(patchMesh_t *p)
1965 char shadername[64+9];
1967 ret = g_FuncTable.m_pfnCreatePatchHandle();
1968 // strcpy(shadername, "textures/");
1969 // strcpy(shadername+9, Texture[Game][0]);
1970 strcpy(shadername, Texture[Game][0]);
1971 g_FuncTable.m_pfnCommitPatchHandleToMap(ret,p,shadername);
1972 g_FuncTable.m_pfnReleasePatchHandles();
1975 //=============================================================
1976 void MakeBrush(BRUSH *brush)
1980 _QERFaceData QERFaceData;
1982 if(g_FuncTable.m_pfnCreateBrushHandle==NULL)
1984 g_FuncTable.m_pfnMessageBox(g_pRadiantWnd,"m_pfnCreateBrushHandle==NULL","Aw damn",0);
1987 vp=(g_FuncTable.m_pfnCreateBrushHandle)();
1989 for(i=0; i<brush->NumFaces; i++)
1991 if(!strncmp(brush->face[i].texture, "textures/", 9))
1992 strcpy(QERFaceData.m_TextureName,brush->face[i].texture);
1995 strcpy(QERFaceData.m_TextureName,"textures/");
1996 strcpy(QERFaceData.m_TextureName+9,brush->face[i].texture);
1998 QERFaceData.m_nContents = brush->face[i].Contents;
1999 QERFaceData.m_nFlags = brush->face[i].Surface;
2000 QERFaceData.m_nValue = brush->face[i].Value;
2001 QERFaceData.m_fShift[0] = brush->face[i].Shift[0];
2002 QERFaceData.m_fShift[1] = brush->face[i].Shift[1];
2003 QERFaceData.m_fRotate = brush->face[i].Rotate;
2004 QERFaceData.m_fScale[0] = brush->face[i].Scale[0];
2005 QERFaceData.m_fScale[1] = brush->face[i].Scale[1];
2006 QERFaceData.m_v1[0] = brush->face[i].v[0][0];
2007 QERFaceData.m_v1[1] = brush->face[i].v[0][1];
2008 QERFaceData.m_v1[2] = brush->face[i].v[0][2];
2009 QERFaceData.m_v2[0] = brush->face[i].v[1][0];
2010 QERFaceData.m_v2[1] = brush->face[i].v[1][1];
2011 QERFaceData.m_v2[2] = brush->face[i].v[1][2];
2012 QERFaceData.m_v3[0] = brush->face[i].v[2][0];
2013 QERFaceData.m_v3[1] = brush->face[i].v[2][1];
2014 QERFaceData.m_v3[2] = brush->face[i].v[2][2];
2015 QERFaceData.m_bBPrimit = false;
2016 (g_FuncTable.m_pfnAddFaceData)(vp,&QERFaceData);
2018 if(g_FuncTable.m_pfnCommitBrushHandle!=NULL)
2021 g_FuncTable.m_pfnCommitBrushHandleToEntity(vp,h_func_group);
2023 g_FuncTable.m_pfnCommitBrushHandle(vp);
2026 //=============================================================
2027 void OpenFuncGroup()
2029 if (g_FuncTable.m_pfnAllocateEpair!=NULL)
2033 h_func_group = g_FuncTable.m_pfnCreateEntityHandle();
2034 ep = g_EntityTable.m_pfnAllocateEpair("classname","func_group");
2035 g_EntityTable.m_pfnSetEntityKeyValList((entity_t *)h_func_group,ep);
2037 if (AddTerrainKey) // ^Fishman - Add terrain key to func_group.
2040 terrainkey = g_FuncTable.m_pfnCreateEntityHandle();
2041 ep2 = g_EntityTable.m_pfnAllocateEpair("terrain","1");
2043 g_EntityTable.m_pfnSetEntityKeyValList((entity_t *)h_func_group,ep);
2047 h_func_group = NULL;
2049 //=============================================================
2050 void CloseFuncGroup()
2053 g_FuncTable.m_pfnCommitEntityHandleToMap (h_func_group);
2054 if (g_FuncTable.m_pfnSysUpdateWindows != NULL)
2055 g_FuncTable.m_pfnSysUpdateWindows (W_ALL);