- Fixed brushexport2 output float-format (Shaderman)
[xonotic/netradiant.git] / contrib / bobtoolz / DShape.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 // DShape.cpp: implementation of the DShape class.
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "DShape.h"
25
26 #include <list>
27 #include <time.h>
28 #include "str.h"
29
30 #include "DPoint.h"
31 #include "DPlane.h"
32 #include "DBrush.h"
33 #include "DEPair.h"
34 #include "DPatch.h"
35 #include "DEntity.h"
36
37 //#include "dialogs-gtk.h"
38
39 #include "misc.h"
40 #include "shapes.h"
41
42 //////////////////////////////////////////////////////////////////////
43 // Construction/Destruction
44 //////////////////////////////////////////////////////////////////////
45
46 bool bFacesAll[6] = {true, true, true, true, true, true};
47
48 DShape::DShape()
49 {
50         m_nNextBrush = 0;
51 }
52
53 DShape::~DShape()
54 {
55
56 }
57
58 void DShape::BuildRegularPrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop)
59 {
60         vec3_t vc[MAX_POLYGON_FACES+2], vd[MAX_POLYGON_FACES+2];
61
62         vec3_t radius;
63         vec3_t origin;
64
65         VectorSubtract(max, min, radius);
66         VectorScale(radius, 0.5f, radius);
67         // calc 3d radius and origin
68         VectorAdd(max, min, origin);
69         VectorScale(origin, 0.5f, origin);
70
71         float phase = 0.0f;
72
73         if(bAlignTop)
74         {
75                 phase = -(Q_PI/nSides);
76                 VectorScale(radius, static_cast<float>(1.0 / cos(phase)), radius);
77         }
78
79         //----- Build Polygon Vertices -----
80
81         int i;
82         for(i = 0; i < nSides; i++)
83         {
84                 VectorCopy(origin, vc[i]);
85                 VectorCopy(origin, vd[i]);
86                 
87                 vc[i][2] = min[2];
88                 vd[i][2] = max[2];
89
90                 vc[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase );
91                 vc[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase );
92
93                 vd[i][0] = vc[i][0];
94                 vd[i][1] = vc[i][1];
95         }
96
97         VectorCopy(vc[0], vc[nSides]);
98         VectorCopy(vd[0], vd[nSides]);
99         VectorCopy(vc[1], vc[nSides+1]);
100         VectorCopy(vd[1], vd[nSides+1]);
101         
102         //----------------------------------
103
104         DBrush* pB = m_Container.GetWorldSpawn()->NewBrush(m_nNextBrush++);
105
106         for(i = 1; i <= nSides; i++)
107                 pB->AddFace(vc[i-1], vc[i], vd[i], GetCurrentTexture(), false);
108
109         pB->AddFace(vc[2], vc[1], vc[0], "textures/common/caulk", false);
110         pB->AddFace(vd[0], vd[1], vd[2], "textures/common/caulk", false);
111 }
112
113 void DShape::Commit()
114 {
115         m_Container.GetWorldSpawn()->FixBrushes();
116         m_Container.BuildInRadiant(true);
117 }
118
119 void DShape::BuildInversePrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop)
120 {
121         vec3_t va[MAX_POLYGON_FACES+1], vb[MAX_POLYGON_FACES+1];
122         vec3_t radius;
123         vec3_t origin;
124
125         VectorSubtract(max, min, radius);
126         VectorScale(radius, 0.5f, radius);
127         // calc 3d radius and origin
128         VectorAdd(max, min, origin);
129         VectorScale(origin, 0.5f, origin);
130
131         float phase = 0.0f;
132
133         if(bAlignTop)
134         {
135                 phase = -(Q_PI/nSides);
136                 VectorScale(radius, static_cast<float>(1.0 / cos(phase)), radius);
137         }
138
139         //----- Build Polygon Vertices -----
140
141         int i;
142         for(i = 0; i < nSides; i++)
143         {
144                 VectorCopy(origin, va[i]);
145                 VectorCopy(origin, vb[i]);
146
147                 va[i][2] = min[2];
148                 vb[i][2] = max[2];
149
150                 va[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase );
151                 va[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase );
152
153                 vb[i][0] = va[i][0];
154                 vb[i][1] = va[i][1];
155         }
156
157         VectorCopy(va[0], va[nSides]);
158         VectorCopy(vb[0], vb[nSides]);
159         
160         //----------------------------------
161
162         for(i = 1; i <= nSides; i++)
163         {
164                 DBrush* pB = GetBoundingCube(min, max, "textures/common/caulk");
165
166                 vec3_t top, bottom;
167                 VectorCopy(va[i-1], top);
168                 VectorCopy(va[i], bottom);
169
170                 if(va[i-1][1] > va[i][1])
171                 {
172                         top[0] += 5;
173                         bottom[0] += 5;
174                 }
175                 else    // flip direction of plane on crossover
176                 {
177                         top[0] -= 5;
178                         bottom[0] -= 5;
179                 }
180                 
181                 if(top[1] != bottom[1]) // internal line is flat already if true
182                 {                       
183                         pB->AddFace(va[i-1], top, vb[i-1], "textures/common/caulk", false);
184                         pB->AddFace(va[i], vb[i], bottom, "textures/common/caulk", false);
185                 }       // add cut-off planes
186
187                 pB->AddFace(va[i-1], vb[i-1], vb[i], GetCurrentTexture(), false);
188                 // add internal polygon plane
189         }
190 }
191
192 void DShape::BuildBorderedPrism(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop)
193 {
194         vec3_t va[MAX_POLYGON_FACES+2], vb[MAX_POLYGON_FACES+2];
195         vec3_t vc[MAX_POLYGON_FACES+2], vd[MAX_POLYGON_FACES+2];
196
197         vec3_t radius;
198         vec3_t origin;
199
200         VectorSubtract(max, min, radius);
201         VectorScale(radius, 0.5f, radius);
202         // calc 3d radius and origin
203         VectorAdd(max, min, origin);
204         VectorScale(origin, 0.5f, origin);
205
206         if(nBorder >= Min(radius[0], radius[1]))
207         {
208 //              DoMessageBox("Border is too large", "Error", MB_OK);
209                 return;
210         }
211
212         float phase = 0.0f;
213
214         if(bAlignTop)
215         {
216                 phase = -(Q_PI/nSides);
217                 VectorScale(radius, static_cast<float>(1.0 / cos(phase)), radius);
218         }
219
220         //----- Build Polygon Vertices -----
221
222         int i;
223         for(i = 0; i < nSides; i++)
224         {
225                 VectorCopy(origin, va[i]);
226                 VectorCopy(origin, vb[i]);
227                 VectorCopy(origin, vc[i]);
228                 VectorCopy(origin, vd[i]);
229
230                 va[i][2] = min[2];
231                 vb[i][2] = max[2];
232
233                 va[i][0] += (radius[0] - nBorder) * sinf( ( 2 * Q_PI * i / nSides ) + phase );
234                 va[i][1] += (radius[1] - nBorder) * cosf( ( 2 * Q_PI * i / nSides ) + phase );
235
236                 vb[i][0] = va[i][0];
237                 vb[i][1] = va[i][1];
238
239
240                 
241                 vc[i][2] = min[2];
242                 vd[i][2] = max[2];
243
244                 vc[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase );
245                 vc[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase );
246
247                 vd[i][0] = vc[i][0];
248                 vd[i][1] = vc[i][1];
249         }
250
251         VectorCopy(va[0], va[nSides]);
252         VectorCopy(vb[0], vb[nSides]);
253         VectorCopy(va[1], va[nSides+1]);
254         VectorCopy(vb[1], vb[nSides+1]);
255
256         VectorCopy(vc[0], vc[nSides]);
257         VectorCopy(vd[0], vd[nSides]);
258         VectorCopy(vc[1], vc[nSides+1]);
259         VectorCopy(vd[1], vd[nSides+1]);
260         
261         //----------------------------------
262
263         for(i = 1; i <= nSides; i++)
264         {
265                 DBrush* pB = GetBoundingCube(min, max, "textures/common/caulk");
266
267                 pB->AddFace(origin, vc[i-1], vd[i-1], "textures/common/caulk", false);
268                 pB->AddFace(origin, vd[i], vc[i], "textures/common/caulk", false); 
269
270                 pB->AddFace(vc[i-1], vc[i], vd[i], GetCurrentTexture(), false);
271                 pB->AddFace(vb[i], va[i], va[i-1], GetCurrentTexture(), false);
272         }
273 }
274
275 DBrush* DShape::GetBoundingCube_Ext(vec3_t min, vec3_t max, const char *textureName, bool* bUseFaces, bool detail)
276 {
277         DBrush* pB = new DBrush;
278         //----- Build Outer Bounds ---------
279
280         vec3_t v1, v2, v3, v5, v6, v7;
281         VectorCopy(min, v1);
282         VectorCopy(min, v2);
283         VectorCopy(min, v3);
284         VectorCopy(max, v5);
285         VectorCopy(max, v6);
286         VectorCopy(max, v7);
287
288         v2[0] = max[0];
289         v3[1] = max[1];
290
291         v6[0] = min[0];
292         v7[1] = min[1];
293
294         //----------------------------------
295
296         //----- Add Six Cube Faces ---------
297
298         if(bUseFaces[0])
299                 pB->AddFace(v1, v2, v3, textureName, detail);
300         if(bUseFaces[1])
301                 pB->AddFace(v1, v3, v6, textureName, detail);
302         if(bUseFaces[2])
303                 pB->AddFace(v1, v7, v2, textureName, detail);
304
305         if(bUseFaces[3])
306                 pB->AddFace(v5, v6, v3, textureName, detail);
307         if(bUseFaces[4])
308                 pB->AddFace(v5, v2, v7, textureName, detail);
309         if(bUseFaces[5])
310                 pB->AddFace(v5, v7, v6, textureName, detail);
311
312         //----------------------------------
313
314         return pB;
315 }
316
317 DBrush* DShape::GetBoundingCube(vec3_t min, vec3_t max, const char *textureName, DEntity* ent, bool* bUseFaces)
318 {
319         DBrush* pB;
320         if(ent == NULL)
321                 pB = m_Container.GetWorldSpawn()->NewBrush(m_nNextBrush++);
322         else
323                 pB = ent->NewBrush(m_nNextBrush++);
324
325         //----- Build Outer Bounds ---------
326
327         vec3_t v1, v2, v3, v5, v6, v7;
328         VectorCopy(min, v1);
329         VectorCopy(min, v2);
330         VectorCopy(min, v3);
331         VectorCopy(max, v5);
332         VectorCopy(max, v6);
333         VectorCopy(max, v7);
334
335         v2[0] = max[0];
336         v3[1] = max[1];
337
338         v6[0] = min[0];
339         v7[1] = min[1];
340
341         //----------------------------------
342
343         //----- Add Six Cube Faces ---------
344
345         if(bUseFaces[0])
346                 pB->AddFace(v1, v2, v3, textureName, false);
347         if(bUseFaces[1])
348                 pB->AddFace(v1, v3, v6, textureName, false);
349         if(bUseFaces[2])
350                 pB->AddFace(v1, v7, v2, textureName, false);
351
352         if(bUseFaces[3])
353                 pB->AddFace(v5, v6, v3, textureName, false);
354         if(bUseFaces[4])
355                 pB->AddFace(v5, v2, v7, textureName, false);
356         if(bUseFaces[5])
357                 pB->AddFace(v5, v7, v6, textureName, false);
358
359         //----------------------------------
360
361         return pB;
362 }
363
364 bool DShape::BuildPit(vec3_t min, vec3_t max)
365 {
366         if((max[2] - min[2]) < 196)
367                 return false;
368
369         srand(time(NULL));
370
371         vec3_t centre;
372         VectorAdd(min, max, centre);
373         VectorScale(centre, 0.5f, centre);
374
375         char buffer[256];
376
377         int team = (rand()%10000)+5000;
378
379 // ************* SPEAKER ***************
380         sprintf(buffer, "t%i_1", team);
381
382 // trigger for speaker
383         vec3_t triggerVoiceBtm;
384         VectorCopy(min, triggerVoiceBtm);
385         triggerVoiceBtm[2] = max[2] - 16;
386
387         DEntity* triggerVoice = m_Container.AddEntity("trigger_multiple");
388         GetBoundingCube(triggerVoiceBtm, max, "textures/common/trigger", triggerVoice);
389         triggerVoice->AddEPair("target", buffer);
390 //--------------------
391
392 // target for speaker
393         vec3_t voiceOrigin;
394         VectorCopy(centre, voiceOrigin);
395         voiceOrigin[2] = max[2]+16;
396
397
398         DEntity* targetVoice = m_Container.AddEntity("target_speaker");
399         targetVoice->AddEPair("targetname", buffer);
400
401         sprintf(buffer, "%f %f %f", voiceOrigin[0], voiceOrigin[1], voiceOrigin[2]);
402         targetVoice->AddEPair("origin", buffer);
403         targetVoice->AddEPair("spawnflags", "8");
404         targetVoice->AddEPair("noise", "*falling1.wav");
405 //--------------------
406
407 // *********** END SPEAKER *************
408
409 // ********* POWERUP REMOVAL ***********
410         sprintf(buffer, "t%i_2", team);
411
412 // trigger for powerup removal
413         vec3_t triggerPwrRmvTop, triggerPwrRmvBtm;
414         VectorCopy(min, triggerPwrRmvBtm);
415         VectorCopy(max, triggerPwrRmvTop);
416
417         triggerPwrRmvTop[2] = triggerVoiceBtm[2] - 64;
418         triggerPwrRmvBtm[2] = triggerPwrRmvTop[2] - 16;
419
420         DEntity* triggerPwrRmv = m_Container.AddEntity("trigger_multiple");
421         GetBoundingCube(triggerPwrRmvBtm, triggerPwrRmvTop, "textures/common/trigger", triggerPwrRmv);
422         triggerPwrRmv->AddEPair("target", buffer);
423 //--------------------
424
425 // target for powerup removal
426         vec3_t pwrRmvOrigin;
427         VectorCopy(centre, pwrRmvOrigin);
428         pwrRmvOrigin[2] = triggerPwrRmvTop[2]+16;
429
430         DEntity* targetPwrRmv = m_Container.AddEntity("target_remove_powerups");
431         targetPwrRmv->AddEPair("targetname", buffer);
432
433         sprintf(buffer, "%f %f %f", pwrRmvOrigin[0], pwrRmvOrigin[1], pwrRmvOrigin[2]);
434         targetPwrRmv->AddEPair("origin", buffer);
435 //--------------------
436
437 // ****** END POWERUP REMOVAL ********
438
439 // ********* DAMAGE ***********
440
441 // trigger for damage
442         vec3_t triggerDmgTop, triggerDmgBtm;
443         VectorCopy(min, triggerDmgBtm);
444         VectorCopy(max, triggerDmgTop);
445
446         triggerDmgBtm[2] = min[2] + 64;
447         triggerDmgTop[2] = triggerDmgBtm[2] + 16;
448
449         DEntity* triggerDmg = m_Container.AddEntity("trigger_hurt");
450         GetBoundingCube(triggerDmgBtm, triggerDmgTop, "textures/common/trigger", triggerDmg);
451         triggerDmg->AddEPair("dmg", "9999");
452         triggerDmg->AddEPair("spawnflags", "12");
453 //--------------------
454
455 // ****** END DAMAGE ********
456
457 // ********* NODROP ***********
458
459         vec3_t nodropTop;
460         VectorCopy(max, nodropTop);
461
462         nodropTop[2] = min[2] + 64;
463
464         GetBoundingCube(min, nodropTop, "textures/common/nodrop");
465
466 // ****** END NODROP ********
467
468         return true;
469 }