Files
Client/Engine/Zalla3D Scene Class/RegionTrigger.cpp
LGram16 e067522598 Initial commit: ROW Client source code
Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 16:24:34 +09:00

1063 lines
21 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "RegionTrigger.h"
#include "BinTree.h"
#include <vector>
#include <set>
#include <assert.h>
#include <algorithm>
#include <fstream>
#include <math.h>
#include "GMMemory.h"
#ifdef _DEBUG
#define LOG_POLYGONTOLINE
#define LOG_PRINTTREE
#endif
TRIGGERLIST EmptyTriggerList;
//////////////////////////////SLineVector////////////////////////////////////
//
float SVector2::Magnitude() const
{
return (float)sqrt( ( x * x ) + ( y * y ) );
}
void SVector2::Normalize()
{
float magnitude = Magnitude();
x /= magnitude;
y /= magnitude;
}
//////////////////////////////SLineVector////////////////////////////////////
//
SLineVector::SLineVector()
: a( 0.0f ), b( 0.0f ), c( 0.0f )
{}
SLineVector::SLineVector( float A, float B, float C )
: a( A ), b( B ), c( C )
{
}
SLineVector::SLineVector( const LINE & line, bool bSwapPos )
{
SVector2 pt1 = line.first;
SVector2 pt2 = line.second;
if( bSwapPos )
{
pt1 = ( line.first.x <= line.second.x ? line.first : line.second );
pt2 = ( line.first.x <= line.second.x ? line.second : line.first );
}
a = pt1.y - pt2.y;
b = pt2.x - pt1.x;
c = pt1.x * pt2.y - pt2.x * pt1.y;
// float temp = a * line.first.x + b * line.first.y + c;
// assert( temp == 0 );
// temp = a * line.second.x + b * line.second.y + c;
// assert( temp == 0 );
}
ePos SLineVector::TestPoint( SVector2 pt, float Epsilon ) const
{
float r = a * pt.x + b * pt.y + c;
if( r > Epsilon )
return POS_FRONT;
if( r < -Epsilon )
return POS_BACK;
return POS_COPLANAR;
}
ePos SLineVector::TestLine( const LINE & line, float Epsilon ) const
{
ePos res1 = TestPoint( line.first, Epsilon );
ePos res2 = TestPoint( line.second, Epsilon );
if( res1 == POS_FRONT )
{
if( res2 == POS_BACK )
return POS_SPLIT;
else
return POS_FRONT;
}
else if( res1 == POS_BACK )
{
if( res2 == POS_FRONT )
return POS_SPLIT;
else
return POS_BACK;
}
else //coplanar
{
if( res2 == POS_FRONT )
return POS_FRONT;
else if( res2 == POS_BACK )
return POS_BACK;
else
return POS_COPLANAR;
}
}
SVector2 SLineVector::SplitPointOfLine( const LINE & l ) const
{
SLineVector line( l );
SVector2 pos;
pos.x = ( line.b * c - b * line.c ) / ( line.a * b - a * line.b );
pos.y = ( line.a * c - a * line.c ) / ( a * line.b - line.a * b );
int iPosX,iPosY;
iPosX = (int)pos.x;
iPosY = (int)pos.y;
pos.x = (float)iPosX;
pos.y = (float)iPosY;
// pos.x = (int)pos.x;
// pos.y = (int)pos.y;
return pos;
}
void SLineVector::SplitLine( const LINE & in, LINE & front, LINE & back, float Epsilon ) const
{
SVector2 pos = SplitPointOfLine( in );
front.first = ( TestPoint( in.first, Epsilon ) == POS_FRONT ? in.first : in.second );
front.second = pos;
back.first = pos;
back.second = ( TestPoint( in.second, Epsilon ) == POS_BACK ? in.second : in.first );
}
ePos SLineVector::TestPolygon( const POLYGON & polygon, float Epsilon ) const
{
bool allfront=true, allback=true;
for( int i=0; i < (int)polygon.size(); i++ )
{
ePos result = TestPoint( polygon[i], Epsilon );
if( result == POS_BACK )
allfront = false;
else if( result == POS_FRONT )
allback = false;
}
if( allfront && !allback )
{
return POS_FRONT;
}
else if( !allfront && allback )
{
return POS_BACK;
}
else if( !allfront && !allback )
{
return POS_SPLIT;
}
return POS_COPLANAR;
}
void SLineVector::Normalize()
{
float magnitude = (float)sqrt( ( a * a ) + ( b * b ) + ( c * c ) );
a /= magnitude;
b /= magnitude;
c /= magnitude;
}
bool SLineVector::SplitPolygon( const POLYGON & in, POLYGON & front, POLYGON & back, float Epsilon ) const
{
if( in.size() == 0 )
return false;
front.clear();
back.clear();
int thisIndex = in.size() - 1;
ePos thisRes = TestPoint( in[thisIndex], Epsilon );
ePos nextRes;
for( int nextIndex = 0; nextIndex < (int)in.size(); nextIndex++ )
{
nextRes = TestPoint( in[nextIndex], Epsilon );
if( thisRes == POS_FRONT )
{
front.push_back( in[thisIndex] );
}
if( thisRes == POS_BACK )
{
back.push_back( in[thisIndex] );
}
if( thisRes == POS_COPLANAR )
{
front.push_back( in[thisIndex] );
back.push_back( in[thisIndex] );
}
if( ( thisRes == POS_BACK && nextRes == POS_FRONT ) ||
( thisRes == POS_FRONT && nextRes == POS_BACK ) )
{
SVector2 splitPoint = SplitPointOfLine( LINE( in[thisIndex], in[nextIndex] ) );
front.push_back( splitPoint );
back.push_back( splitPoint );
}
thisIndex = nextIndex;
thisRes = nextRes;
}
if( front.size() >= 3 && back.size() >= 3 )
{
return true;
}
return false;
}
//////////////////////////CRegionTrigger::SNode/////////////////////////////////
//
CRegionTrigger::SNode::SNode()
: m_bNode( 0 ), m_pLine( NULL )
{
}
CRegionTrigger::SNode::SNode( const SNode & rhs )
: m_bNode( 0 ), m_pLine( NULL )
{
this->operator=( rhs );
}
CRegionTrigger::SNode & CRegionTrigger::SNode::operator=( const SNode & rhs )
{
Destroy();
m_bNode = rhs.m_bNode;
if( rhs.m_pTriggerID == NULL )
return *this;
if( m_bNode == 0 )
{
m_pTriggerID = new TRIGGERLIST( *rhs.m_pTriggerID );
}
else if( m_bNode == 1 )
{
m_pLineVector = new SLineVector( *rhs.m_pLineVector );
}
else
{
m_pLine = new LINE( *rhs.m_pLine );
}
return *this;
}
CRegionTrigger::SNode::~SNode()
{
Destroy();
}
void CRegionTrigger::SNode::Create( float a, float b, float c )
{
Destroy();
m_bNode = 1;
m_pLineVector = new SLineVector( a, b, c );
}
void CRegionTrigger::SNode::Create( const TRIGGERLIST & triggers )
{
Destroy();
m_bNode = 0;
m_pTriggerID = new TRIGGERLIST( triggers );
}
void CRegionTrigger::SNode::Create( const SVector2 a, const SVector2 b )
{
m_bNode = 2;
m_pLine = new LINE( a, b );
}
void CRegionTrigger::SNode::Create( const LINES & lines, CRegionTrigger & regionTrigger, int thisIndex, float Epsilon )
{
Destroy();
if( lines.size() == 0 )
return;
int bestIndex = BestSplitLine( lines, Epsilon );
if( bestIndex < 0 )
{
Create( TRIGGERLIST() );
return;
}
m_bNode = 2;
m_pLine = new LINE( lines[ bestIndex ] );
SLineVector lineVector( *m_pLine );
LINES frontList, backList;
for( int i = 0; i < (int)lines.size(); i++ )
{
if( i == bestIndex ) continue;
ePos res = lineVector.TestLine( lines[i], Epsilon );
switch( res )
{
case POS_FRONT:
frontList.push_back( lines[i] );
break;
case POS_BACK:
backList.push_back( lines[i] );
break;
case POS_SPLIT:
{
LINE front, back;
lineVector.SplitLine( lines[i], front, back, Epsilon );
frontList.push_back( front );
backList.push_back( back );
break;
}
case POS_COPLANAR:
break;
}
}
int leftIndex = LINETREE::LeftChild( thisIndex );
SNode & leftNode = regionTrigger.m_pLineTree->SetData( leftIndex );
if( frontList.size() )
{
leftNode.Create( frontList, regionTrigger, leftIndex, Epsilon );
}
else
{
leftNode.Create( TRIGGERLIST() );
}
int rightIndex = LINETREE::RightChild( thisIndex );
SNode & rightNode = regionTrigger.m_pLineTree->SetData( rightIndex );
if( backList.size() )
{
rightNode.Create( backList, regionTrigger, rightIndex, Epsilon );
}
else
{
rightNode.Create( TRIGGERLIST() );
}
}
void CRegionTrigger::SNode::Destroy()
{
if( m_bNode == 0 )
{
delete m_pTriggerID;
m_pTriggerID = NULL;
}
else if( m_bNode == 1 )
{
delete m_pLineVector;
m_pLineVector = NULL;
}
else
{
delete [] m_pLine;
m_pLine = NULL;
}
}
void CRegionTrigger::SNode::ToLineVector()
{
if( m_bNode == 2 )
{
SLineVector * pLineVector = new SLineVector( *m_pLine );
delete [] m_pLine;
m_pLineVector = pLineVector;
m_bNode = 1;
}
}
//////////////////////////////////////////////////////////////////////////////
//
#ifdef LOG_PRINTTREE
ofstream tree_file;
void PrintToFile( const char * szMsg )
{
if( tree_file.is_open() )
tree_file << szMsg;
}
#endif
/////////////////////////////CRegionTrigger////////////////////////////////////
//
CRegionTrigger::CRegionTrigger()
: m_pLineTree( new LINETREE )
, m_fEpsilon( 0.01f )
{
}
CRegionTrigger::~CRegionTrigger()
{
Destroy();
delete m_pLineTree;
}
void CRegionTrigger::Create( const TRIGGERREGIONS & regions, float epsilon )
{
Destroy();
m_fEpsilon = epsilon;
LINES lines;
RegionsToLines( regions, lines );
m_pLineTree->Create();
SNode & node = m_pLineTree->SetData( m_pLineTree->Root() );
node.Create( lines, *this, m_pLineTree->Root(), m_fEpsilon );
AssignTrigger( regions );
#ifdef LOG_PRINTTREE
tree_file.open( "TriggerTree.txt" );
Print( PrintToFile );
tree_file.close();
#endif
}
void CRegionTrigger::Create( FILE * fp )
{
Destroy();
m_pLineTree->Create( fp, LoadNode );
}
void CRegionTrigger::Destroy()
{
m_pLineTree->Destroy();
}
void CRegionTrigger::Save( FILE * fp )
{
m_pLineTree->Save( fp, SaveNode );
}
unsigned CRegionTrigger::ChildIndex( SLineVector & splitLine, SVector2 pos, unsigned index )
{
ePos relativePos = splitLine.TestPoint( pos, m_fEpsilon );
if( relativePos == POS_FRONT )
return LINETREE::LeftChild( index );
else if( relativePos == POS_BACK )
return LINETREE::RightChild( index );
else
{
//Coplanar<61><72> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ٿ<EFBFBD><D9BF><EFBFBD> <20>ٽ<EFBFBD> <20>õ<EFBFBD>
relativePos = splitLine.TestPoint( pos, m_fEpsilon/100.0f );
if( relativePos == POS_FRONT )
return LINETREE::LeftChild( index );
else
return LINETREE::RightChild( index );
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>(pos)<29><> <20>ش<EFBFBD><D8B4>Ǵ<EFBFBD> <20><>(leaf)<29><> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
unsigned CRegionTrigger::GetLeaf( SVector2 pos )
{
unsigned index = 1;
while( index < m_pLineTree->Size() && !m_pLineTree->IsLeaf( index ) )
{
const SNode & node = m_pLineTree->GetData( index );
if( node.m_bNode == 1 )
{
index = ChildIndex( *node.m_pLineVector, pos, index );
}
else if( node.m_bNode == 2 )
{
SLineVector splitLine( *node.m_pLine );
index = ChildIndex( splitLine, pos, index );
}
else
{
//1<><31> 2 <20>̿<EFBFBD><CCBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>ȿ
return 0xffffffff;
}
}
return index;
}
const TRIGGERLIST & CRegionTrigger::CheckTrigger( SVector2 pos )
{
unsigned index = GetLeaf( pos );
if( !m_pLineTree->IsValid( index ) )
return EmptyTriggerList;
const SNode & node = m_pLineTree->GetData( index );
return *node.m_pTriggerID;
}
void CRegionTrigger::Print( PRINTFUNC printFunc )
{
if( m_pLineTree->IsEmpty() )
return;
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȸ<EFBFBD><C8B8> <20>ϸ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
for( LINETREE::iterator_preorder i = m_pLineTree->Begin_preorder(); i != m_pLineTree->End_preorder(); i++ )
{
char szBuffer[1024];
sprintf( szBuffer, "<%d> ", i.GetIndex() );
printFunc( szBuffer );
if( i->m_bNode == 0 )
{
if( i->m_pTriggerID )
{
TRIGGERLIST & tList = *(i->m_pTriggerID);
if( tList.size() >= 1 )
{
sprintf( szBuffer, ", %d", tList[0] );
printFunc( szBuffer );
}
for( int i = 1; i < (int)tList.size(); i++ )
{
sprintf( szBuffer, ", %d", tList[i] );
printFunc( szBuffer );
}
printFunc( "\n" );
}
}
else if( i->m_bNode == 1 )
{
sprintf( szBuffer, "%fx + %fy + %f = 0\n", i->m_pLineVector->a, i->m_pLineVector->b, i->m_pLineVector->c );
printFunc( szBuffer );
}
else if( i->m_bNode == 2 )
{
float x = i->m_pLine->first.x;
float y = i->m_pLine->first.y;
float x2 = i->m_pLine->second.x;
float y2 = i->m_pLine->second.y;
sprintf( szBuffer, "( %f, %f ) - ( %f, %f )\n", x, y, x2, y2 );
printFunc( szBuffer );
}
else
{
assert( false );
}
}
}
int CRegionTrigger::BestSplitLine( const LINES & lines, float Epsilon )
{
int maxCheck = (int)( lines.size() * 0.1f );
if( maxCheck == 0 ) maxCheck = 1;
int bestSplits = 100000;
int bestIndex = -1;
for( int i = 0; i < maxCheck; i++ )
{
SLineVector currLine( lines[i] );
int currSplits = 0;
for( int i2 = 0; i2 < (int)lines.size(); i2++ )
{
if( i == i2 ) continue;
ePos res = currLine.TestLine( lines[i2], Epsilon );
if( res == POS_SPLIT )
currSplits++;
}
if( currSplits < bestSplits )
{
bestSplits = currSplits;
bestIndex = i;
}
}
return bestIndex;
}
#ifdef LOG_POLYGONTOLINE
void PrintOneLine( ofstream & file, SVector2 pt1, SVector2 pt2 )
{
file << pt1.x << ", " << pt1.y << " --- " << pt2.x << ", " << pt2.y << endl;
}
#endif
void CRegionTrigger::RegionsToLines( const TRIGGERREGIONS & regions, LINES & line )
{
//-------<2D><><EFBFBD><EFBFBD>ȭ<EFBFBD><C8AD>(log) <20>ۼ<EFBFBD>--------//
#ifdef LOG_POLYGONTOLINE
ofstream file( "log_lines.txt" );
if( !file.is_open() )
return;
#endif
//---------------------------------//
for( unsigned i = 0; i < regions.size(); i++ )
{
const POLYGON & polygon = regions[i].second;
if( polygon.size() >= 2 )
{
#ifdef LOG_POLYGONTOLINE
PrintOneLine( file, polygon[0], polygon[1] );
#endif
line.push_back( LINE( polygon[0], polygon[1] ) );
for( unsigned n = 2; n < polygon.size(); n++ )
{
#ifdef LOG_POLYGONTOLINE
PrintOneLine( file, polygon[n-2], polygon[n] );
#endif
line.push_back( LINE( polygon[n-2], polygon[n] ) );
}
#ifdef LOG_POLYGONTOLINE
PrintOneLine( file, polygon[polygon.size()-2], polygon[polygon.size()-1] );
#endif
line.push_back( LINE( polygon[polygon.size()-2], polygon[polygon.size()-1] ) );
}
}
/*
for( int i = 0; i < regions.size(); i++ )
{
const POLYGON & polygon = regions[i].second;
SVector2 thisPoint = polygon[ polygon.size() - 1 ];
for( int i2 = 0; i2 < polygon.size(); i2++ )
{
SVector2 nextPoint = polygon[i2];
line.push_back( LINE( thisPoint, nextPoint ) );
#ifdef LOG_POLYGONTOLINE
file << thisPoint.x << ", " << thisPoint.y << " --- " << nextPoint.x << ", " << nextPoint.y << endl;
#endif
thisPoint = nextPoint;
}
}
*/
}
void CRegionTrigger::AssignTrigger( const TRIGGERREGIONS & regions )
{
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ε<EFBFBD><CEB5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>´<EFBFBD>.
/* vector<unsigned> leafs;
unsigned size = m_pLineTree->Size();
for( unsigned i = 0; i < size; i++ )
{
if( m_pLineTree->IsValid( i ) && m_pLineTree->IsLeaf( i ) )
{
leafs.push_back( i );
}
}
vector<SVector2> KeyPos;
for( i = 0; i < leafs.size(); i++ )
{
unsigned parent = LINETREE::Parent( leafs[i] );
if( m_pLineTree->IsValid( parent ) )
{
const SNode & node = m_pLineTree->GetData( parent );
if( node.m_bNode == 2 )
{
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ϰ<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><20>̵<EFBFBD><CCB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD>
//<2F><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ʈ<><C6AE><EFBFBD>Ÿ<EFBFBD> <20>Ҵ<EFBFBD><D2B4>Ѵ<EFBFBD>.
SVector2 & pt1 = node.m_pLine->first;
SVector2 & pt2 = node.m_pLine->second;
SVector2 ptCenter( ( pt1.x + pt2.x ) / 2, ( pt1.y + pt2.y ) / 2 );
SLineVector lineVec( *node.m_pLine );
SVector2 dirVec( lineVec.a, lineVec.b );
dirVec.Normalize();
//i<><69> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ڽ<EFBFBD><DABD>̾<EFBFBD><CCBE><EFBFBD> <20><><EFBFBD>
if( LINETREE::LeftChild( parent ) != leafs[i] )
{
//-a, -b<><62><EFBFBD><EFBFBD>
KeyPos.push_back( SVector2( ptCenter.x - dirVec.x, ptCenter.y - dirVec.y ) );
}
else //i<><69> <20><><EFBFBD><EFBFBD> <20>ڽ<EFBFBD><DABD>̾<EFBFBD><CCBE><EFBFBD> <20><><EFBFBD>
{
//a, b<><62><EFBFBD><EFBFBD>
KeyPos.push_back( SVector2( ptCenter.x + dirVec.x, ptCenter.y + dirVec.y ) );
}
}
}
}
for( i = 0; i < KeyPos.size(); i++ )
{
const TRIGGERLIST & trigger = GetTrigger( KeyPos[i], regions );
AssignTrigger( KeyPos[i], trigger );
}
*/
TRIGGERREGIONS tempRegions;
SplitToTriangle( regions, tempRegions );
TRIGGERREGIONS SplittedRegions = SplitTriggerRegions( tempRegions, 1 );
for( unsigned i = 0; i < SplittedRegions.size(); i++ )
{
SVector2 ptCenter = CenterPoint( SplittedRegions[i].second );
const TRIGGERLIST & triggers = SplittedRegions[i].first;
unsigned index = GetLeaf( ptCenter );
if( m_pLineTree->IsValid( index ) )
{
SNode & node = m_pLineTree->SetData( index );
TRIGGERLIST & tList = *node.m_pTriggerID;
for( unsigned i2 = 0; i2 < triggers.size(); i2++ )
{
if( tList.end() == find( tList.begin(), tList.end(), triggers[i2] ) )
node.m_pTriggerID->push_back( triggers[i2] );
}
}
}
}
const TRIGGERLIST & CRegionTrigger::GetTrigger( SVector2 vecPos, const TRIGGERREGIONS & regions )
{
static TRIGGERLIST triggerList;
for( unsigned i = 0; i < regions.size(); i++ )
{
const POLYGON & poly = regions[i].second;
SVector2 pt1;
bool in = true;
if( !poly.empty() )
pt1 = poly[ poly.size() - 1 ];
for( unsigned j = 0; j < poly.size(); j++ )
{
SVector2 pt2 = poly[j];
SLineVector lineVec( LINE( pt1, pt2 ), false );
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>𼭸<EFBFBD><F0BCADB8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20>ϳ<EFBFBD><CFB3><EFBFBD><EFBFBD><EFBFBD> <20>ۿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ۿ<EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD>
if( lineVec.TestPoint( vecPos, m_fEpsilon ) == POS_BACK )
{
in = false;
break;
}
pt1 = pt2;
}
if( in )
{
//<2F><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ȿ<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ʈ<><C6AE><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD> triggerList<73><74> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
for( unsigned k = 0; k < regions[i].first.size(); k++ )
{
triggerList.push_back( regions[i].first[k] );
}
}
}
return triggerList;
}
void CRegionTrigger::AssignTrigger( SVector2 vecPos, const TRIGGERLIST & trigger )
{
unsigned index = GetLeaf( vecPos );
if( m_pLineTree->IsValid( index ) )
{
SNode & node = m_pLineTree->SetData( index );
TRIGGERLIST & tList = *node.m_pTriggerID;
for( unsigned i = 0; i < trigger.size(); i++ )
{
if( tList.end() == find( tList.begin(), tList.end(), trigger[i] ) )
node.m_pTriggerID->push_back( trigger[i] );
}
}
}
SVector2 CRegionTrigger::CenterPoint( const POLYGON & polygon )
{
double xTotal = 0.0, yTotal = 0.0;
for( unsigned i = 0; i < polygon.size(); i++ )
{
xTotal += polygon[i].x;
yTotal += polygon[i].y;
}
return SVector2( (float)(xTotal / polygon.size()), (float)(yTotal / polygon.size()) );
}
void CRegionTrigger::MergeRegions( TRIGGERREGIONS & out, const TRIGGERREGIONS & in )
{
for( int i = 0; i < (int)in.size(); i++ )
{
out.push_back( in[i] );
}
}
void CRegionTrigger::SplitToTriangle( const TRIGGERREGIONS & regions, TRIGGERREGIONS & out )
{
for( unsigned i = 0; i < regions.size(); i++ )
{
const POLYGON & poly = regions[i].second;
for( unsigned n = 0; n < poly.size() - 2; n++ )
{
out.push_back( TRIGGERREGION() );
TRIGGERREGION & t = out.back();
t.first = regions[i].first;
if( ( n + 1 ) % 2 ) //n + 1<><31> Ȧ<><C8A6><EFBFBD><EFBFBD> <20><>
{
SVector2 temp = poly[n];
t.second.push_back( temp );
temp = poly[n+1];
t.second.push_back( temp );
temp = poly[n+2];
t.second.push_back( temp );
}
else
{
SVector2 temp = poly[n+1];
t.second.push_back( temp );
temp = poly[n];
t.second.push_back( temp );
temp = poly[n+2];
t.second.push_back( temp );
}
}
}
}
TRIGGERREGIONS CRegionTrigger::SplitTriggerRegions( const TRIGGERREGIONS & regions, unsigned splitIndex )
{
if( regions.size() == 0 )
return regions;
if( !m_pLineTree->IsValid( splitIndex ) || m_pLineTree->IsLeaf( splitIndex ) )
return regions;
SNode & tempNode = m_pLineTree->SetData( splitIndex );
//tempNode.ToLineVector();
//const SLineVector & splitLine = *tempNode.m_pLineVector;
SLineVector splitLine( *tempNode.m_pLine );
TRIGGERREGIONS frontList, backList;
for( int i = 0; i < (int)regions.size(); i++ )
{
ePos res = splitLine.TestPolygon( regions[i].second, m_fEpsilon );
switch( res )
{
case POS_FRONT:
frontList.push_back( regions[i] );
break;
case POS_BACK:
backList.push_back( regions[i] );
break;
case POS_SPLIT:
{
POLYGON front, back;
splitLine.SplitPolygon( regions[i].second, front, back, m_fEpsilon );
frontList.push_back( TRIGGERREGION( regions[i].first, front ) );
backList.push_back( TRIGGERREGION( regions[i].first, back ) );
break;
}
case POS_COPLANAR: //<2F><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>.
break;
}
}
TRIGGERREGIONS result1 = SplitTriggerRegions( frontList, LINETREE::LeftChild( splitIndex ) );
TRIGGERREGIONS result2 = SplitTriggerRegions( backList, LINETREE::RightChild( splitIndex ) );
MergeRegions( result1, result2 );
return result1;
}
void CRegionTrigger::SaveNode( FILE * fp, const SNode & node )
{
if( node.m_pLine == 0 )
{
//<2F><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ǥ<>÷<EFBFBD> 3<><33> <20><><EFBFBD><EFBFBD>
byte b = 3;
fwrite( &b, sizeof( byte ), 1, fp );
}
else
{
fwrite( &node.m_bNode, sizeof( byte ), 1, fp );
if( node.m_bNode == 0 )
{
unsigned nTrigger = node.m_pTriggerID->size();
fwrite( &nTrigger, sizeof( unsigned ), 1, fp );
for( unsigned i = 0; i < nTrigger; i++ )
{
fwrite( &node.m_pTriggerID->at( i ), sizeof( int ), 1, fp );
}
}
else if( node.m_bNode == 1 )
{
fwrite( &node.m_pLineVector->a, sizeof( float ), 1, fp );
fwrite( &node.m_pLineVector->b, sizeof( float ), 1, fp );
fwrite( &node.m_pLineVector->c, sizeof( float ), 1, fp );
}
else if( node.m_bNode == 2 )
{
fwrite( &node.m_pLine->first, sizeof( SVector2 ), 1, fp );
fwrite( &node.m_pLine->second, sizeof( SVector2 ), 1, fp );
}
else
{
assert( false );
}
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>׸<EFBFBD> <20><><EFBFBD><EFBFBD> ǥ<><C7A5>
char temp = '#';
fwrite( &temp, 1, 1, fp );
}
void CRegionTrigger::LoadNode( FILE * fp, SNode & node )
{
node.Destroy();
byte bNode;
int vectorsize = sizeof( LINE );
fread( &bNode, sizeof( byte ), 1, fp );
if( bNode == 0 )
{
unsigned nTrigger = 0;
fread( &nTrigger, sizeof( unsigned ), 1, fp );
TRIGGERLIST tlist;
for( unsigned i = 0; i < nTrigger; i++ )
{
int t;
fread( &t, sizeof( int ), 1, fp );
tlist.push_back( t );
}
node.Create( tlist );
}
else if( bNode == 1 )
{
float a, b, c;
fread( &a, sizeof( float ), 1, fp );
fread( &b, sizeof( float ), 1, fp );
fread( &c, sizeof( float ), 1, fp );
node.Create( a, b, c );
}
else if( bNode == 2 )
{
SVector2 a, b;
fread( &a, sizeof( SVector2 ), 1, fp );
fread( &b, sizeof( SVector2 ), 1, fp );
node.Create( a, b );
}
else if( bNode == 3 )
{
}
else
{
assert( false );
}
char c;
fread( &c, 1, 1, fp );
assert( c == '#' );
}
/////////////////////////////////////////////////////////////////////////////