1 /*
2    BobToolz plugin for GtkRadiant
3    Copyright (C) 2001 Gordon Biggans
4 
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.
9 
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.
14 
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
18  */
19 
20 
21 #include "shapes.h"
22 
23 #include <list>
24 
25 #include "DPoint.h"
26 #include "DPlane.h"
27 
28 #include "str.h"
29 #include "misc.h"
30 #include "funchandlers.h"
31 
32 #include "iundo.h"
33 #include "ishaders.h"
34 #include "ientity.h"
35 #include "ieclass.h"
36 #include "ipatch.h"
37 #include "qerplugin.h"
38 
39 #include <vector>
40 #include <list>
41 #include <map>
42 #include <algorithm>
43 #include <stdlib.h>
44 #include <time.h>
45 
46 #include "scenelib.h"
47 #include "texturelib.h"
48 
49 //#include "dialogs-gtk.h"
50 
51 /************************
52     Cube Diagram
53 ************************/
54 
55 /*
56 
57         7 ----- 5
58         /|    /|
59        / |   / |
60       /  |  /  |
61     4 ----- 6  |
62  |  2|_|___|8
63  |  /  |   /
64  | /   |  /       ----> WEST, definitely
65  ||/    | /
66     1|_____|/3
67 
68  */
69 
70 /************************
71     Global Variables
72 ************************/
73 
74 vec3_t g_Origin = {0.0f, 0.0f, 0.0f};
75 
76 extern bool bFacesAll[];
77 
78 /************************
79     Helper Functions
80 ************************/
81 
Deg2Rad(float angle)82 float Deg2Rad( float angle ){
83 	return (float)( angle * Q_PI / 180 );
84 }
85 
AddFaceWithTexture(scene::Node & brush,vec3_t va,vec3_t vb,vec3_t vc,const char * texture,bool detail)86 void AddFaceWithTexture( scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail ){
87 	_QERFaceData faceData;
88 	FillDefaultTexture( &faceData, va, vb, vc, texture );
89 	if ( detail ) {
90 		faceData.contents |= FACE_DETAIL;
91 	}
92 	GlobalBrushCreator().Brush_addFace( brush, faceData );
93 }
94 
AddFaceWithTextureScaled(scene::Node & brush,vec3_t va,vec3_t vb,vec3_t vc,const char * texture,bool bVertScale,bool bHorScale,float minX,float minY,float maxX,float maxY)95 void AddFaceWithTextureScaled( scene::Node& brush, vec3_t va, vec3_t vb, vec3_t vc,
96 							   const char* texture, bool bVertScale, bool bHorScale,
97 							   float minX, float minY, float maxX, float maxY ){
98 	qtexture_t* pqtTexInfo;
99 
100 	// TTimo: there used to be a call to pfnHasShader here
101 	//   this was not necessary. In Radiant everything is shader.
102 	//   If a texture doesn't have a shader script, a default shader object is used.
103 	// The IShader object was leaking also
104 	// collect texture info: sizes, etc
105 	IShader* i = GlobalShaderSystem().getShaderForName( texture );
106 	pqtTexInfo = i->getTexture(); // shader width/height doesn't come out properly
107 
108 	if ( pqtTexInfo ) {
109 		float scale[2] = {0.5f, 0.5f};
110 		float shift[2] = {0, 0};
111 
112 		if ( bHorScale ) {
113 			float width = maxX - minX;
114 
115 			scale[0] = width / pqtTexInfo->width;
116 			shift[0] = -(float)( (int)maxX % (int)width ) / scale[0];
117 		}
118 
119 		if ( bVertScale ) {
120 			float height = maxY - minY;
121 
122 			scale[1] = height / pqtTexInfo->height;
123 			shift[1] = (float)( (int)minY % (int)height ) / scale[1];
124 		}
125 
126 		_QERFaceData addFace;
127 		FillDefaultTexture( &addFace, va, vb, vc, texture );
128 		addFace.m_texdef.scale[0] = scale[0];
129 		addFace.m_texdef.scale[1] = scale[1];
130 		addFace.m_texdef.shift[0] = shift[0];
131 		addFace.m_texdef.shift[1] = shift[1];
132 
133 		GlobalBrushCreator().Brush_addFace( brush, addFace );
134 	}
135 	else
136 	{
137 		// shouldn't even get here, as default missing texture should be returned if
138 		// texture doesn't exist, but just in case
139 		AddFaceWithTexture( brush, va, vb, vc, texture, false );
140 		globalErrorStream() << "BobToolz::Invalid Texture Name-> " << texture;
141 	}
142 	// the IShader is not kept referenced, DecRef it
143 	i->DecRef();
144 }
145 
146 /************************
147     --Main Functions--
148 ************************/
149 
Build_Wedge(int dir,vec3_t min,vec3_t max,bool bUp)150 void Build_Wedge( int dir, vec3_t min, vec3_t max, bool bUp ){
151 	NodeSmartReference newBrush( GlobalBrushCreator().createBrush() );
152 
153 	vec3_t v1, v2, v3, v5, v6, v7, v8;
154 	VectorCopy( min, v1 );
155 	VectorCopy( min, v2 );
156 	VectorCopy( min, v3 );
157 	VectorCopy( max, v5 );
158 	VectorCopy( max, v6 );
159 	VectorCopy( max, v7 );
160 	VectorCopy( max, v8 );
161 
162 	v2[0] = max[0];
163 	v3[1] = max[1];
164 
165 	v6[0] = min[0];
166 	v7[1] = min[1];
167 	v8[2] = min[2];
168 
169 	if ( bUp ) {
170 
171 		if ( dir != MOVE_EAST ) {
172 			AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", false );
173 		}
174 
175 		if ( dir != MOVE_WEST ) {
176 			AddFaceWithTexture( newBrush, v7, v5, v8, "textures/common/caulk", false );
177 		}
178 
179 		if ( dir != MOVE_NORTH ) {
180 			AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", false );
181 		}
182 
183 		if ( dir != MOVE_SOUTH ) {
184 			AddFaceWithTexture( newBrush, v3, v8, v6, "textures/common/caulk", false );
185 		}
186 
187 		AddFaceWithTexture( newBrush, v1, v2, v3, "textures/common/caulk", false );
188 
189 		if ( dir == MOVE_EAST ) {
190 			AddFaceWithTexture( newBrush, v1, v3, v5, "textures/common/caulk", false );
191 		}
192 
193 		if ( dir == MOVE_WEST ) {
194 			AddFaceWithTexture( newBrush, v2, v6, v8, "textures/common/caulk", false );
195 		}
196 
197 		if ( dir == MOVE_NORTH ) {
198 			AddFaceWithTexture( newBrush, v1, v6, v5, "textures/common/caulk", false );
199 		}
200 
201 		if ( dir == MOVE_SOUTH ) {
202 			AddFaceWithTexture( newBrush, v7, v3, v8, "textures/common/caulk", false );
203 		}
204 	}
205 	else
206 	{
207 		if ( dir != MOVE_WEST ) {
208 			AddFaceWithTexture( newBrush, v7, v5, v8, "textures/common/caulk", false );
209 		}
210 
211 		if ( dir != MOVE_EAST ) {
212 			AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", false );
213 		}
214 
215 		if ( dir != MOVE_NORTH ) {
216 			AddFaceWithTexture( newBrush, v3, v8, v6, "textures/common/caulk", false );
217 		}
218 
219 		if ( dir != MOVE_SOUTH ) {
220 			AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", false );
221 		}
222 
223 
224 		AddFaceWithTexture( newBrush, v6, v5, v7, "textures/common/caulk", false );
225 
226 		if ( dir == MOVE_WEST ) {
227 			AddFaceWithTexture( newBrush, v1, v5, v3, "textures/common/caulk", false );
228 		}
229 
230 		if ( dir == MOVE_EAST ) {
231 			AddFaceWithTexture( newBrush, v2, v8, v6, "textures/common/caulk", false );
232 		}
233 
234 		if ( dir == MOVE_NORTH ) {
235 			AddFaceWithTexture( newBrush, v1, v5, v6, "textures/common/caulk", false );
236 		}
237 
238 		if ( dir == MOVE_SOUTH ) {
239 			AddFaceWithTexture( newBrush, v7, v8, v3, "textures/common/caulk", false );
240 		}
241 	}
242 
243 	Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( newBrush );
244 }
245 
246 //-----------------------------------------------------------------------------------
247 //-----------------------------------------------------------------------------------
248 
Build_StairStep_Wedge(int dir,vec3_t min,vec3_t max,const char * mainTexture,const char * riserTexture,bool detail)249 void Build_StairStep_Wedge( int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail ){
250 	NodeSmartReference newBrush( GlobalBrushCreator().createBrush() );
251 
252 	//----- Build Outer Bounds ---------
253 
254 	vec3_t v1, v2, v3, v5, v6, v7, v8;
255 	VectorCopy( min, v1 );
256 	VectorCopy( min, v2 );
257 	VectorCopy( min, v3 );
258 	VectorCopy( max, v5 );
259 	VectorCopy( max, v6 );
260 	VectorCopy( max, v7 );
261 	VectorCopy( max, v8 );
262 
263 	v2[0] = max[0];
264 	v3[1] = max[1];
265 
266 	v6[0] = min[0];
267 	v7[1] = min[1];
268 
269 	v8[2] = min[2];
270 	//v8 needed this time, becoz of sloping faces (2-4-6-8)
271 
272 	//----------------------------------
273 
274 	AddFaceWithTexture( newBrush, v6, v5, v7, mainTexture, detail );
275 
276 	if ( dir != MOVE_EAST ) {
277 		if ( dir == MOVE_WEST ) {
278 			AddFaceWithTexture( newBrush, v5, v2, v7, riserTexture, detail );
279 		}
280 		else{
281 			AddFaceWithTexture( newBrush, v5, v2, v7, "textures/common/caulk", detail );
282 		}
283 	}
284 
285 	if ( dir != MOVE_WEST ) {
286 		if ( dir == MOVE_EAST ) {
287 			AddFaceWithTexture( newBrush, v1, v3, v6, riserTexture, detail );
288 		}
289 		else{
290 			AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", detail );
291 		}
292 	}
293 
294 	if ( dir != MOVE_NORTH ) {
295 		if ( dir == MOVE_SOUTH ) {
296 			AddFaceWithTexture( newBrush, v3, v5, v6, riserTexture, detail );
297 		}
298 		else{
299 			AddFaceWithTexture( newBrush, v3, v5, v6, "textures/common/caulk", detail );
300 		}
301 	}
302 
303 	if ( dir != MOVE_SOUTH ) {
304 		if ( dir == MOVE_NORTH ) {
305 			AddFaceWithTexture( newBrush, v1, v7, v2, riserTexture, detail );
306 		}
307 		else{
308 			AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", detail );
309 		}
310 	}
311 
312 
313 	if ( dir == MOVE_EAST ) {
314 		AddFaceWithTexture( newBrush, v1, v5, v3, "textures/common/caulk", detail );
315 	}
316 
317 	if ( dir == MOVE_WEST ) {
318 		AddFaceWithTexture( newBrush, v2, v8, v6, "textures/common/caulk", detail );
319 	}
320 
321 	if ( dir == MOVE_NORTH ) {
322 		AddFaceWithTexture( newBrush, v1, v5, v6, "textures/common/caulk", detail );
323 	}
324 
325 	if ( dir == MOVE_SOUTH ) {
326 		AddFaceWithTexture( newBrush, v7, v8, v3, "textures/common/caulk", detail );
327 	}
328 
329 	Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( newBrush );
330 }
331 
332 //-----------------------------------------------------------------------------------
333 //-----------------------------------------------------------------------------------
334 
335 // internal use only, to get a box without finishing construction
Build_Get_BoundingCube_Selective(vec3_t min,vec3_t max,char * texture,bool * useFaces)336 scene::Node& Build_Get_BoundingCube_Selective( vec3_t min, vec3_t max, char* texture, bool* useFaces ){
337 	NodeSmartReference newBrush( GlobalBrushCreator().createBrush() );
338 
339 	//----- Build Outer Bounds ---------
340 
341 	vec3_t v1, v2, v3, v5, v6, v7;
342 	VectorCopy( min, v1 );
343 	VectorCopy( min, v2 );
344 	VectorCopy( min, v3 );
345 	VectorCopy( max, v5 );
346 	VectorCopy( max, v6 );
347 	VectorCopy( max, v7 );
348 
349 	v2[0] = max[0];
350 	v3[1] = max[1];
351 
352 	v6[0] = min[0];
353 	v7[1] = min[1];
354 
355 	//----------------------------------
356 
357 	//----- Add Six Cube Faces ---------
358 
359 	if ( useFaces[0] ) {
360 		AddFaceWithTexture( newBrush, v1, v2, v3, texture, false );
361 	}
362 	if ( useFaces[1] ) {
363 		AddFaceWithTexture( newBrush, v1, v3, v6, texture, false );
364 	}
365 	if ( useFaces[2] ) {
366 		AddFaceWithTexture( newBrush, v1, v7, v2, texture, false );
367 	}
368 
369 	if ( useFaces[3] ) {
370 		AddFaceWithTexture( newBrush, v5, v6, v3, texture, false );
371 	}
372 	if ( useFaces[4] ) {
373 		AddFaceWithTexture( newBrush, v5, v2, v7, texture, false );
374 	}
375 	if ( useFaces[5] ) {
376 		AddFaceWithTexture( newBrush, v5, v7, v6, texture, false );
377 	}
378 
379 	//----------------------------------
380 
381 	return newBrush;
382 }
383 
Build_Get_BoundingCube(vec3_t min,vec3_t max,char * texture)384 scene::Node& Build_Get_BoundingCube( vec3_t min, vec3_t max, char* texture ){
385 	return Build_Get_BoundingCube_Selective( min, max, texture, bFacesAll );
386 }
387 
388 //-----------------------------------------------------------------------------------
389 //-----------------------------------------------------------------------------------
390 
Build_StairStep(vec3_t min,vec3_t max,const char * mainTexture,const char * riserTexture,int direction)391 void Build_StairStep( vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction ){
392 	NodeSmartReference newBrush( GlobalBrushCreator().createBrush() );
393 
394 	//----- Build Outer Bounds ---------
395 
396 	vec3_t v1, v2, v3, v5, v6, v7;
397 	VectorCopy( min, v1 );
398 	VectorCopy( min, v2 );
399 	VectorCopy( min, v3 );
400 	VectorCopy( max, v5 );
401 	VectorCopy( max, v6 );
402 	VectorCopy( max, v7 );
403 
404 	v2[0] = max[0];
405 	v3[1] = max[1];
406 
407 	v6[0] = min[0];
408 	v7[1] = min[1];
409 
410 	//----------------------------------
411 
412 	AddFaceWithTexture( newBrush, v6, v5, v7, mainTexture, false );
413 	// top gets current texture
414 
415 
416 	if ( direction == MOVE_EAST ) {
417 		AddFaceWithTexture( newBrush, v1, v3, v6, riserTexture, false );
418 	}
419 	else{
420 		AddFaceWithTexture( newBrush, v1, v3, v6, "textures/common/caulk", false );
421 	}
422 	// west facing side, etc...
423 
424 
425 	if ( direction == MOVE_NORTH ) {
426 		AddFaceWithTexture( newBrush, v1, v7, v2, riserTexture, false );
427 	}
428 	else{
429 		AddFaceWithTexture( newBrush, v1, v7, v2, "textures/common/caulk", false );
430 	}
431 
432 	if ( direction == MOVE_SOUTH ) {
433 		AddFaceWithTexture( newBrush, v3, v5, v6, riserTexture, false );
434 	}
435 	else{
436 		AddFaceWithTexture( newBrush, v3, v5, v6, "textures/common/caulk", false );
437 	}
438 
439 	if ( direction == MOVE_WEST ) {
440 		AddFaceWithTexture( newBrush, v7, v5, v2, riserTexture, false );
441 	}
442 	else{
443 		AddFaceWithTexture( newBrush, v7, v5, v2, "textures/common/caulk", false );
444 	}
445 
446 
447 	AddFaceWithTexture( newBrush, v1, v2, v3, "textures/common/caulk", false );
448 	// base is caulked
449 
450 	Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( newBrush );
451 	// finish brush
452 }
453 
454 //-----------------------------------------------------------------------------------
455 //-----------------------------------------------------------------------------------
456 
BuildDoorsX2(vec3_t min,vec3_t max,bool bSclMainHor,bool bSclMainVert,bool bSclTrimHor,bool bSclTrimVert,const char * mainTexture,const char * trimTexture,int direction)457 void BuildDoorsX2( vec3_t min, vec3_t max,
458 				   bool bSclMainHor, bool bSclMainVert,
459 				   bool bSclTrimHor, bool bSclTrimVert,
460 				   const char* mainTexture, const char* trimTexture,
461 				   int direction ){
462 	int xy;
463 	if ( direction == 0 ) {
464 		xy = 0;
465 	}
466 	else{
467 		xy = 1;
468 	}
469 
470 	//----- Build Outer Bounds ---------
471 
472 	vec3_t v1, v2, v3, v5, v6, v7, ve_1, ve_2, ve_3;
473 	VectorCopy( min, v1 );
474 	VectorCopy( min, v2 );
475 	VectorCopy( min, v3 );
476 	VectorCopy( max, v5 );
477 	VectorCopy( max, v6 );
478 	VectorCopy( max, v7 );
479 
480 	v2[0] = max[0];
481 	v3[1] = max[1];
482 
483 	v6[0] = min[0];
484 	v7[1] = min[1];
485 
486 	float width = ( max[xy] - min[xy] ) / 2;
487 
488 	if ( direction == 0 ) {
489 		VectorCopy( v1, ve_1 );
490 		VectorCopy( v3, ve_2 );
491 		VectorCopy( v6, ve_3 );
492 	}
493 	else
494 	{
495 		VectorCopy( v7, ve_1 );
496 		VectorCopy( v1, ve_2 );
497 		VectorCopy( v2, ve_3 );
498 	}
499 
500 	ve_1[xy] += width;
501 	ve_2[xy] += width;
502 	ve_3[xy] += width;
503 
504 	//----------------------------------
505 
506 	NodeSmartReference newBrush1( GlobalBrushCreator().createBrush() );
507 	NodeSmartReference newBrush2( GlobalBrushCreator().createBrush() );
508 
509 	AddFaceWithTexture( newBrush1, v1, v2, v3, "textures/common/caulk", false );
510 	AddFaceWithTexture( newBrush1, v5, v7, v6, "textures/common/caulk", false );
511 
512 	AddFaceWithTexture( newBrush2, v1, v2, v3, "textures/common/caulk", false );
513 	AddFaceWithTexture( newBrush2, v5, v7, v6, "textures/common/caulk", false );
514 
515 	if ( direction == 0 ) {
516 		AddFaceWithTexture( newBrush1, v1, v3, v6, "textures/common/caulk", false );
517 		AddFaceWithTexture( newBrush2, v5, v2, v7, "textures/common/caulk", false );
518 	}
519 	else
520 	{
521 		AddFaceWithTexture( newBrush1, v1, v7, v2, "textures/common/caulk", false );
522 		AddFaceWithTexture( newBrush2, v5, v6, v3, "textures/common/caulk", false );
523 	}
524 
525 	if ( direction == 0 ) {
526 		AddFaceWithTextureScaled( newBrush1, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor,
527 								  min[0], min[2], max[0], max[2] );
528 		AddFaceWithTextureScaled( newBrush1, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor,
529 								  max[0], min[2], min[0], max[2] );
530 
531 
532 		AddFaceWithTextureScaled( newBrush2, v1, v7, v2, mainTexture, bSclMainVert, bSclMainHor,
533 								  min[0], min[2], max[0], max[2] );
534 		AddFaceWithTextureScaled( newBrush2, v5, v6, v3, mainTexture, bSclMainVert, bSclMainHor,
535 								  max[0], min[2], min[0], max[2] ); // flip max/min to reverse tex dir
536 
537 
538 
539 		AddFaceWithTextureScaled( newBrush1, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor,
540 								  min[1], min[2], max[1], max[2] );
541 
542 		AddFaceWithTextureScaled( newBrush2, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor,
543 								  max[1], min[2], min[1], max[2] );
544 	}
545 	else
546 	{
547 		AddFaceWithTextureScaled( newBrush1, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor,
548 								  min[1], min[2], max[1], max[2] );
549 		AddFaceWithTextureScaled( newBrush1, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor,
550 								  max[1], min[2], min[1], max[2] );
551 
552 
553 		AddFaceWithTextureScaled( newBrush2, v1, v3, v6, mainTexture, bSclMainVert, bSclMainHor,
554 								  min[1], min[2], max[1], max[2] );
555 		AddFaceWithTextureScaled( newBrush2, v5, v2, v7, mainTexture, bSclMainVert, bSclMainHor,
556 								  max[1], min[2], min[1], max[2] ); // flip max/min to reverse tex dir
557 
558 
559 		AddFaceWithTextureScaled( newBrush1, ve_1, ve_2, ve_3, trimTexture, bSclTrimVert, bSclTrimHor,
560 								  min[0], min[2], max[0], max[2] );
561 
562 		AddFaceWithTextureScaled( newBrush2, ve_3, ve_2, ve_1, trimTexture, bSclTrimVert, bSclTrimHor,
563 								  max[0], min[2], min[0], max[2] );
564 	}
565 
566 	//----------------------------------
567 
568 
569 	EntityClass* doorClass = GlobalEntityClassManager().findOrInsert( "func_door", true );
570 	NodeSmartReference pEDoor1( GlobalEntityCreator().createEntity( doorClass ) );
571 	NodeSmartReference pEDoor2( GlobalEntityCreator().createEntity( doorClass ) );
572 
573 	if ( direction == 0 ) {
574 		Node_getEntity( pEDoor1 )->setKeyValue( "angle", "180" );
575 		Node_getEntity( pEDoor2 )->setKeyValue( "angle", "360" );
576 	}
577 	else
578 	{
579 		Node_getEntity( pEDoor1 )->setKeyValue( "angle", "270" );
580 		Node_getEntity( pEDoor2 )->setKeyValue( "angle", "90" );
581 	}
582 
583 	srand( (unsigned)time( NULL ) );
584 
585 	char teamname[256];
586 	sprintf( teamname, "t%i", rand() );
587 	Node_getEntity( pEDoor1 )->setKeyValue( "team", teamname );
588 	Node_getEntity( pEDoor2 )->setKeyValue( "team", teamname );
589 
590 	Node_getTraversable( pEDoor1 )->insert( newBrush1 );
591 	Node_getTraversable( pEDoor2 )->insert( newBrush2 );
592 
593 	Node_getTraversable( GlobalSceneGraph().root() )->insert( pEDoor1 );
594 	Node_getTraversable( GlobalSceneGraph().root() )->insert( pEDoor2 );
595 
596 //	ResetCurrentTexture();
597 }
598 
599 //-----------------------------------------------------------------------------------
600 //-----------------------------------------------------------------------------------
601 
MakeBevel(vec3_t vMin,vec3_t vMax)602 void MakeBevel( vec3_t vMin, vec3_t vMax ){
603 	NodeSmartReference patch( GlobalPatchCreator().createPatch() );
604 	GlobalPatchCreator().Patch_resize( patch, 3, 3 );
605 	GlobalPatchCreator().Patch_setShader( patch, "textures/common/caulk" );
606 	PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints( patch );
607 	vec3_t x_3, y_3, z_3;
608 	x_3[0] = vMin[0];   x_3[1] = vMin[0];               x_3[2] = vMax[0];
609 	y_3[0] = vMin[1];   y_3[1] = vMax[1];               y_3[2] = vMax[1];
610 	z_3[0] = vMin[2];   z_3[1] = ( vMax[2] + vMin[2] ) / 2; z_3[2] = vMax[2];
611 	/*
612 	   x_3[0] = 0;		x_3[1] = 0;		x_3[2] = 64;
613 	   y_3[0] = 0;		y_3[1] = 64;	y_3[2] = 64;
614 	   z_3[0] = 0;		z_3[1] = 32;	z_3[2] = 64;*/
615 	for ( int i = 0; i < 3; i++ )
616 	{
617 		for ( int j = 0; j < 3; j++ )
618 		{
619 			PatchControl& p = matrix( i, j );
620 			p.m_vertex[0] = x_3[i];
621 			p.m_vertex[1] = y_3[i];
622 			p.m_vertex[2] = z_3[j];
623 		}
624 	}
625 	//does invert the matrix, else the patch face is on wrong side.
626 	for ( int i = 0 ; i < 3 ; i++ )
627 	{
628 		for ( int j = 0; j < 1; j++ )
629 		{
630 			PatchControl& p = matrix( i,2 - j );
631 			PatchControl& q = matrix( i, j );
632 			std::swap( p.m_vertex, q.m_vertex );
633 			//std::swap(p.m_texcoord, q.m_texcoord);
634 		}
635 	}
636 	GlobalPatchCreator().Patch_controlPointsChanged( patch );
637 	//TODO - the patch has textures weird, patchmanip.h has all function it needs.. lots of duplicate code..
638 	//NaturalTexture(patch);
639 	Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( patch );
640 }
641 
BuildCornerStairs(vec3_t vMin,vec3_t vMax,int nSteps,const char * mainTexture,const char * riserTex)642 void BuildCornerStairs( vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex ){
643 	vec3_t* topPoints = new vec3_t[nSteps + 1];
644 	vec3_t* botPoints = new vec3_t[nSteps + 1];
645 
646 	//bool bFacesUse[6] = {true, true, false, true, false, false};
647 
648 	vec3_t centre;
649 	VectorCopy( vMin, centre );
650 	centre[0] = vMax[0];
651 
652 	int height = (int)( vMax[2] - vMin[2] ) / nSteps;
653 
654 	vec3_t vTop, vBot;
655 	VectorCopy( vMax, vTop );
656 	VectorCopy( vMin, vBot );
657 	vTop[2] = vMin[2] + height;
658 
659 	int i;
660 	for ( i = 0; i <= nSteps; i++ )
661 	{
662 		VectorCopy( centre, topPoints[i] );
663 		VectorCopy( centre, botPoints[i] );
664 
665 		topPoints[i][2] = vMax[2];
666 		botPoints[i][2] = vMin[2];
667 
668 		topPoints[i][0] -= 10 * sinf( Q_PI * i / ( 2 * nSteps ) );
669 		topPoints[i][1] += 10 * cosf( Q_PI * i / ( 2 * nSteps ) );
670 
671 		botPoints[i][0] = topPoints[i][0];
672 		botPoints[i][1] = topPoints[i][1];
673 	}
674 
675 	vec3_t tp[3];
676 	for ( int j = 0; j < 3; j++ )
677 		VectorCopy( topPoints[j], tp[j] );
678 
679 	for ( i = 0; i < nSteps; i++ )
680 	{
681 		NodeSmartReference brush( GlobalBrushCreator().createBrush() );
682 		vec3_t v1, v2, v3, v5, v6, v7;
683 		VectorCopy( vBot, v1 );
684 		VectorCopy( vBot, v2 );
685 		VectorCopy( vBot, v3 );
686 		VectorCopy( vTop, v5 );
687 		VectorCopy( vTop, v6 );
688 		VectorCopy( vTop, v7 );
689 
690 		v2[0] = vTop[0];
691 		v3[1] = vTop[1];
692 
693 		v6[0] = vBot[0];
694 		v7[1] = vBot[1];
695 
696 		AddFaceWithTexture( brush, v1, v2, v3, "textures/common/caulk", false );
697 		AddFaceWithTexture( brush, v1, v3, v6, "textures/common/caulk", false );
698 		AddFaceWithTexture( brush, v5, v6, v3, "textures/common/caulk", false );
699 
700 		for ( int j = 0; j < 3; j++ )
701 			tp[j][2] = vTop[2];
702 
703 		AddFaceWithTexture( brush, tp[2], tp[1], tp[0], mainTexture, false );
704 
705 		AddFaceWithTexture( brush, centre, botPoints[i + 1], topPoints[i + 1], "textures/common/caulk", false );
706 		AddFaceWithTexture( brush, centre, topPoints[i], botPoints[i], riserTex, false );
707 
708 		Node_getTraversable( GlobalRadiant().getMapWorldEntity() )->insert( brush );
709 
710 		vTop[2] += height;
711 		vBot[2] += height;
712 	}
713 
714 	delete[] topPoints;
715 	delete[] botPoints;
716 
717 	vMin[2] += height;
718 	vMax[2] += height;
719 	MakeBevel( vMin, vMax );
720 }
721