47215106d2b388c52c1062193547ec236a0e4243
[xonotic/netradiant.git] / contrib / bobtoolz / DBobView.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 // BobView.cpp: implementation of the DBobView class.
21 //
22 //////////////////////////////////////////////////////////////////////
23
24 #include "StdAfx.h"
25 #include "DBobView.h"
26 #include "DListener.h"
27 #include "misc.h"
28 #include "funchandlers.h"
29
30 //////////////////////////////////////////////////////////////////////
31 // Construction/Destruction
32 //////////////////////////////////////////////////////////////////////
33
34 DBobView::DBobView()
35 {
36         nPathCount = 0;
37         refCount = 1;
38         
39         m_bHooked = FALSE;
40
41         path = NULL;
42         eyes = NULL;
43
44         boundingShow = BOUNDS_APEX;
45 }
46
47 DBobView::~DBobView()
48 {
49         if(path)
50                 delete[] path;
51
52         // oops forgot to remove our eyes, was causing access violation when it tried
53         // to talk to it's parent
54         if(eyes)
55                 delete eyes;
56
57         if(m_bHooked)
58                 UnRegister();
59
60         g_PathView = NULL;
61 }
62
63 //////////////////////////////////////////////////////////////////////
64 // Implementation
65 //////////////////////////////////////////////////////////////////////
66
67 void DBobView::Draw2D(VIEWTYPE vt)
68 {
69         if(!path)
70                 return;
71
72         g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);
73
74         g_QglTable.m_pfn_qglDisable(GL_BLEND);
75         g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);
76
77         g_QglTable.m_pfn_qglPushMatrix();
78         
79         switch(vt)
80         {
81         case XY:
82                 break;
83         case XZ:
84                 g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);
85                 break;
86         case YZ:
87                 g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f);
88                 g_QglTable.m_pfn_qglRotatef(270.0f, 0.0f, 0.0f, 1.0f);
89                 break;
90         }
91
92         g_QglTable.m_pfn_qglLineWidth(1.0f);
93         g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 1.0f);
94
95         int i;
96
97         g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP);
98
99         for(i = 0; i < nPathCount; i++)
100                 g_QglTable.m_pfn_qglVertex3fv(path[i]);
101
102         g_QglTable.m_pfn_qglEnd();
103
104         if(m_bShowExtra)
105         {
106                 // +mars
107                 // for the bounding box stuff
108                 g_QglTable.m_pfn_qglColor4f(0.25f, 0.75f, 0.75f, 1.0f);
109
110                 g_QglTable.m_pfn_qglTranslatef( 16.0f, 16.0f, 28.0f );
111
112                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
113         
114                         for ( i = 0; i < nPathCount; i++ )
115                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
116
117                 g_QglTable.m_pfn_qglEnd();
118         
119         // ---------------
120
121                 g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );       // back to where we were
122                 g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // move to new postion
123         
124                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
125
126                         for ( i = 0; i < nPathCount; i++ )
127                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
128
129                 g_QglTable.m_pfn_qglEnd();
130
131         // --------------
132
133                 g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // back to where we were
134                 g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // new pos
135
136                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
137                 
138                         for ( i = 0; i < nPathCount; i++ )
139                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
140
141                 g_QglTable.m_pfn_qglEnd();
142
143         // ----------------
144
145                 g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // back to where we were
146
147 /*              g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );               // new pos
148
149                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
150                 
151                 if ( boundingShow == BOUNDS_ALL )
152                 {
153                         for ( i = 0; i < nPathCount; i++ )
154                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
155                 }
156                 else if ( boundingShow == BOUNDS_APEX )
157                 {
158                         for ( i = (nPathCount/4); i < (nPathCount/4) * 3; i++ )
159                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
160                 }
161
162                 g_QglTable.m_pfn_qglEnd();*/ // djbob: er, um doesn't really seem to do anyhting
163         }
164
165         // -mars
166         
167         g_QglTable.m_pfn_qglPopMatrix();
168
169         g_QglTable.m_pfn_qglPopAttrib();
170 }
171
172 void DBobView::Draw3D()
173 {
174         if(!path)
175                 return;
176
177         g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS);
178
179         g_QglTable.m_pfn_qglDisable(GL_BLEND);
180         g_QglTable.m_pfn_qglEnable(GL_LINE_SMOOTH);
181
182         g_QglTable.m_pfn_qglLineWidth(1.0f);
183         g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 1.0f);
184
185         g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP);
186
187         for(int i = 0; i < nPathCount; i++)
188                 g_QglTable.m_pfn_qglVertex3fv(path[i]);
189
190         g_QglTable.m_pfn_qglEnd();
191
192         if(m_bShowExtra)
193         {
194                 // +mars
195                 // ahhh -- a nice C&P job :)
196                 // for the bounding box stuff
197                 g_QglTable.m_pfn_qglColor4f(0.25f, 0.75f, 0.75f, 1.0f);
198
199                 g_QglTable.m_pfn_qglTranslatef( 16.0f, 16.0f, 28.0f );
200
201                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
202                 
203                 int i;  
204                 for ( i = 0; i < nPathCount; i++ )
205                         g_QglTable.m_pfn_qglVertex3fv( path[i] );
206
207                 g_QglTable.m_pfn_qglEnd();
208         
209         // ---------------
210
211                 g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );       // back to where we were
212                 g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // move to new postion
213         
214                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
215                 
216                         for ( i = 0; i < nPathCount; i++ )
217                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
218
219                 g_QglTable.m_pfn_qglEnd();
220
221         // --------------
222
223                 g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // back to where we were
224                 g_QglTable.m_pfn_qglTranslatef( 16.0f, -16.0f, -28.0f );                // new pos
225
226                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
227                 
228                         for ( i = 0; i < nPathCount; i++ )
229                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
230
231                 g_QglTable.m_pfn_qglEnd();
232
233         // ----------------
234
235                 g_QglTable.m_pfn_qglTranslatef( -16.0f, 16.0f, 28.0f );         // back to where we were
236                 g_QglTable.m_pfn_qglTranslatef( -16.0f, -16.0f, -28.0f );               // new pos
237
238                 g_QglTable.m_pfn_qglBegin( GL_LINE_STRIP );
239                 
240                         for ( i = 0; i < nPathCount; i++ )
241                                 g_QglTable.m_pfn_qglVertex3fv( path[i] );
242
243                 g_QglTable.m_pfn_qglEnd();
244         }
245         // -mars
246
247         g_QglTable.m_pfn_qglPopAttrib();
248 }
249
250 void DBobView::Register()
251 {
252         g_QglTable.m_pfnHookGL2DWindow( this );
253         g_QglTable.m_pfnHookGL3DWindow( this );
254         m_bHooked = TRUE;
255 }
256
257 void DBobView::UnRegister()
258 {
259         g_QglTable.m_pfnUnHookGL2DWindow( this );
260         g_QglTable.m_pfnUnHookGL3DWindow( this );
261         m_bHooked = FALSE;
262 }
263
264 void DBobView::SetPath(vec3_t *pPath)
265 {
266         if(path)
267                 delete[] path;
268
269         path = pPath;
270 }
271
272 #define LOCAL_GRAVITY -800.0f
273
274 bool DBobView::CalculateTrajectory(vec3_t start, vec3_t apex, float multiplier, int points, float varGravity)
275 {
276         if(apex[2] <= start[2])
277         {
278                 SetPath(NULL);
279                 return FALSE;
280         }
281         // ----think q3a actually would allow these
282         //scrub that, coz the plugin wont :]
283
284         vec3_t dist, speed;
285         VectorSubtract(apex, start, dist);
286
287         vec_t speed_z = (float)sqrt(-2*LOCAL_GRAVITY*dist[2]);
288         float flight_time = -speed_z/LOCAL_GRAVITY;
289
290
291         VectorScale(dist, 1/flight_time, speed);
292         speed[2] = speed_z;
293
294 //      Sys_Printf("Speed: (%.4f %.4f %.4f)\n", speed[0], speed[1], speed[2]);
295
296         vec3_t* pPath = new vec3_t[points];
297
298         float interval = multiplier*flight_time/points;
299         for(int i = 0; i < points; i++)
300         {
301                 float ltime = interval*i;
302
303                 VectorScale(speed, ltime, pPath[i]);
304                 VectorAdd(pPath[i], start, pPath[i]);
305
306                 // could do this all with vectors
307                 // vGrav = {0, 0, -800.0f}
308                 // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd);
309                 // VectorScale(speed, ltime, pPath[i]);
310                 // _VectorAdd(pPath[i], start, pPath[i])
311                 // _VectorAdd(pPath[i], vAdd, pPath[i])
312
313                 pPath[i][2] = start[2] + (speed_z*ltime) + (varGravity*0.5f*ltime*ltime);
314         }
315
316         SetPath(pPath);
317         return TRUE;
318 }
319
320 void DBobView::Begin(const char* trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra)
321 {
322         strcpy(entTrigger, trigger);
323         strcpy(entTarget, target);
324
325         fMultiplier = multiplier;
326         fVarGravity = varGravity;
327         nPathCount = points;
328         m_bShowExtra = bShowExtra;
329
330         Register();
331
332         if(UpdatePath())
333         {
334                 if(!bNoUpdate)
335                 {
336                         eyes = new DListener;
337                         eyes->parent = this;
338                         eyes->Register();
339                 }
340         }
341         else
342         {
343                 Sys_ERROR("Initialization Failure in DBobView::Begin");
344                 delete this;
345         }
346 }
347
348 bool DBobView::UpdatePath()
349 {
350         vec3_t start, apex;
351
352         if(GetEntityCentre(entTrigger, start))
353         {
354                 if(GetEntityCentre(entTarget, apex))
355                 {
356                         CalculateTrajectory(start, apex, fMultiplier, nPathCount, fVarGravity);
357                         return TRUE;
358                 }
359         }
360         return FALSE;
361 }