mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-08 01:39:36 +00:00
1
This commit is contained in:
@@ -0,0 +1,657 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "OPTGeneral.h"
|
||||
#include "Options.h"
|
||||
#include "hammer_mathlib.h"
|
||||
#include "MapFace.h"
|
||||
#include "MapGroup.h"
|
||||
#include "MapSolid.h"
|
||||
#include "hammer.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Create a segment using two polygons and a start and end position in
|
||||
// those polygons.
|
||||
// Input : fZMin -
|
||||
// fZMax -
|
||||
// fOuterPoints -
|
||||
// fInnerPoints -
|
||||
// iStart -
|
||||
// iEnd -
|
||||
// bCreateSouthFace -
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
static CMapSolid *CreateSegment(float fZMin, float fZMax, float fOuterPoints[][2], float fInnerPoints[][2], int iStart, int iEnd, BOOL bCreateSouthFace)
|
||||
{
|
||||
CMapFace Face;
|
||||
Vector points[4]; // all sides have four vertices
|
||||
|
||||
CMapSolid *pSolid = new CMapSolid;
|
||||
|
||||
int iNorthSouthPoints = 3 + (bCreateSouthFace ? 1 : 0);
|
||||
|
||||
// create top face
|
||||
points[0][0] = fOuterPoints[iStart][0];
|
||||
points[0][1] = fOuterPoints[iStart][1];
|
||||
points[0][2] = fZMin;
|
||||
|
||||
points[1][0] = fOuterPoints[iEnd][0];
|
||||
points[1][1] = fOuterPoints[iEnd][1];
|
||||
points[1][2] = fZMin;
|
||||
|
||||
points[2][0] = fInnerPoints[iEnd][0];
|
||||
points[2][1] = fInnerPoints[iEnd][1];
|
||||
points[2][2] = fZMin;
|
||||
|
||||
points[3][0] = fInnerPoints[iStart][0];
|
||||
points[3][1] = fInnerPoints[iStart][1];
|
||||
points[3][2] = fZMin;
|
||||
|
||||
Face.CreateFace(points, iNorthSouthPoints);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// bottom face - set other z value and reverse order
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
points[i][2] = fZMax;
|
||||
}
|
||||
|
||||
Face.CreateFace(points, -iNorthSouthPoints);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// left side
|
||||
points[0][0] = fOuterPoints[iStart][0];
|
||||
points[0][1] = fOuterPoints[iStart][1];
|
||||
points[0][2] = fZMax;
|
||||
|
||||
points[1][0] = fOuterPoints[iStart][0];
|
||||
points[1][1] = fOuterPoints[iStart][1];
|
||||
points[1][2] = fZMin;
|
||||
|
||||
points[2][0] = fInnerPoints[iStart][0];
|
||||
points[2][1] = fInnerPoints[iStart][1];
|
||||
points[2][2] = fZMin;
|
||||
|
||||
points[3][0] = fInnerPoints[iStart][0];
|
||||
points[3][1] = fInnerPoints[iStart][1];
|
||||
points[3][2] = fZMax;
|
||||
|
||||
Face.CreateFace(points, 4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// right side
|
||||
points[0][0] = fOuterPoints[iEnd][0];
|
||||
points[0][1] = fOuterPoints[iEnd][1];
|
||||
points[0][2] = fZMin;
|
||||
|
||||
points[1][0] = fOuterPoints[iEnd][0];
|
||||
points[1][1] = fOuterPoints[iEnd][1];
|
||||
points[1][2] = fZMax;
|
||||
|
||||
points[2][0] = fInnerPoints[iEnd][0];
|
||||
points[2][1] = fInnerPoints[iEnd][1];
|
||||
points[2][2] = fZMax;
|
||||
|
||||
points[3][0] = fInnerPoints[iEnd][0];
|
||||
points[3][1] = fInnerPoints[iEnd][1];
|
||||
points[3][2] = fZMin;
|
||||
|
||||
Face.CreateFace(points, 4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// north face
|
||||
points[0][0] = fOuterPoints[iEnd][0];
|
||||
points[0][1] = fOuterPoints[iEnd][1];
|
||||
points[0][2] = fZMin;
|
||||
|
||||
points[1][0] = fOuterPoints[iStart][0];
|
||||
points[1][1] = fOuterPoints[iStart][1];
|
||||
points[1][2] = fZMin;
|
||||
|
||||
points[2][0] = fOuterPoints[iStart][0];
|
||||
points[2][1] = fOuterPoints[iStart][1];
|
||||
points[2][2] = fZMax;
|
||||
|
||||
points[3][0] = fOuterPoints[iEnd][0];
|
||||
points[3][1] = fOuterPoints[iEnd][1];
|
||||
points[3][2] = fZMax;
|
||||
|
||||
Face.CreateFace(points, 4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// south face
|
||||
if (bCreateSouthFace)
|
||||
{
|
||||
points[0][0] = fInnerPoints[iStart][0];
|
||||
points[0][1] = fInnerPoints[iStart][1];
|
||||
points[0][2] = fZMin;
|
||||
|
||||
points[1][0] = fInnerPoints[iEnd][0];
|
||||
points[1][1] = fInnerPoints[iEnd][1];
|
||||
points[1][2] = fZMin;
|
||||
|
||||
points[2][0] = fInnerPoints[iEnd][0];
|
||||
points[2][1] = fInnerPoints[iEnd][1];
|
||||
points[2][2] = fZMax;
|
||||
|
||||
points[3][0] = fInnerPoints[iStart][0];
|
||||
points[3][1] = fInnerPoints[iStart][1];
|
||||
points[3][2] = fZMax;
|
||||
|
||||
Face.CreateFace(points, 4);
|
||||
pSolid->AddFace(&Face);
|
||||
}
|
||||
|
||||
pSolid->InitializeTextureAxes(Options.GetTextureAlignment(), INIT_TEXTURE_ALL | INIT_TEXTURE_FORCE);
|
||||
|
||||
return(pSolid);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Create a segment using two polygons and a start and end position in
|
||||
// those polygons.
|
||||
// Input : fZMin -
|
||||
// fZMax -
|
||||
// fOuterPoints -
|
||||
// fInnerPoints -
|
||||
// iStart -
|
||||
// iEnd -
|
||||
// bCreateSouthFace -
|
||||
// Output :
|
||||
//-----------------------------------------------------------------------------
|
||||
static CMapSolid *CreateSegment(float fStartOuterPoints[][3], float fStartInnerPoints[][3],
|
||||
float fEndOuterPoints[][3], float fEndInnerPoints[][3],
|
||||
int iStart, int iEnd, BOOL bCreateSouthFace)
|
||||
{
|
||||
CMapFace Face;
|
||||
Vector points[4]; // all sides have four vertices
|
||||
|
||||
CMapSolid *pSolid = new CMapSolid;
|
||||
|
||||
// create top face
|
||||
points[0][0] = fStartOuterPoints[iStart][0];
|
||||
points[0][1] = fStartOuterPoints[iStart][1];
|
||||
points[0][2] = fStartOuterPoints[iStart][2];
|
||||
|
||||
points[1][0] = fStartOuterPoints[iEnd][0];
|
||||
points[1][1] = fStartOuterPoints[iEnd][1];
|
||||
points[1][2] = fStartOuterPoints[iEnd][2];
|
||||
|
||||
points[2][0] = fStartInnerPoints[iEnd][0];
|
||||
points[2][1] = fStartInnerPoints[iEnd][1];
|
||||
points[2][2] = fStartInnerPoints[iEnd][2];
|
||||
|
||||
points[3][0] = fStartInnerPoints[iStart][0];
|
||||
points[3][1] = fStartInnerPoints[iStart][1];
|
||||
points[3][2] = fStartInnerPoints[iStart][2];
|
||||
|
||||
Face.CreateFace(points, -4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// bottom face - set other z value and reverse order
|
||||
points[0][0] = fEndOuterPoints[iStart][0];
|
||||
points[0][1] = fEndOuterPoints[iStart][1];
|
||||
points[0][2] = fEndOuterPoints[iStart][2];
|
||||
|
||||
points[1][0] = fEndOuterPoints[iEnd][0];
|
||||
points[1][1] = fEndOuterPoints[iEnd][1];
|
||||
points[1][2] = fEndOuterPoints[iEnd][2];
|
||||
|
||||
points[2][0] = fEndInnerPoints[iEnd][0];
|
||||
points[2][1] = fEndInnerPoints[iEnd][1];
|
||||
points[2][2] = fEndInnerPoints[iEnd][2];
|
||||
|
||||
points[3][0] = fEndInnerPoints[iStart][0];
|
||||
points[3][1] = fEndInnerPoints[iStart][1];
|
||||
points[3][2] = fEndInnerPoints[iStart][2];
|
||||
|
||||
Face.CreateFace(points, 4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// left side
|
||||
points[0][0] = fEndOuterPoints[iStart][0];
|
||||
points[0][1] = fEndOuterPoints[iStart][1];
|
||||
points[0][2] = fEndOuterPoints[iStart][2];
|
||||
|
||||
points[1][0] = fStartOuterPoints[iStart][0];
|
||||
points[1][1] = fStartOuterPoints[iStart][1];
|
||||
points[1][2] = fStartOuterPoints[iStart][2];
|
||||
|
||||
points[2][0] = fStartInnerPoints[iStart][0];
|
||||
points[2][1] = fStartInnerPoints[iStart][1];
|
||||
points[2][2] = fStartInnerPoints[iStart][2];
|
||||
|
||||
points[3][0] = fEndInnerPoints[iStart][0];
|
||||
points[3][1] = fEndInnerPoints[iStart][1];
|
||||
points[3][2] = fEndInnerPoints[iStart][2];
|
||||
|
||||
Face.CreateFace(points, -4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// right side
|
||||
points[0][0] = fStartOuterPoints[iEnd][0];
|
||||
points[0][1] = fStartOuterPoints[iEnd][1];
|
||||
points[0][2] = fStartOuterPoints[iEnd][2];
|
||||
|
||||
points[1][0] = fEndOuterPoints[iEnd][0];
|
||||
points[1][1] = fEndOuterPoints[iEnd][1];
|
||||
points[1][2] = fEndOuterPoints[iEnd][2];
|
||||
|
||||
points[2][0] = fEndInnerPoints[iEnd][0];
|
||||
points[2][1] = fEndInnerPoints[iEnd][1];
|
||||
points[2][2] = fEndInnerPoints[iEnd][2];
|
||||
|
||||
points[3][0] = fStartInnerPoints[iEnd][0];
|
||||
points[3][1] = fStartInnerPoints[iEnd][1];
|
||||
points[3][2] = fStartInnerPoints[iEnd][2];
|
||||
|
||||
Face.CreateFace(points, -4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// north face
|
||||
points[0][0] = fStartOuterPoints[iEnd][0];
|
||||
points[0][1] = fStartOuterPoints[iEnd][1];
|
||||
points[0][2] = fStartOuterPoints[iEnd][2];
|
||||
|
||||
points[1][0] = fStartOuterPoints[iStart][0];
|
||||
points[1][1] = fStartOuterPoints[iStart][1];
|
||||
points[1][2] = fStartOuterPoints[iStart][2];
|
||||
|
||||
points[2][0] = fEndOuterPoints[iStart][0];
|
||||
points[2][1] = fEndOuterPoints[iStart][1];
|
||||
points[2][2] = fEndOuterPoints[iStart][2];
|
||||
|
||||
points[3][0] = fEndOuterPoints[iEnd][0];
|
||||
points[3][1] = fEndOuterPoints[iEnd][1];
|
||||
points[3][2] = fEndOuterPoints[iEnd][2];
|
||||
|
||||
Face.CreateFace(points, -4);
|
||||
pSolid->AddFace(&Face);
|
||||
|
||||
// south face
|
||||
if (bCreateSouthFace)
|
||||
{
|
||||
points[0][0] = fStartInnerPoints[iStart][0];
|
||||
points[0][1] = fStartInnerPoints[iStart][1];
|
||||
points[0][2] = fStartInnerPoints[iStart][2];
|
||||
|
||||
points[1][0] = fStartInnerPoints[iEnd][0];
|
||||
points[1][1] = fStartInnerPoints[iEnd][1];
|
||||
points[1][2] = fStartInnerPoints[iEnd][2];
|
||||
|
||||
points[2][0] = fEndInnerPoints[iEnd][0];
|
||||
points[2][1] = fEndInnerPoints[iEnd][1];
|
||||
points[2][2] = fEndInnerPoints[iEnd][2];
|
||||
|
||||
points[3][0] = fEndInnerPoints[iStart][0];
|
||||
points[3][1] = fEndInnerPoints[iStart][1];
|
||||
points[3][2] = fEndInnerPoints[iStart][2];
|
||||
|
||||
Face.CreateFace(points, -4);
|
||||
pSolid->AddFace(&Face);
|
||||
}
|
||||
|
||||
pSolid->InitializeTextureAxes(Options.GetTextureAlignment(), INIT_TEXTURE_ALL | INIT_TEXTURE_FORCE);
|
||||
|
||||
return(pSolid);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Make a 2d arc
|
||||
//-----------------------------------------------------------------------------
|
||||
void MakeArcCenterRadius(float xCenter, float yCenter, float xrad, float yrad, int npoints, float start_ang, float fArc, float points[][2])
|
||||
{
|
||||
int point;
|
||||
float angle = start_ang;
|
||||
float angle_delta;
|
||||
|
||||
angle_delta = fArc / (float)npoints;
|
||||
|
||||
// Add an additional points if we are not doing a full circle
|
||||
if (fArc != 360.0)
|
||||
{
|
||||
++npoints;
|
||||
}
|
||||
|
||||
for( point = 0; point < npoints; point++ )
|
||||
{
|
||||
if ( angle > 360 )
|
||||
{
|
||||
angle -= 360;
|
||||
}
|
||||
|
||||
points[point][0] = V_rint(xCenter + (float)cos(DEG2RAD(angle)) * xrad);
|
||||
points[point][1] = V_rint(yCenter + (float)sin(DEG2RAD(angle)) * yrad);
|
||||
|
||||
angle += angle_delta;
|
||||
}
|
||||
|
||||
// Full circle, recopy the first point as the closing point.
|
||||
if (fArc == 360.0)
|
||||
{
|
||||
points[point][0] = points[0][0];
|
||||
points[point][1] = points[0][1];
|
||||
}
|
||||
}
|
||||
|
||||
void MakeArc(float x1, float y1, float x2, float y2, int npoints, float start_ang, float fArc, float points[][2])
|
||||
{
|
||||
float xrad = (x2 - x1) / 2.0f;
|
||||
float yrad = (y2 - y1) / 2.0f;
|
||||
|
||||
// make centerpoint for polygon:
|
||||
float xCenter = x1 + xrad;
|
||||
float yCenter = y1 + yrad;
|
||||
|
||||
MakeArcCenterRadius( xCenter, yCenter, xrad, yrad, npoints, start_ang, fArc, points );
|
||||
}
|
||||
|
||||
#define ARC_MAX_POINTS 4096
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pBox -
|
||||
// fStartAngle -
|
||||
// iSides -
|
||||
// fArc -
|
||||
// iWallWidth -
|
||||
// iAddHeight -
|
||||
// bPreview -
|
||||
// Output : Returns a group containing the arch solids.
|
||||
//-----------------------------------------------------------------------------
|
||||
CMapClass *CreateArch(BoundBox *pBox, float fStartAngle, int iSides, float fArc, int iWallWidth, int iAddHeight, BOOL bPreview)
|
||||
{
|
||||
float fOuterPoints[ARC_MAX_POINTS][2];
|
||||
float fInnerPoints[ARC_MAX_POINTS][2];
|
||||
|
||||
//
|
||||
// create outer points
|
||||
//
|
||||
MakeArc(pBox->bmins[AXIS_X], pBox->bmins[AXIS_Y],
|
||||
pBox->bmaxs[AXIS_X], pBox->bmaxs[AXIS_Y], iSides,
|
||||
fStartAngle, fArc, fOuterPoints);
|
||||
|
||||
//
|
||||
// create inner points
|
||||
//
|
||||
MakeArc(pBox->bmins[AXIS_X] + iWallWidth,
|
||||
pBox->bmins[AXIS_Y] + iWallWidth,
|
||||
pBox->bmaxs[AXIS_X] - iWallWidth,
|
||||
pBox->bmaxs[AXIS_Y] - iWallWidth, iSides,
|
||||
fStartAngle, fArc, fInnerPoints);
|
||||
|
||||
|
||||
//
|
||||
// check wall width - if it's half or more of the total,
|
||||
// set the inner poinst to the center point of the box
|
||||
// and turn off the CreateSouthFace flag
|
||||
//
|
||||
BOOL bCreateSouthFace = TRUE;
|
||||
Vector Center;
|
||||
pBox->GetBoundsCenter(Center);
|
||||
if((iWallWidth*2+8) >= (pBox->bmaxs[AXIS_X] - pBox->bmins[AXIS_X]) ||
|
||||
(iWallWidth*2+8) >= (pBox->bmaxs[AXIS_Y] - pBox->bmins[AXIS_Y]))
|
||||
{
|
||||
for(int i = 0; i < ARC_MAX_POINTS; i++)
|
||||
{
|
||||
fInnerPoints[i][AXIS_X] = Center[AXIS_X];
|
||||
fInnerPoints[i][AXIS_Y] = Center[AXIS_Y];
|
||||
}
|
||||
bCreateSouthFace = FALSE;
|
||||
}
|
||||
|
||||
// create group for segments
|
||||
CMapGroup *pGroup = new CMapGroup;
|
||||
|
||||
Vector MoveAccum( 0.f, 0.f, 0.f );
|
||||
|
||||
float fMinZ, fMaxZ;
|
||||
|
||||
fMinZ = pBox->bmins[2];
|
||||
fMaxZ = pBox->bmaxs[2];
|
||||
|
||||
if ((fMaxZ - fMinZ) < 1.0f)
|
||||
fMaxZ = fMinZ + 1.0f;
|
||||
|
||||
for (int i = 0; i < iSides; i++)
|
||||
{
|
||||
int iNextPoint = i+1;
|
||||
if (iNextPoint >= iSides + 1)
|
||||
iNextPoint = 0;
|
||||
|
||||
CMapSolid *pSolid = CreateSegment(
|
||||
fMinZ, fMaxZ,
|
||||
fOuterPoints, fInnerPoints,
|
||||
i, iNextPoint, bCreateSouthFace);
|
||||
|
||||
pGroup->AddChild(pSolid);
|
||||
|
||||
if (iAddHeight && i) // don't move first segment
|
||||
{
|
||||
MoveAccum[2] += iAddHeight;
|
||||
pSolid->TransMove(MoveAccum);
|
||||
}
|
||||
}
|
||||
|
||||
pGroup->CalcBounds(TRUE);
|
||||
if (Options.general.bStretchArches)
|
||||
{
|
||||
// make sure size of group's bounds are size of original bounds -
|
||||
// if not, scale up. this can happen when we use rotation.
|
||||
Vector objsize, boundsize;
|
||||
pBox->GetBoundsSize(boundsize);
|
||||
pGroup->GetBoundsSize(objsize);
|
||||
|
||||
if (boundsize[AXIS_X] > objsize[AXIS_X] ||
|
||||
boundsize[AXIS_Y] > objsize[AXIS_Y])
|
||||
{
|
||||
Vector scale;
|
||||
scale[AXIS_X] = boundsize[AXIS_X] / objsize[AXIS_X];
|
||||
scale[AXIS_Y] = boundsize[AXIS_Y] / objsize[AXIS_Y];
|
||||
scale[AXIS_Z] = 1.0f; // xxxYWB scaling by 0 causes veneers, so I changed to 1.0
|
||||
Vector center;
|
||||
pBox->GetBoundsCenter(center);
|
||||
pGroup->TransScale(center, scale);
|
||||
}
|
||||
}
|
||||
|
||||
return pGroup;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : pBox -
|
||||
// fStartAngle -
|
||||
// iSides -
|
||||
// fArc -
|
||||
// iWallWidth -
|
||||
// iAddHeight -
|
||||
// bPreview -
|
||||
// Output : Returns a group containing the arch solids.
|
||||
//-----------------------------------------------------------------------------
|
||||
typedef float TorusPointList_t[ARC_MAX_POINTS][3];
|
||||
|
||||
CMapClass *CreateTorus(BoundBox *pBox, float fStartAngle, int iSides, float fArc, int iWallWidth, float flCrossSectionalRadius,
|
||||
float fRotationStartAngle, int iRotationSides, float fRotationArc, int iAddHeight, BOOL bPreview)
|
||||
{
|
||||
float xCenter = (pBox->bmaxs[AXIS_X] + pBox->bmins[AXIS_X]) * 0.5f;
|
||||
float yCenter = (pBox->bmaxs[AXIS_Y] + pBox->bmins[AXIS_Y]) * 0.5f;
|
||||
float xRad = (pBox->bmaxs[AXIS_X] - xCenter);
|
||||
float yRad = (pBox->bmaxs[AXIS_Y] - yCenter);
|
||||
if (xRad < 0.0f )
|
||||
{
|
||||
xRad = 0.0f;
|
||||
}
|
||||
|
||||
if (yRad < 0.0f )
|
||||
{
|
||||
yRad = 0.0f;
|
||||
}
|
||||
|
||||
if ( flCrossSectionalRadius > (xRad * 0.5f) )
|
||||
{
|
||||
flCrossSectionalRadius = (xRad * 0.5f);
|
||||
}
|
||||
if ( flCrossSectionalRadius > (yRad * 0.5f) )
|
||||
{
|
||||
flCrossSectionalRadius = (yRad * 0.5f);
|
||||
}
|
||||
|
||||
if ( iWallWidth < flCrossSectionalRadius )
|
||||
{
|
||||
flCrossSectionalRadius -= iWallWidth;
|
||||
}
|
||||
else
|
||||
{
|
||||
iWallWidth = flCrossSectionalRadius;
|
||||
flCrossSectionalRadius = 0.0f;
|
||||
}
|
||||
|
||||
float flCrossSectionHalfWidth = flCrossSectionalRadius + iWallWidth;
|
||||
xRad -= flCrossSectionHalfWidth;
|
||||
yRad -= flCrossSectionHalfWidth;
|
||||
|
||||
float fOuterPoints[ARC_MAX_POINTS][2];
|
||||
float fInnerPoints[ARC_MAX_POINTS][2];
|
||||
|
||||
// create outer points (unrotated)
|
||||
MakeArcCenterRadius(0.0f, 0.0f,
|
||||
flCrossSectionalRadius + iWallWidth, flCrossSectionalRadius + iWallWidth,
|
||||
iSides, fStartAngle, fArc, fOuterPoints);
|
||||
|
||||
BOOL bCreateSouthFace = TRUE;
|
||||
if ( flCrossSectionalRadius != 0.0f )
|
||||
{
|
||||
// create inner points (unrotated)
|
||||
MakeArcCenterRadius(0.0f, 0.0f, flCrossSectionalRadius, flCrossSectionalRadius,
|
||||
iSides, fStartAngle, fArc, fInnerPoints);
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < iSides; i++)
|
||||
{
|
||||
fInnerPoints[i][0] = fInnerPoints[i][1] = 0.0f;
|
||||
}
|
||||
bCreateSouthFace = FALSE;
|
||||
}
|
||||
|
||||
// create group for segments
|
||||
CMapGroup *pGroup = new CMapGroup;
|
||||
|
||||
TorusPointList_t innerPoints[2];
|
||||
TorusPointList_t outerPoints[2];
|
||||
TorusPointList_t *pStartInnerPoints;
|
||||
TorusPointList_t *pStartOuterPoints;
|
||||
TorusPointList_t *pEndInnerPoints = &innerPoints[1];
|
||||
TorusPointList_t *pEndOuterPoints = &outerPoints[1];
|
||||
int nCurrIndex = 0;
|
||||
|
||||
float flCurrentZ = pBox->bmins[AXIS_Z] + iWallWidth + flCrossSectionalRadius;
|
||||
float flDeltaZ = (float)iAddHeight / (float)(iRotationSides);
|
||||
|
||||
float flRotationAngle = fRotationStartAngle;
|
||||
float flRotationDeltaAngle = fRotationArc / iRotationSides;
|
||||
|
||||
bool bIsCircle = ( iAddHeight == 0.0f ) && ( fRotationArc == 360.0f );
|
||||
++iRotationSides;
|
||||
for ( int i = 0; i != iRotationSides; ++i )
|
||||
{
|
||||
// This eliminates a seam in circular toruses
|
||||
if ( bIsCircle && (i == iRotationSides - 1) )
|
||||
{
|
||||
flRotationAngle = fRotationStartAngle;
|
||||
}
|
||||
|
||||
float xCurrCenter, yCurrCenter;
|
||||
|
||||
float flCosAngle = cos( DEG2RAD(flRotationAngle) );
|
||||
float flSinAngle = sin( DEG2RAD(flRotationAngle) );
|
||||
xCurrCenter = xCenter + xRad * flCosAngle;
|
||||
yCurrCenter = yCenter + yRad * flSinAngle;
|
||||
|
||||
// Update buffers
|
||||
pStartInnerPoints = pEndInnerPoints;
|
||||
pStartOuterPoints = pEndOuterPoints;
|
||||
pEndInnerPoints = &innerPoints[nCurrIndex];
|
||||
pEndOuterPoints = &outerPoints[nCurrIndex];
|
||||
nCurrIndex = 1 - nCurrIndex;
|
||||
|
||||
// Transform points into actual space.
|
||||
int jPrevPoint = -1;
|
||||
int j = 0;
|
||||
do
|
||||
{
|
||||
// x original is transformed into x/y based on rotation
|
||||
// y original is transformed into z
|
||||
(*pEndInnerPoints)[j][0] = xCurrCenter + fInnerPoints[j][0] * flCosAngle;
|
||||
(*pEndInnerPoints)[j][1] = yCurrCenter + fInnerPoints[j][0] * flSinAngle;
|
||||
(*pEndInnerPoints)[j][2] = flCurrentZ + fInnerPoints[j][1];
|
||||
|
||||
(*pEndOuterPoints)[j][0] = xCurrCenter + fOuterPoints[j][0] * flCosAngle;
|
||||
(*pEndOuterPoints)[j][1] = yCurrCenter + fOuterPoints[j][0] * flSinAngle;
|
||||
(*pEndOuterPoints)[j][2] = flCurrentZ + fOuterPoints[j][1];
|
||||
|
||||
// We'll use the j == 0 data when iNextPoint = iSides - 1
|
||||
if (( i != 0 ) && ( jPrevPoint != -1 ))
|
||||
{
|
||||
CMapSolid *pSolid = CreateSegment(
|
||||
*pStartOuterPoints, *pStartInnerPoints,
|
||||
*pEndOuterPoints, *pEndInnerPoints,
|
||||
jPrevPoint, j, bCreateSouthFace);
|
||||
|
||||
pGroup->AddChild(pSolid);
|
||||
}
|
||||
|
||||
jPrevPoint = j;
|
||||
++j;
|
||||
} while( jPrevPoint != iSides );
|
||||
|
||||
flRotationAngle += flRotationDeltaAngle;
|
||||
flCurrentZ += flDeltaZ;
|
||||
|
||||
if ( flRotationAngle >= 360.0f )
|
||||
{
|
||||
flRotationAngle -= 360.0f;
|
||||
}
|
||||
}
|
||||
|
||||
pGroup->CalcBounds(TRUE);
|
||||
|
||||
if (Options.general.bStretchArches)
|
||||
{
|
||||
// make sure size of group's bounds are size of original bounds -
|
||||
// if not, scale up. this can happen when we use rotation.
|
||||
Vector objsize, boundsize;
|
||||
pBox->GetBoundsSize(boundsize);
|
||||
pGroup->GetBoundsSize(objsize);
|
||||
|
||||
if (boundsize[AXIS_X] > objsize[AXIS_X] ||
|
||||
boundsize[AXIS_Y] > objsize[AXIS_Y])
|
||||
{
|
||||
Vector scale;
|
||||
scale[AXIS_X] = boundsize[AXIS_X] / objsize[AXIS_X];
|
||||
scale[AXIS_Y] = boundsize[AXIS_Y] / objsize[AXIS_Y];
|
||||
scale[AXIS_Z] = 1.0f; // xxxYWB scaling by 0 causes veneers, so I changed to 1.0
|
||||
Vector center;
|
||||
pBox->GetBoundsCenter(center);
|
||||
pGroup->TransScale(center, scale);
|
||||
}
|
||||
}
|
||||
|
||||
return pGroup;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user