/* 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 */ // DShape.cpp: implementation of the DShape class. // ////////////////////////////////////////////////////////////////////// #include "DShape.h" #include #include #include "str.h" #include "DPoint.h" #include "DPlane.h" #include "DBrush.h" #include "DEPair.h" #include "DPatch.h" #include "DEntity.h" //#include "dialogs-gtk.h" #include "misc.h" #include "shapes.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// bool bFacesAll[6] = {true, true, true, true, true, true}; DShape::DShape(){ m_nNextBrush = 0; } DShape::~DShape(){ } void DShape::BuildRegularPrism( vec3_t min, vec3_t max, int nSides, bool bAlignTop ){ vec3_t vc[MAX_POLYGON_FACES + 2], vd[MAX_POLYGON_FACES + 2]; vec3_t radius; vec3_t origin; VectorSubtract( max, min, radius ); VectorScale( radius, 0.5f, radius ); // calc 3d radius and origin VectorAdd( max, min, origin ); VectorScale( origin, 0.5f, origin ); float phase = 0.0f; if ( bAlignTop ) { phase = -( Q_PI / nSides ); VectorScale( radius, static_cast( 1.0 / cos( phase ) ), radius ); } //----- Build Polygon Vertices ----- int i; for ( i = 0; i < nSides; i++ ) { VectorCopy( origin, vc[i] ); VectorCopy( origin, vd[i] ); vc[i][2] = min[2]; vd[i][2] = max[2]; vc[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase ); vc[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase ); vd[i][0] = vc[i][0]; vd[i][1] = vc[i][1]; } VectorCopy( vc[0], vc[nSides] ); VectorCopy( vd[0], vd[nSides] ); VectorCopy( vc[1], vc[nSides + 1] ); VectorCopy( vd[1], vd[nSides + 1] ); //---------------------------------- DBrush* pB = m_Container.GetWorldSpawn()->NewBrush( m_nNextBrush++ ); for ( i = 1; i <= nSides; i++ ) pB->AddFace( vc[i - 1], vc[i], vd[i], GetCurrentTexture(), false ); pB->AddFace( vc[2], vc[1], vc[0], "textures/common/caulk", false ); pB->AddFace( vd[0], vd[1], vd[2], "textures/common/caulk", false ); } void DShape::Commit(){ m_Container.GetWorldSpawn()->FixBrushes(); m_Container.BuildInRadiant( true ); } void DShape::BuildInversePrism( vec3_t min, vec3_t max, int nSides, bool bAlignTop ){ vec3_t va[MAX_POLYGON_FACES + 1], vb[MAX_POLYGON_FACES + 1]; vec3_t radius; vec3_t origin; VectorSubtract( max, min, radius ); VectorScale( radius, 0.5f, radius ); // calc 3d radius and origin VectorAdd( max, min, origin ); VectorScale( origin, 0.5f, origin ); float phase = 0.0f; if ( bAlignTop ) { phase = -( Q_PI / nSides ); VectorScale( radius, static_cast( 1.0 / cos( phase ) ), radius ); } //----- Build Polygon Vertices ----- int i; for ( i = 0; i < nSides; i++ ) { VectorCopy( origin, va[i] ); VectorCopy( origin, vb[i] ); va[i][2] = min[2]; vb[i][2] = max[2]; va[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase ); va[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase ); vb[i][0] = va[i][0]; vb[i][1] = va[i][1]; } VectorCopy( va[0], va[nSides] ); VectorCopy( vb[0], vb[nSides] ); //---------------------------------- for ( i = 1; i <= nSides; i++ ) { DBrush* pB = GetBoundingCube( min, max, "textures/common/caulk" ); vec3_t top, bottom; VectorCopy( va[i - 1], top ); VectorCopy( va[i], bottom ); if ( va[i - 1][1] > va[i][1] ) { top[0] += 5; bottom[0] += 5; } else // flip direction of plane on crossover { top[0] -= 5; bottom[0] -= 5; } if ( top[1] != bottom[1] ) { // internal line is flat already if true pB->AddFace( va[i - 1], top, vb[i - 1], "textures/common/caulk", false ); pB->AddFace( va[i], vb[i], bottom, "textures/common/caulk", false ); } // add cut-off planes pB->AddFace( va[i - 1], vb[i - 1], vb[i], GetCurrentTexture(), false ); // add internal polygon plane } } void DShape::BuildBorderedPrism( vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop ){ vec3_t va[MAX_POLYGON_FACES + 2], vb[MAX_POLYGON_FACES + 2]; vec3_t vc[MAX_POLYGON_FACES + 2], vd[MAX_POLYGON_FACES + 2]; vec3_t radius; vec3_t origin; VectorSubtract( max, min, radius ); VectorScale( radius, 0.5f, radius ); // calc 3d radius and origin VectorAdd( max, min, origin ); VectorScale( origin, 0.5f, origin ); if ( nBorder >= Min( radius[0], radius[1] ) ) { // DoMessageBox("Border is too large", "Error", MB_OK); return; } float phase = 0.0f; if ( bAlignTop ) { phase = -( Q_PI / nSides ); VectorScale( radius, static_cast( 1.0 / cos( phase ) ), radius ); } //----- Build Polygon Vertices ----- int i; for ( i = 0; i < nSides; i++ ) { VectorCopy( origin, va[i] ); VectorCopy( origin, vb[i] ); VectorCopy( origin, vc[i] ); VectorCopy( origin, vd[i] ); va[i][2] = min[2]; vb[i][2] = max[2]; va[i][0] += ( radius[0] - nBorder ) * sinf( ( 2 * Q_PI * i / nSides ) + phase ); va[i][1] += ( radius[1] - nBorder ) * cosf( ( 2 * Q_PI * i / nSides ) + phase ); vb[i][0] = va[i][0]; vb[i][1] = va[i][1]; vc[i][2] = min[2]; vd[i][2] = max[2]; vc[i][0] += radius[0] * sinf( ( 2 * Q_PI * i / nSides ) + phase ); vc[i][1] += radius[1] * cosf( ( 2 * Q_PI * i / nSides ) + phase ); vd[i][0] = vc[i][0]; vd[i][1] = vc[i][1]; } VectorCopy( va[0], va[nSides] ); VectorCopy( vb[0], vb[nSides] ); VectorCopy( va[1], va[nSides + 1] ); VectorCopy( vb[1], vb[nSides + 1] ); VectorCopy( vc[0], vc[nSides] ); VectorCopy( vd[0], vd[nSides] ); VectorCopy( vc[1], vc[nSides + 1] ); VectorCopy( vd[1], vd[nSides + 1] ); //---------------------------------- for ( i = 1; i <= nSides; i++ ) { DBrush* pB = GetBoundingCube( min, max, "textures/common/caulk" ); pB->AddFace( origin, vc[i - 1], vd[i - 1], "textures/common/caulk", false ); pB->AddFace( origin, vd[i], vc[i], "textures/common/caulk", false ); pB->AddFace( vc[i - 1], vc[i], vd[i], GetCurrentTexture(), false ); pB->AddFace( vb[i], va[i], va[i - 1], GetCurrentTexture(), false ); } } DBrush* DShape::GetBoundingCube_Ext( vec3_t min, vec3_t max, const char *textureName, bool* bUseFaces, bool detail ){ DBrush* pB = new DBrush; //----- Build Outer Bounds --------- vec3_t v1, v2, v3, v5, v6, v7; VectorCopy( min, v1 ); VectorCopy( min, v2 ); VectorCopy( min, v3 ); VectorCopy( max, v5 ); VectorCopy( max, v6 ); VectorCopy( max, v7 ); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; //---------------------------------- //----- Add Six Cube Faces --------- if ( bUseFaces[0] ) { pB->AddFace( v1, v2, v3, textureName, detail ); } if ( bUseFaces[1] ) { pB->AddFace( v1, v3, v6, textureName, detail ); } if ( bUseFaces[2] ) { pB->AddFace( v1, v7, v2, textureName, detail ); } if ( bUseFaces[3] ) { pB->AddFace( v5, v6, v3, textureName, detail ); } if ( bUseFaces[4] ) { pB->AddFace( v5, v2, v7, textureName, detail ); } if ( bUseFaces[5] ) { pB->AddFace( v5, v7, v6, textureName, detail ); } //---------------------------------- return pB; } DBrush* DShape::GetBoundingCube( vec3_t min, vec3_t max, const char *textureName, DEntity* ent, bool* bUseFaces ){ DBrush* pB; if ( ent == NULL ) { pB = m_Container.GetWorldSpawn()->NewBrush( m_nNextBrush++ ); } else{ pB = ent->NewBrush( m_nNextBrush++ ); } //----- Build Outer Bounds --------- vec3_t v1, v2, v3, v5, v6, v7; VectorCopy( min, v1 ); VectorCopy( min, v2 ); VectorCopy( min, v3 ); VectorCopy( max, v5 ); VectorCopy( max, v6 ); VectorCopy( max, v7 ); v2[0] = max[0]; v3[1] = max[1]; v6[0] = min[0]; v7[1] = min[1]; //---------------------------------- //----- Add Six Cube Faces --------- if ( bUseFaces[0] ) { pB->AddFace( v1, v2, v3, textureName, false ); } if ( bUseFaces[1] ) { pB->AddFace( v1, v3, v6, textureName, false ); } if ( bUseFaces[2] ) { pB->AddFace( v1, v7, v2, textureName, false ); } if ( bUseFaces[3] ) { pB->AddFace( v5, v6, v3, textureName, false ); } if ( bUseFaces[4] ) { pB->AddFace( v5, v2, v7, textureName, false ); } if ( bUseFaces[5] ) { pB->AddFace( v5, v7, v6, textureName, false ); } //---------------------------------- return pB; } bool DShape::BuildPit( vec3_t min, vec3_t max ){ if ( ( max[2] - min[2] ) < 196 ) { return false; } srand( time( NULL ) ); vec3_t centre; VectorAdd( min, max, centre ); VectorScale( centre, 0.5f, centre ); char buffer[256]; int team = ( rand() % 10000 ) + 5000; // ************* SPEAKER *************** sprintf( buffer, "t%i_1", team ); // trigger for speaker vec3_t triggerVoiceBtm; VectorCopy( min, triggerVoiceBtm ); triggerVoiceBtm[2] = max[2] - 16; DEntity* triggerVoice = m_Container.AddEntity( "trigger_multiple" ); GetBoundingCube( triggerVoiceBtm, max, "textures/common/trigger", triggerVoice ); triggerVoice->AddEPair( "target", buffer ); //-------------------- // target for speaker vec3_t voiceOrigin; VectorCopy( centre, voiceOrigin ); voiceOrigin[2] = max[2] + 16; DEntity* targetVoice = m_Container.AddEntity( "target_speaker" ); targetVoice->AddEPair( "targetname", buffer ); sprintf( buffer, "%f %f %f", voiceOrigin[0], voiceOrigin[1], voiceOrigin[2] ); targetVoice->AddEPair( "origin", buffer ); targetVoice->AddEPair( "spawnflags", "8" ); targetVoice->AddEPair( "noise", "*falling1.wav" ); //-------------------- // *********** END SPEAKER ************* // ********* POWERUP REMOVAL *********** sprintf( buffer, "t%i_2", team ); // trigger for powerup removal vec3_t triggerPwrRmvTop, triggerPwrRmvBtm; VectorCopy( min, triggerPwrRmvBtm ); VectorCopy( max, triggerPwrRmvTop ); triggerPwrRmvTop[2] = triggerVoiceBtm[2] - 64; triggerPwrRmvBtm[2] = triggerPwrRmvTop[2] - 16; DEntity* triggerPwrRmv = m_Container.AddEntity( "trigger_multiple" ); GetBoundingCube( triggerPwrRmvBtm, triggerPwrRmvTop, "textures/common/trigger", triggerPwrRmv ); triggerPwrRmv->AddEPair( "target", buffer ); //-------------------- // target for powerup removal vec3_t pwrRmvOrigin; VectorCopy( centre, pwrRmvOrigin ); pwrRmvOrigin[2] = triggerPwrRmvTop[2] + 16; DEntity* targetPwrRmv = m_Container.AddEntity( "target_remove_powerups" ); targetPwrRmv->AddEPair( "targetname", buffer ); sprintf( buffer, "%f %f %f", pwrRmvOrigin[0], pwrRmvOrigin[1], pwrRmvOrigin[2] ); targetPwrRmv->AddEPair( "origin", buffer ); //-------------------- // ****** END POWERUP REMOVAL ******** // ********* DAMAGE *********** // trigger for damage vec3_t triggerDmgTop, triggerDmgBtm; VectorCopy( min, triggerDmgBtm ); VectorCopy( max, triggerDmgTop ); triggerDmgBtm[2] = min[2] + 64; triggerDmgTop[2] = triggerDmgBtm[2] + 16; DEntity* triggerDmg = m_Container.AddEntity( "trigger_hurt" ); GetBoundingCube( triggerDmgBtm, triggerDmgTop, "textures/common/trigger", triggerDmg ); triggerDmg->AddEPair( "dmg", "9999" ); triggerDmg->AddEPair( "spawnflags", "12" ); //-------------------- // ****** END DAMAGE ******** // ********* NODROP *********** vec3_t nodropTop; VectorCopy( max, nodropTop ); nodropTop[2] = min[2] + 64; GetBoundingCube( min, nodropTop, "textures/common/nodrop" ); // ****** END NODROP ******** return true; }