/* BobToolz plugin for GtkRadiant Copyright (C) 2001 Gordon Biggans This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // BobView.cpp: implementation of the DBobView class. // ////////////////////////////////////////////////////////////////////// #include "DBobView.h" //#include "misc.h" #include "funchandlers.h" #include #include "iglrender.h" #include "qerplugin.h" #include "str.h" #include "math/matrix.h" #include "DEntity.h" #include "DEPair.h" #include "misc.h" #include "dialogs/dialogs-gtk.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// DBobView::DBobView() { nPathCount = 0; path = NULL; boundingShow = BOUNDS_APEX; constructShaders(); GlobalShaderCache().attachRenderable(*this); } DBobView::~DBobView() { GlobalShaderCache().detachRenderable(*this); destroyShaders(); if (path) { delete[] path; } g_PathView = NULL; } ////////////////////////////////////////////////////////////////////// // Implementation ////////////////////////////////////////////////////////////////////// void DBobView::render(RenderStateFlags state) const { glBegin(GL_LINE_STRIP); for (int i = 0; i < nPathCount; i++) glVertex3fv(path[i]); glEnd(); } const char *DBobView_state_line = "$bobtoolz/bobview/line"; const char *DBobView_state_box = "$bobtoolz/bobview/box"; void DBobView::constructShaders() { OpenGLState state; GlobalOpenGLStateLibrary().getDefaultState(state); state.m_state = RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_BLEND | RENDER_LINESMOOTH; state.m_sort = OpenGLState::eSortOpaque; state.m_linewidth = 1; state.m_colour[0] = 1; state.m_colour[1] = 0; state.m_colour[2] = 0; state.m_colour[3] = 1; GlobalOpenGLStateLibrary().insert(DBobView_state_line, state); state.m_colour[0] = 0.25f; state.m_colour[1] = 0.75f; state.m_colour[2] = 0.75f; state.m_colour[3] = 1; GlobalOpenGLStateLibrary().insert(DBobView_state_box, state); m_shader_line = GlobalShaderCache().capture(DBobView_state_line); m_shader_box = GlobalShaderCache().capture(DBobView_state_box); } void DBobView::destroyShaders() { GlobalOpenGLStateLibrary().erase(DBobView_state_line); GlobalOpenGLStateLibrary().erase(DBobView_state_box); GlobalShaderCache().release(DBobView_state_line); GlobalShaderCache().release(DBobView_state_box); } Matrix4 g_transform_box1 = matrix4_translation_for_vec3(Vector3(16.0f, 16.0f, 28.0f)); Matrix4 g_transform_box2 = matrix4_translation_for_vec3(Vector3(-16.0f, 16.0f, 28.0f)); Matrix4 g_transform_box3 = matrix4_translation_for_vec3(Vector3(16.0f, -16.0f, -28.0f)); Matrix4 g_transform_box4 = matrix4_translation_for_vec3(Vector3(-16.0f, -16.0f, -28.0f)); void DBobView::renderSolid(Renderer &renderer, const VolumeTest &volume) const { if (!path) { return; } renderer.SetState(m_shader_line, Renderer::eWireframeOnly); renderer.SetState(m_shader_line, Renderer::eFullMaterials); renderer.addRenderable(*this, g_matrix4_identity); if (m_bShowExtra) { renderer.SetState(m_shader_box, Renderer::eWireframeOnly); renderer.SetState(m_shader_box, Renderer::eFullMaterials); renderer.addRenderable(*this, g_transform_box1); renderer.addRenderable(*this, g_transform_box2); renderer.addRenderable(*this, g_transform_box3); renderer.addRenderable(*this, g_transform_box4); } } void DBobView::renderWireframe(Renderer &renderer, const VolumeTest &volume) const { renderSolid(renderer, volume); } void DBobView::SetPath(vec3_t *pPath) { if (path) { delete[] path; } path = pPath; } const float LOCAL_GRAVITY = -800.0f; bool DBobView::CalculateTrajectory(vec3_t start, vec3_t apex, float multiplier, int points, float varGravity) { if (apex[2] <= start[2]) { SetPath(NULL); return false; } // ----think q3a actually would allow these //scrub that, coz the plugin wont :] vec3_t dist, speed; VectorSubtract(apex, start, dist); vec_t speed_z = (float) sqrt(-2 * LOCAL_GRAVITY * dist[2]); float flight_time = -speed_z / LOCAL_GRAVITY; VectorScale(dist, 1 / flight_time, speed); speed[2] = speed_z; // Sys_Printf("Speed: (%.4f %.4f %.4f)\n", speed[0], speed[1], speed[2]); vec3_t *pPath = new vec3_t[points]; float interval = multiplier * flight_time / points; for (int i = 0; i < points; i++) { float ltime = interval * i; VectorScale(speed, ltime, pPath[i]); VectorAdd(pPath[i], start, pPath[i]); // could do this all with vectors // vGrav = {0, 0, -800.0f} // VectorScale(vGrav, 0.5f*ltime*ltime, vAdd); // VectorScale(speed, ltime, pPath[i]); // _VectorAdd(pPath[i], start, pPath[i]) // _VectorAdd(pPath[i], vAdd, pPath[i]) pPath[i][2] = start[2] + (speed_z * ltime) + (varGravity * 0.5f * ltime * ltime); } SetPath(pPath); return true; } void DBobView::Begin(const char *trigger, const char *target, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra) { strcpy(entTrigger, trigger); strcpy(entTarget, target); fMultiplier = multiplier; fVarGravity = varGravity; nPathCount = points; m_bShowExtra = bShowExtra; if (!UpdatePath()) { globalErrorStream() << "Initialization Failure in DBobView::Begin"; delete this; } globalOutputStream() << "Initialization of Path Plotter succeeded."; } bool DBobView::UpdatePath() { vec3_t start, apex; if (GetEntityCentre(entTrigger, start)) { if (GetEntityCentre(entTarget, apex)) { CalculateTrajectory(start, apex, fMultiplier, nPathCount, fVarGravity); return true; } } return false; } void DBobView_setEntity(Entity &entity, float multiplier, int points, float varGravity, bool bNoUpdate, bool bShowExtra) { DEntity trigger; trigger.LoadEPairList(&entity); DEPair *trigger_ep = trigger.FindEPairByKey("targetname"); if (trigger_ep) { if (!strcmp(trigger.m_Classname, "trigger_push")) { DEPair *target_ep = trigger.FindEPairByKey("target"); if (target_ep) { const scene::Path *entTarget = FindEntityFromTargetname(target_ep->value); if (entTarget) { if (g_PathView) { delete g_PathView; } g_PathView = new DBobView; Entity *target = Node_getEntity(entTarget->top()); if (target != 0) { if (!bNoUpdate) { g_PathView->trigger = &entity; entity.attach(*g_PathView); g_PathView->target = target; target->attach(*g_PathView); } g_PathView->Begin(trigger_ep->value, target_ep->value, multiplier, points, varGravity, bNoUpdate, bShowExtra); } else { globalErrorStream() << "bobToolz PathPlotter: trigger_push ARGH\n"; } } else { globalErrorStream() << "bobToolz PathPlotter: trigger_push target could not be found..\n"; } } else { globalErrorStream() << "bobToolz PathPlotter: trigger_push has no target..\n"; } } else { globalErrorStream() << "bobToolz PathPlotter: You must select a 'trigger_push' entity..\n"; } } else { globalErrorStream() << "bobToolz PathPlotter: Entity must have a targetname.\n"; } return; }