]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/bobtoolz/DBobView.cpp
940d1918d755f56a04259411f7648f45d12ed5bb
[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 "DBobView.h"
25 //#include "misc.h"
26 #include "funchandlers.h"
27
28 #include <list>
29
30 #include "iglrender.h"
31 #include "qerplugin.h"
32 #include "str.h"
33 #include "math/matrix.h"
34
35 #include "DEntity.h"
36 #include "DEPair.h"
37 #include "misc.h"
38 #include "dialogs/dialogs-gtk.h"
39
40 //////////////////////////////////////////////////////////////////////
41 // Construction/Destruction
42 //////////////////////////////////////////////////////////////////////
43
44 DBobView::DBobView()
45 {
46     nPathCount = 0;
47
48     path = NULL;
49
50     boundingShow = BOUNDS_APEX;
51
52     constructShaders();
53     GlobalShaderCache().attachRenderable(*this);
54 }
55
56 DBobView::~DBobView()
57 {
58     GlobalShaderCache().detachRenderable(*this);
59     destroyShaders();
60
61     if (path) {
62         delete[] path;
63     }
64
65     g_PathView = NULL;
66 }
67
68 //////////////////////////////////////////////////////////////////////
69 // Implementation
70 //////////////////////////////////////////////////////////////////////
71
72 void DBobView::render(RenderStateFlags state) const
73 {
74     glBegin(GL_LINE_STRIP);
75
76     for (int i = 0; i < nPathCount; i++)
77         glVertex3fv(path[i]);
78
79     glEnd();
80 }
81
82 const char *DBobView_state_line = "$bobtoolz/bobview/line";
83 const char *DBobView_state_box = "$bobtoolz/bobview/box";
84
85 void DBobView::constructShaders()
86 {
87     OpenGLState state;
88     GlobalOpenGLStateLibrary().getDefaultState(state);
89     state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND | RENDER_LINESMOOTH;
90     state.m_sort = OpenGLState::eSortOpaque;
91     state.m_linewidth = 1;
92     state.m_colour[0] = 1;
93     state.m_colour[1] = 0;
94     state.m_colour[2] = 0;
95     state.m_colour[3] = 1;
96     GlobalOpenGLStateLibrary().insert(DBobView_state_line, state);
97
98     state.m_colour[0] = 0.25f;
99     state.m_colour[1] = 0.75f;
100     state.m_colour[2] = 0.75f;
101     state.m_colour[3] = 1;
102     GlobalOpenGLStateLibrary().insert(DBobView_state_box, state);
103
104     m_shader_line = GlobalShaderCache().capture(DBobView_state_line);
105     m_shader_box = GlobalShaderCache().capture(DBobView_state_box);
106 }
107
108 void DBobView::destroyShaders()
109 {
110     GlobalOpenGLStateLibrary().erase(DBobView_state_line);
111     GlobalOpenGLStateLibrary().erase(DBobView_state_box);
112     GlobalShaderCache().release(DBobView_state_line);
113     GlobalShaderCache().release(DBobView_state_box);
114 }
115
116 Matrix4 g_transform_box1 = matrix4_translation_for_vec3(Vector3(16.0f, 16.0f, 28.0f));
117 Matrix4 g_transform_box2 = matrix4_translation_for_vec3(Vector3(-16.0f, 16.0f, 28.0f));
118 Matrix4 g_transform_box3 = matrix4_translation_for_vec3(Vector3(16.0f, -16.0f, -28.0f));
119 Matrix4 g_transform_box4 = matrix4_translation_for_vec3(Vector3(-16.0f, -16.0f, -28.0f));
120
121 void DBobView::renderSolid(Renderer &renderer, const VolumeTest &volume) const
122 {
123     if (!path) {
124         return;
125     }
126
127     renderer.SetState(m_shader_line, Renderer::eWireframeOnly);
128     renderer.SetState(m_shader_line, Renderer::eFullMaterials);
129     renderer.addRenderable(*this, g_matrix4_identity);
130
131     if (m_bShowExtra) {
132         renderer.SetState(m_shader_box, Renderer::eWireframeOnly);
133         renderer.SetState(m_shader_box, Renderer::eFullMaterials);
134         renderer.addRenderable(*this, g_transform_box1);
135         renderer.addRenderable(*this, g_transform_box2);
136         renderer.addRenderable(*this, g_transform_box3);
137         renderer.addRenderable(*this, g_transform_box4);
138     }
139 }
140
141 void DBobView::renderWireframe(Renderer &renderer, const VolumeTest &volume) const
142 {
143     renderSolid(renderer, volume);
144 }
145
146 void DBobView::SetPath(vec3_t *pPath)
147 {
148     if (path) {
149         delete[] path;
150     }
151
152     path = pPath;
153 }
154
155 const float LOCAL_GRAVITY = -800.0f;
156
157 bool DBobView::CalculateTrajectory(vec3_t start, vec3_t apex, float multiplier, int points, float varGravity)
158 {
159     if (apex[2] <= start[2]) {
160         SetPath(NULL);
161         return false;
162     }
163     // ----think q3a actually would allow these
164     //scrub that, coz the plugin wont :]
165
166     vec3_t dist, speed;
167     VectorSubtract(apex, start, dist);
168
169     vec_t speed_z = (float) sqrt(-2 * LOCAL_GRAVITY * dist[2]);
170     float flight_time = -speed_z / LOCAL_GRAVITY;
171
172
173     VectorScale(dist, 1 / flight_time, speed);
174     speed[2] = speed_z;
175
176 //      Sys_Printf("Speed: (%.4f %.4f %.4f)\n", speed[0], speed[1], speed[2]);
177
178     vec3_t *pPath = new vec3_t[points];
179
180     float interval = multiplier * flight_time / points;
181     for (int i = 0; i < points; i++) {
182         float ltime = interval * i;
183
184         VectorScale(speed, ltime, pPath[i]);
185         VectorAdd(pPath[i], start, pPath[i]);
186
187         // could do this all with vectors
188         // vGrav = {0, 0, -800.0f}
189         // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd);
190         // VectorScale(speed, ltime, pPath[i]);
191         // _VectorAdd(pPath[i], start, pPath[i])
192         // _VectorAdd(pPath[i], vAdd, pPath[i])
193
194         pPath[i][2] = start[2] + (speed_z * ltime) + (varGravity * 0.5f * ltime * ltime);
195     }
196
197     SetPath(pPath);
198     return true;
199 }
200
201 void
202 DBobView::Begin(const char *trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate,
203                 bool bShowExtra)
204 {
205     strcpy(entTrigger, trigger);
206     strcpy(entTarget, target);
207
208     fMultiplier = multiplier;
209     fVarGravity = varGravity;
210     nPathCount = points;
211     m_bShowExtra = bShowExtra;
212
213     if (!UpdatePath()) {
214         globalErrorStream() << "Initialization Failure in DBobView::Begin";
215         delete this;
216     }
217     globalOutputStream() << "Initialization of Path Plotter succeeded.";
218 }
219
220 bool DBobView::UpdatePath()
221 {
222     vec3_t start, apex;
223
224     if (GetEntityCentre(entTrigger, start)) {
225         if (GetEntityCentre(entTarget, apex)) {
226             CalculateTrajectory(start, apex, fMultiplier, nPathCount, fVarGravity);
227             return true;
228         }
229     }
230     return false;
231 }
232
233 void DBobView_setEntity(Entity &entity, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra)
234 {
235     DEntity trigger;
236     trigger.LoadEPairList(&entity);
237
238     DEPair *trigger_ep = trigger.FindEPairByKey("targetname");
239
240     if (trigger_ep) {
241         if (!strcmp(trigger.m_Classname, "trigger_push")) {
242             DEPair *target_ep = trigger.FindEPairByKey("target");
243             if (target_ep) {
244                 const scene::Path *entTarget = FindEntityFromTargetname(target_ep->value);
245                 if (entTarget) {
246                     if (g_PathView) {
247                         delete g_PathView;
248                     }
249                     g_PathView = new DBobView;
250
251                     Entity *target = Node_getEntity(entTarget->top());
252                     if (target != 0) {
253                         if (!bNoUpdate) {
254                             g_PathView->trigger = &entity;
255                             entity.attach(*g_PathView);
256                             g_PathView->target = target;
257                             target->attach(*g_PathView);
258                         }
259                         g_PathView->Begin(trigger_ep->value, target_ep->value, multiplier, points, varGravity,
260                                           bNoUpdate, bShowExtra);
261                     } else {
262                         globalErrorStream() << "bobToolz PathPlotter: trigger_push ARGH\n";
263                     }
264                 } else {
265                     globalErrorStream() << "bobToolz PathPlotter: trigger_push target could not be found..\n";
266                 }
267             } else {
268                 globalErrorStream() << "bobToolz PathPlotter: trigger_push has no target..\n";
269             }
270         } else {
271             globalErrorStream() << "bobToolz PathPlotter: You must select a 'trigger_push' entity..\n";
272         }
273     } else {
274         globalErrorStream() << "bobToolz PathPlotter: Entity must have a targetname.\n";
275     }
276     return;
277 }