/* 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; }