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