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