]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/DTrainDrawer.cpp
gcc: appease the hardening warnings
[xonotic/netradiant.git] / contrib / bobtoolz / DTrainDrawer.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 #include "DTrainDrawer.h"
21
22 #include <list>
23 #include "str.h"
24
25 #include "DPoint.h"
26 #include "DPlane.h"
27 #include "DBrush.h"
28 #include "DEPair.h"
29 #include "DPatch.h"
30 #include "DEntity.h"
31
32 #include "misc.h"
33 #include "funchandlers.h"
34
35 #include "iglrender.h"
36 #include "ientity.h"
37 #include "math/matrix.h"
38
39 #include "dialogs/dialogs-gtk.h"
40
41 DTrainDrawer::DTrainDrawer()
42 {
43     m_bDisplay = false;
44
45     BuildPaths();
46     constructShaders();
47     GlobalShaderCache().attachRenderable(*this);
48 }
49
50 DTrainDrawer::~DTrainDrawer(void)
51 {
52     GlobalShaderCache().detachRenderable(*this);
53     destroyShaders();
54
55     ClearPoints();
56     ClearSplines();
57 }
58
59 void DTrainDrawer::ClearSplines()
60 {
61     for (std::list<splinePoint_t *>::const_iterator deadSpline = m_splineList.begin();
62          deadSpline != m_splineList.end(); deadSpline++) {
63         (*deadSpline)->m_pointList.clear();
64         (*deadSpline)->m_vertexList.clear();
65         delete (*deadSpline);
66     }
67
68     m_splineList.clear();
69 }
70
71 void DTrainDrawer::ClearPoints()
72 {
73     for (std::list<controlPoint_t *>::const_iterator deadPoint = m_pointList.begin();
74          deadPoint != m_pointList.end(); deadPoint++) {
75         delete *deadPoint;
76     }
77
78     m_pointList.clear();
79 }
80
81 void CalculateSpline_r(vec3_t *v, int count, vec3_t out, float tension)
82 {
83     vec3_t dist;
84
85     if (count < 2) {
86         return;
87     }
88
89     if (count == 2) {
90         VectorSubtract(v[1], v[0], dist);
91         VectorMA(v[0], tension, dist, out);
92         return;
93     }
94
95     vec3_t *v2 = new vec3_t[count - 1];
96
97     for (int i = 0; i < count - 1; i++) {
98         VectorSubtract(v[i + 1], v[i], dist);
99         VectorMA(v[i], tension, dist, v2[i]);
100     }
101
102     CalculateSpline_r(v2, count - 1, out, tension);
103
104     delete[] v2;
105 }
106
107 void DTrainDrawer::render(RenderStateFlags state) const
108 {
109     for (std::list<splinePoint_t *>::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) {
110         splinePoint_t *pSP = (*sp);
111
112         glBegin(GL_LINE_STRIP);
113         for (std::list<DPoint>::const_iterator v = pSP->m_vertexList.begin(); v != pSP->m_vertexList.end(); v++) {
114             glVertex3fv((*v)._pnt);
115         }
116         glEnd();
117
118     }
119 }
120
121 const char *DTrainDrawer_state_wireframe = "$bobtoolz/traindrawer/wireframe";
122 const char *DTrainDrawer_state_solid = "$bobtoolz/traindrawer/solid";
123
124 void DTrainDrawer::constructShaders()
125 {
126     OpenGLState state;
127     GlobalOpenGLStateLibrary().getDefaultState(state);
128     state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND;
129     state.m_sort = OpenGLState::eSortOverlayFirst;
130     state.m_linewidth = 1;
131     state.m_colour[0] = 1;
132     state.m_colour[1] = 0;
133     state.m_colour[2] = 0;
134     state.m_colour[3] = 1;
135     state.m_linewidth = 1;
136     GlobalOpenGLStateLibrary().insert(DTrainDrawer_state_wireframe, state);
137
138     state.m_colour[0] = 1;
139     state.m_colour[1] = 1;
140     state.m_colour[2] = 1;
141     state.m_colour[3] = 1;
142     state.m_linewidth = 2;
143     GlobalOpenGLStateLibrary().insert(DTrainDrawer_state_solid, state);
144
145     m_shader_wireframe = GlobalShaderCache().capture(DTrainDrawer_state_wireframe);
146     m_shader_solid = GlobalShaderCache().capture(DTrainDrawer_state_solid);
147 }
148
149 void DTrainDrawer::destroyShaders()
150 {
151     GlobalOpenGLStateLibrary().erase(DTrainDrawer_state_wireframe);
152     GlobalOpenGLStateLibrary().erase(DTrainDrawer_state_solid);
153     GlobalShaderCache().release(DTrainDrawer_state_wireframe);
154     GlobalShaderCache().release(DTrainDrawer_state_solid);
155 }
156
157
158 void DTrainDrawer::renderSolid(Renderer &renderer, const VolumeTest &volume) const
159 {
160     if (!m_bDisplay) {
161         return;
162     }
163
164     renderer.SetState(m_shader_wireframe, Renderer::eWireframeOnly);
165     renderer.SetState(m_shader_solid, Renderer::eFullMaterials);
166     renderer.addRenderable(*this, g_matrix4_identity);
167 }
168
169 void DTrainDrawer::renderWireframe(Renderer &renderer, const VolumeTest &volume) const
170 {
171     renderSolid(renderer, volume);
172 }
173
174 void AddSplineControl(const char *control, splinePoint_t *pSP)
175 {
176     controlPoint_t cp;
177     strncpy(cp.strName, control, 64);
178
179     pSP->m_pointList.push_front(cp);
180 }
181
182 class EntityBuildPaths {
183     mutable DEntity e;
184     DTrainDrawer &drawer;
185 public:
186     EntityBuildPaths(DTrainDrawer &drawer) : drawer(drawer)
187     {
188     }
189
190     void operator()(scene::Instance &instance) const
191     {
192         e.ClearEPairs();
193         e.LoadEPairList(Node_getEntity(instance.path().top()));
194
195         const char *classname = e.m_Classname.GetBuffer();
196         const char *target;
197         const char *control;
198         const char *targetname;
199         vec3_t vOrigin;
200
201         e.SpawnString("targetname", NULL, &targetname);
202         e.SpawnVector("origin", "0 0 0", vOrigin);
203
204         if (!strcmp(classname, "info_train_spline_main")) {
205             if (!targetname) {
206                 globalOutputStream() << "info_train_spline_main with no targetname";
207                 return;
208             }
209
210             e.SpawnString("target", NULL, &target);
211
212             if (!target) {
213                 drawer.AddControlPoint(targetname, vOrigin);
214             } else {
215                 splinePoint_t *pSP = drawer.AddSplinePoint(targetname, target, vOrigin);
216
217                 e.SpawnString("control", NULL, &control);
218
219                 if (control) {
220                     AddSplineControl(control, pSP);
221
222                     for (int j = 2;; j++) {
223                         char buffer[18];
224                         sprintf(buffer, "control%i", j);
225
226                         e.SpawnString(buffer, NULL, &control);
227                         if (!control) {
228                             break;
229                         }
230
231                         AddSplineControl(control, pSP);
232                     }
233                 }
234             }
235         } else if (!strcmp(classname, "info_train_spline_control")) {
236             if (!targetname) {
237                 globalOutputStream() << "info_train_spline_control with no targetname";
238                 return;
239             }
240
241             drawer.AddControlPoint(targetname, vOrigin);
242         }
243     }
244 };
245
246 void DTrainDrawer::BuildPaths()
247 {
248     Scene_forEachEntity(EntityBuildPaths(*this));
249
250     std::list<splinePoint_t *>::const_iterator sp;
251     for (sp = m_splineList.begin(); sp != m_splineList.end(); sp++) {
252         splinePoint_t *pSP = (*sp);
253
254         controlPoint_t *pTarget = FindControlPoint(pSP->strTarget);
255
256         if (!pTarget) {
257             globalOutputStream() << "couldn't find target " << pSP->strTarget;
258             return;
259 //                      continue;
260         }
261
262         pSP->pTarget = pTarget;
263
264
265         for (std::list<controlPoint_t>::iterator cp = pSP->m_pointList.begin(); cp != pSP->m_pointList.end(); cp++) {
266             controlPoint_t *pControl = FindControlPoint((*cp).strName);
267             if (!pControl) {
268                 globalOutputStream() << "couldn't find control " << (*cp).strName;
269                 return;
270             }
271
272             VectorCopy(pControl->vOrigin, (*cp).vOrigin);
273         }
274     }
275
276     m_bDisplay = true;
277
278     for (sp = m_splineList.begin(); sp != m_splineList.end(); sp++) {
279         splinePoint_t *pSP = (*sp);
280         DPoint out;
281
282         if (!pSP->pTarget) {
283             continue;
284         }
285
286         std::size_t count = pSP->m_pointList.size() + 2;
287         vec3_t *v = new vec3_t[count];
288
289         VectorCopy(pSP->point.vOrigin, v[0]);
290
291         int i = 1;
292         for (std::list<controlPoint_t>::reverse_iterator cp = pSP->m_pointList.rbegin();
293              cp != pSP->m_pointList.rend(); cp++) {
294             VectorCopy((*cp).vOrigin, v[i]);
295             i++;
296         }
297         VectorCopy(pSP->pTarget->vOrigin, v[i]);
298
299         for (float tension = 0.0f; tension <= 1.f; tension += 0.01f) {
300             CalculateSpline_r(v, static_cast<int>( count ), out._pnt, tension);
301             pSP->m_vertexList.push_front(out);
302         }
303
304         delete[] v;
305
306         VectorCopy(pSP->pTarget->vOrigin, out._pnt);
307         pSP->m_vertexList.push_front(out);
308     }
309
310     SceneChangeNotify();
311 }
312
313 void DTrainDrawer::AddControlPoint(const char *name, vec_t *origin)
314 {
315     controlPoint_t *pCP = new controlPoint_t;
316
317     strncpy(pCP->strName, name, 64);
318     VectorCopy(origin, pCP->vOrigin);
319
320     m_pointList.push_back(pCP);
321 }
322
323 splinePoint_t *DTrainDrawer::AddSplinePoint(const char *name, const char *target, vec_t *origin)
324 {
325     splinePoint_t *pSP = new splinePoint_t;
326
327     strncpy(pSP->point.strName, name, 64);
328     strncpy(pSP->strTarget, target, 64);
329     VectorCopy(origin, pSP->point.vOrigin);
330     m_splineList.push_back(pSP);
331
332     return pSP;
333 }
334
335 controlPoint_t *DTrainDrawer::FindControlPoint(const char *name)
336 {
337     for (std::list<controlPoint_t *>::const_iterator cp = m_pointList.begin(); cp != m_pointList.end(); cp++) {
338         if (!strcmp(name, (*cp)->strName)) {
339             return (*cp);
340         }
341     }
342
343     for (std::list<splinePoint_t *>::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) {
344         if (!strcmp(name, (*sp)->point.strName)) {
345             return &((*sp)->point);
346         }
347     }
348
349     return NULL;
350 }