/* 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 */ #include "StdAfx.h" #include "DPoint.h" #include "DTrainDrawer.h" #include "DEPair.h" #include "misc.h" #include "funchandlers.h" #include "dialogs/dialogs-gtk.h" DTrainDrawer::DTrainDrawer() { refCount = 1; m_bHooked = FALSE; m_bDisplay = FALSE; BuildPaths(); } DTrainDrawer::~DTrainDrawer(void) { if(m_bHooked) UnRegister(); ClearPoints(); ClearSplines(); } void DTrainDrawer::ClearSplines() { for(list::const_iterator deadSpline = m_splineList.begin(); deadSpline != m_splineList.end(); deadSpline++) { (*deadSpline)->m_pointList.clear(); (*deadSpline)->m_vertexList.clear(); delete (*deadSpline); } m_splineList.clear(); } void DTrainDrawer::ClearPoints() { for(list::const_iterator deadPoint = m_pointList.begin(); deadPoint != m_pointList.end(); deadPoint++) { delete *deadPoint; } m_pointList.clear(); } void DTrainDrawer::Register() { g_QglTable.m_pfnHookGL2DWindow( this ); g_QglTable.m_pfnHookGL3DWindow( this ); m_bHooked = TRUE; } void DTrainDrawer::UnRegister() { g_QglTable.m_pfnUnHookGL2DWindow( this ); g_QglTable.m_pfnUnHookGL3DWindow( this ); m_bHooked = FALSE; } void CalculateSpline_r(vec3_t* v, int count, vec3_t out, float tension) { vec3_t dist; if(count < 2) { return; } if(count == 2) { VectorSubtract( v[1], v[0], dist ); VectorMA(v[0], tension, dist, out); return; } vec3_t* v2 = new vec3_t[count-1]; for( int i = 0; i < count-1; i++ ) { VectorSubtract( v[i+1], v[i], dist ); VectorMA(v[i], tension, dist, v2[i]); } CalculateSpline_r( v2, count-1, out, tension); delete[] v2; } void DTrainDrawer::Draw3D() { if(!m_bDisplay) { return; } g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS); g_QglTable.m_pfn_qglDisable(GL_BLEND); g_QglTable.m_pfn_qglDisable(GL_LINE_SMOOTH); g_QglTable.m_pfn_qglPushMatrix(); g_QglTable.m_pfn_qglLineWidth(2.0f); g_QglTable.m_pfn_qglColor4f(1.0f, 1.0f, 1.0f, 1.0f); g_QglTable.m_pfn_qglEnable(GL_BLEND); g_QglTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); g_QglTable.m_pfn_qglDisable(GL_POLYGON_SMOOTH); g_QglTable.m_pfn_qglDepthFunc(GL_ALWAYS); for(list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { splinePoint_t* pSP = (*sp); g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP); for(list::const_iterator v = pSP->m_vertexList.begin(); v != pSP->m_vertexList.end(); v++) { g_QglTable.m_pfn_qglVertex3fv((*v)._pnt); } g_QglTable.m_pfn_qglEnd(); } g_QglTable.m_pfn_qglPopMatrix(); g_QglTable.m_pfn_qglPopAttrib(); } void DTrainDrawer::Draw2D(VIEWTYPE vt) { if(!m_bDisplay) { return; } g_QglTable.m_pfn_qglPushAttrib(GL_ALL_ATTRIB_BITS); g_QglTable.m_pfn_qglDisable(GL_BLEND); g_QglTable.m_pfn_qglDisable(GL_LINE_SMOOTH); g_QglTable.m_pfn_qglPushMatrix(); switch(vt) { case XY: break; case XZ: g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f); break; case YZ: g_QglTable.m_pfn_qglRotatef(270.0f, 1.0f, 0.0f, 0.0f); g_QglTable.m_pfn_qglRotatef(270.0f, 0.0f, 0.0f, 1.0f); break; } g_QglTable.m_pfn_qglLineWidth(1.0f); g_QglTable.m_pfn_qglColor4f(1.0f, 0.0f, 0.0f, 0.5f); g_QglTable.m_pfn_qglEnable(GL_BLEND); g_QglTable.m_pfn_qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); g_QglTable.m_pfn_qglDisable(GL_POLYGON_SMOOTH); g_QglTable.m_pfn_qglDepthFunc(GL_ALWAYS); g_QglTable.m_pfn_qglColor4f(1.f, 0.f, 0.f, 1.f); for(list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { splinePoint_t* pSP = (*sp); g_QglTable.m_pfn_qglBegin(GL_LINE_STRIP); for(list::const_iterator v = pSP->m_vertexList.begin(); v != pSP->m_vertexList.end(); v++) { g_QglTable.m_pfn_qglVertex3fv((*v)._pnt); } g_QglTable.m_pfn_qglEnd(); } g_QglTable.m_pfn_qglPopMatrix(); g_QglTable.m_pfn_qglPopAttrib(); } void AddSplineControl(const char* control, splinePoint_t* pSP) { controlPoint_t cp; strncpy(cp.strName, control, 64); pSP->m_pointList.push_front(cp); } void DTrainDrawer::BuildPaths() { int count = g_FuncTable.m_pfnGetEntityCount(); DEntity e; for(int i = 0; i < count; i++) { entity_s* ent = (entity_s*)g_FuncTable.m_pfnGetEntityHandle(i); e.ClearEPairs(); e.LoadEPairList(*g_EntityTable.m_pfnGetEntityKeyValList(ent)); const char* classname = e.m_Classname.GetBuffer(); const char* target; const char* control; const char* targetname; vec3_t vOrigin; e.SpawnString("targetname", NULL, &targetname); e.SpawnVector("origin", "0 0 0", vOrigin); if(!strcmp(classname, "info_train_spline_main")) { if(!targetname) { Sys_Printf( "info_train_spline_main with no targetname" ); return; } e.SpawnString("target", NULL, &target); if(!target) { AddControlPoint( targetname, vOrigin ); } else { splinePoint_t* pSP = AddSplinePoint( targetname, target, vOrigin ); e.SpawnString("control", NULL, &control); if(control) { AddSplineControl( control, pSP ); for(int j = 2;; j++) { char buffer[16]; sprintf(buffer, "control%i", j); e.SpawnString(buffer, NULL, &control); if(!control) { break; } AddSplineControl( control, pSP ); } } } } else if(!strcmp(classname, "info_train_spline_control")) { if(!targetname) { Sys_Printf( "info_train_spline_control with no targetname" ); return; } AddControlPoint( targetname, vOrigin ); } } list::const_iterator sp; for(sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { splinePoint_t* pSP = (*sp); controlPoint_t* pTarget = FindControlPoint( pSP->strTarget ); if(!pTarget) { Sys_Printf( "couldn't find target %s", pSP->strTarget ); return; // continue; } pSP->pTarget = pTarget; for(list::iterator cp = pSP->m_pointList.begin(); cp != pSP->m_pointList.end(); cp++) { controlPoint_t* pControl = FindControlPoint( (*cp).strName ); if(!pControl) { Sys_Printf( "couldn't find control %s", (*cp).strName ); return; } VectorCopy(pControl->vOrigin, (*cp).vOrigin); } } m_bDisplay = TRUE; Register(); for(sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { splinePoint_t* pSP = (*sp); DPoint out; if(!pSP->pTarget) { continue; } int count = pSP->m_pointList.size() + 2; vec3_t* v = new vec3_t[count]; VectorCopy(pSP->point.vOrigin, v[0]); int i = 1; for(list::reverse_iterator cp = pSP->m_pointList.rbegin(); cp != pSP->m_pointList.rend(); cp++) { VectorCopy((*cp).vOrigin, v[i]); i++; } VectorCopy(pSP->pTarget->vOrigin, v[i]); for (float tension = 0.0f; tension <= 1.f; tension += 0.01f) { CalculateSpline_r(v, count, out._pnt, tension); pSP->m_vertexList.push_front(out); } delete[] v; VectorCopy(pSP->pTarget->vOrigin, out._pnt); pSP->m_vertexList.push_front(out); } } void DTrainDrawer::AddControlPoint(const char* name, vec_t* origin) { controlPoint_t* pCP = new controlPoint_t; strncpy(pCP->strName, name, 64); VectorCopy( origin, pCP->vOrigin ); m_pointList.push_back( pCP ); } splinePoint_t* DTrainDrawer::AddSplinePoint(const char* name, const char* target, vec_t* origin) { splinePoint_t* pSP = new splinePoint_t; strncpy(pSP->point.strName, name, 64); strncpy(pSP->strTarget, target, 64); VectorCopy( origin, pSP->point.vOrigin ); m_splineList.push_back( pSP ); return pSP; } controlPoint_t* DTrainDrawer::FindControlPoint(const char* name) { for(list::const_iterator cp = m_pointList.begin(); cp != m_pointList.end(); cp++) { if(!strcmp(name, (*cp)->strName)) { return (*cp); } } for(list::const_iterator sp = m_splineList.begin(); sp != m_splineList.end(); sp++) { if(!strcmp(name, (*sp)->point.strName)) { return &((*sp)->point); } } return NULL; }