Files
FC1/Editor/Brush/BrushPoly.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

252 lines
5.3 KiB
C++

////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: BrushPoly.cpp
// Version: v1.00
// Created: 8/7/2002 by Timur.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History: Based on Andrey's Indoor editor.
//
////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "BrushPoly.h"
#include "BrushPlane.h"
//////////////////////////////////////////////////////////////////////////
// SBrushPoly implementation.
//////////////////////////////////////////////////////////////////////////
#define POLY_DOT_EPSILON 0.001f
void SBrushPoly::ClipByPlane(SBrushPlane *p, float eps, SBrushPoly **front, SBrushPoly **back)
{
float dists[64];
int sides[64];
int counts[3];
float dot;
int i, j;
SBrushVert *p1, *p2;
Vec3d mid;
SBrushPoly *f, *b;
counts[0] = counts[1] = counts[2] = 0;
for (i=0; i<m_Pts.size(); i++)
{
dot = (m_Pts[i].xyz | p->normal) - p->dist;
dists[i] = dot;
if (dot > eps)
sides[i] = 0;
else
if (dot < -eps)
sides[i] = 1;
else
sides[i] = 2;
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
*front = *back = NULL;
if (!counts[0])
{
*back = this;
return;
}
if (!counts[1])
{
*front = this;
return;
}
*front = f = new SBrushPoly;
*back = b = new SBrushPoly;
// Reserve space for at least 4 points.
f->m_Pts.reserve(4);
b->m_Pts.reserve(4);
SBrushVert v;
for (i=0; i<m_Pts.size(); i++)
{
p1 = &m_Pts[i];
if (sides[i] == 2)
{
f->m_Pts.push_back(*p1);
b->m_Pts.push_back(*p1);
continue;
}
if (sides[i] == 0)
f->m_Pts.push_back(*p1);
if (sides[i] == 1)
b->m_Pts.push_back(*p1);
if (sides[i+1] == 2 || sides[i+1] == sides[i])
continue;
p2 = &m_Pts[(i+1)%m_Pts.size()];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0; j<3; j++)
{
if (p->normal[j] == 1)
mid[j] = p->dist;
else
if (p->normal[j] == -1)
mid[j] = -p->dist;
else
mid[j] = p1->xyz[j] + dot*(p2->xyz[j]-p1->xyz[j]);
}
v.xyz = mid;
f->m_Pts.push_back(v);
b->m_Pts.push_back(v);
}
}
//////////////////////////////////////////////////////////////////////////
SBrushPoly *SBrushPoly::ClipByPlane(SBrushPlane *split, bool keep)
{
float dists[64];
int sides[64];
int counts[3];
float dot;
int i, j;
SBrushVert *p1, *p2;
//SBrushPoly *newp;
counts[0] = counts[1] = counts[2] = 0;
for (i=0; i<m_Pts.size(); i++)
{
dot = (m_Pts[i].xyz | split->normal) - split->dist;
dists[i] = dot;
if (dot > POLY_DOT_EPSILON)
sides[i] = 0;
else
if (dot < -POLY_DOT_EPSILON)
sides[i] = 1;
else
sides[i] = 2;
counts[sides[i]]++;
}
sides[i] = sides[0];
dists[i] = dists[0];
if (keep && !counts[0] && !counts[1])
return this;
if (!counts[0])
{
delete this;
return NULL;
}
if (!counts[1])
return this;
//newp = new SBrushPoly;
SBrushVert v;
static std::vector<SBrushVert> newpoints;
newpoints.clear();
newpoints.reserve(16);
for (i=0; i<m_Pts.size(); i++)
{
p1 = &m_Pts[i];
if (sides[i] == 2)
{
//newp->m_Pts.push_back(*p1);
newpoints.push_back(*p1);
continue;
}
if (sides[i] == 0)
//newp->m_Pts.push_back(*p1);
newpoints.push_back(*p1);
if (sides[i+1] == 2 || sides[i+1] == sides[i])
continue;
p2 = &m_Pts[(i+1)%m_Pts.size()];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0; j<3 ; j++)
{
if (split->normal[j] == 1)
v.xyz[j] = (float)split->dist;
else
if (split->normal[j] == -1)
v.xyz[j] = -(float)split->dist;
else
v.xyz[j] = p1->xyz[j] + dot*(p2->xyz[j]-p1->xyz[j]);
}
for (j=0; j<2; j++)
{
if (split->normal[j] == 1)
v.st[j] = (float)split->dist;
else
if (split->normal[j] == -1)
v.st[j] = -(float)split->dist;
else
v.st[j] = p1->st[j] + dot*(p2->st[j]-p1->st[j]);
}
//newp->m_Pts.push_back(v);
newpoints.push_back(v);
}
m_Pts = newpoints;
//delete this;
//return newp;
return this;
}
//////////////////////////////////////////////////////////////////////////
void SBrushPoly::CalcBounds(Vec3d& mins, Vec3d& maxs)
{
mins=SetMaxBB();
maxs=SetMinBB();
for (int i=0; i<m_Pts.size(); i++)
{
AddToBounds(m_Pts[i].xyz, mins, maxs);
}
}
//////////////////////////////////////////////////////////////////////////
void SBrushPoly::MakePlane(SBrushPlane *pl)
{
Vec3d v1 = m_Pts[1].xyz - m_Pts[0].xyz;
Vec3d v2 = m_Pts[2].xyz - m_Pts[0].xyz;
pl->normal = v2 ^ v1;
pl->normal.Normalize();
pl->dist = m_Pts[0].xyz | pl->normal;
}
//////////////////////////////////////////////////////////////////////////
float SBrushPoly::Area()
{
int i;
Vec3d d1, d2, cross;
float total;
total = 0;
for (i=2; i<m_Pts.size(); i++)
{
d1 = m_Pts[i-1].xyz - m_Pts[0].xyz;
d2 = m_Pts[i].xyz - m_Pts[0].xyz;
cross = d1 ^ d2;
total += 0.5 * cross.Length();
}
return total;
}