- °³¿ä
- µ¥ÀÌÅÍ »ý¼º
- ºÐÇÒ
- º´ÇÕ
- ÀÎÁ¢ ³ëµå °è»ê
- ÇÊ¿ä¾ø´Â ³ëµå Á¦°ÅÇϱâ
- Æ÷Å» »ý¼ºÇϱâ
- °á°ú¹°
- Àå/´ÜÁ¡
- ÀåÁ¡
- ´ÜÁ¡
- ¸µÅ©
1 °³¿ä
Space Filling VolumeÀº °Ë»ö °ø°£À» Ç¥ÇöÇÏ´Â ÇϳªÀÇ ¹æ¹ýÀÌ´Ù. À§ÀÇ ±×¸²Ã³·³ °ø°£À» ÀÓÀÇÀÇ Å©±â ¹Ú½º·Î ä¿ì°í, ÀÌ ¹Ú½ºµéÀ» ÀÏÁ¾ÀÇ ³ëµå·Î¼ ±æÃ£±â µî¿¡ Ȱ¿ëÇÏ´Â °ÍÀÌ´Ù. NavigationMesh¸¸Å À¶Å뼺ÀÌ ÀÖÁö´Â ¾ÊÀ¸³ª, »ý¼º ¹× ÀÌ¿ëÀÌ ½±´Ù.
2 µ¥ÀÌÅÍ »ý¼º
ÀÏ´Ü 3D ȯ°æÀ» ±â¹ÝÀ¸·Î ÇÑ´Ù. Áï Æ¯Á¤ ¸Þ½¬¸¦ ÀԷ¹޾Æ, Space Filling VolumeÀ» »ý¼ºÇÏ´Â °ÍÀÌ ¸ñÇ¥´Ù.
»ý¼º ¹æ¹ý¿¡´Â 2°¡Áö ¹æ¹ýÀÌ ÀÖ´Ù. ù¹øÂ°´Â °ø°£ÀÇ ÀÓÀÇ ÁöÁ¡¿¡´Ù Å¥ºê¸¦ ¶³¾î¶ß¸®°í, ±× Å¥ºêÀÇ Å©±â¸¦ Ãæµ¹ÀÌ ÀϾ´Â ¹üÀ§±îÁö ´Ã·Á°¡´Â ¹æ¹ýÀÌ´Ù. µÎ¹øÂ°´Â °ø°£À» ÀÏÁ¤ Å©±âÀÇ ±×¸®µå·Î Âɰµ ÈÄ, Ãæµ¹ÀÌ ÀϾÁö ¾Ê´Â ±×¸®µåµéÀ» º´ÇÕÇÏ´Â ¹æ¹ýÀÌ´Ù. ù¹øÂ° ¹æ¹ýÀº ÀÓÀÇÀÇ ÁöÁ¡À» °í¸£´Â °Ô ¾Ö¸ÅÇØ¼, µÎ¹øÂ° ¹æ¹ýÀ» ¼±ÅÃÇß´Ù.
2.1 ºÐÇÒ
- ¸ÕÀú ÀԷ¹ÞÀº ¸Þ½¬¸¦ °¨½Ò ¼ö ÀÖ´Â AABB¸¦ ±¸ÇÑ´Ù.
- Á¤ÇØÁø Å©±â ´ÜÀ§·Î AABB¸¦ Âɰµ´Ù.
- ÀÌ Å©±â°¡ ÀÛÀ¸¸é ÀÛÀ»¼ö·Ï ¿ø·¡ ¸Þ½¬¿¡ Á» ´õ °¡±î¿î Space Filling VolumeÀÌ »ý¼ºµÇÁö¸¸, ´ë½Å »ý¼º °úÁ¤¿¡ µé¾î°¡´Â ¸Þ¸ð¸®°¡ 3Á¦°öÀ¸·Î ´Ã¾î³ª°Ô µÈ´Ù. ÀÌ ¶§¹®¿¡ ³Ê¹« Ä¿´Ù¶õ ¸Þ½¬(Æú¸®°ï ¼ö¿Í´Â »ó°ü¾øÀÌ ´Ü¼øÈ÷ Å«...)¸¦ ó¸®ÇÒ ¶§¿¡´Â ¸Þ¸ð¸® ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù.
- ÀÌ Âɰµ À°¸éüµéÀ» ¼¿À̶ó ºÎ¸£°Ú´Ù.
- ¸Þ½¬¸¦ ±¸¼ºÇÏ´Â ¸ðµç »ï°¢Çüµé°ú ¼¿µé°£ÀÇ Ãæµ¹ üũ(Triangle vs AABB)¸¦ ¼öÇàÇÑ´Ù.
- »ï°¢Çü°ú Ãæµ¹ °¡´É¼ºÀÌ ÀÖ´Â ¼¿µé, Áï »ï°¢ÇüÀ» °¨½Î´Â AABB ¾È¿¡ µé¾î°¡´Â ¼¿µé¸¸ Ãæµ¹ üũÇÏ´Â °ÍÀº ±âº»À̶ó°í ÇÒ ¼ö ÀÖ°Ú´Ù.
- Ãæµ¹ üũ¸¦ ¼öÇàÇÏ°í ³ª¸é, °¥ ¼ö ÀÖ´Â ¼¿°ú °¥ ¼ö ¾ø´Â ¼¿ÀÌ ºÐ¸®µÈ´Ù.
2.2 º´ÇÕ
º´ÇÕÀº ¹¹¶ö±î, ¸»·Î ¼³¸íÇϱ⿡´Â ¾à°£ º¹ÀâÇÑ °ü°è·Î ½´µµ ÄÚµå·Î º¸´Â °ÍÀÌ ÀÌÇØ°¡ ºü¸¦ °ÍÀÌ´Ù.
enum
{
EXPAND_LEFT,
EXPAND_RIGHT,
EXPAND_FORWARD,
EXPAND_BACKWARD,
EXPAND_UP,
EXPAND_DOWN,
EXPAND_MAX
};
struct REGION
{
int x0, y0, z0; ///< ¿µ¿ª ÃÖ¼Ò ÁÂÇ¥
int x1, y1, z1; ///< ¿µ¿ª ÃÖ´ë ÁÂÇ¥
};
bool GetLargestEmptyRegion(int x, int y, int z, int size, REGION& result)
{
// ¿µ¿ªÀ» ¼³Á¤ÇÑ´Ù.
result = { x, y, z, x + size, y + size, z + size };
// ¸ÕÀú ÇØ´ç ¿µ¿ªÀÌ ¸ðµÎ ºñ¾îÀÖ´ÂÁö üũÇÑ´Ù.
if (IsEmpty(result)) return false;
REGION test, current;
int failed = 0;
// °¢ ¹æÇâÀ» µû¶ó ·çÇÁ¸¦ µ¹¸é¼ Å¥ºêÀÇ Å©±â¸¦ ´Ã¸± ¼ö ÀÖ´ÂÁö üũÇÑ´Ù.
while (failed < EXPAND_MAX) {
for (int dir=0; dir<EXPAND_MAX; ++dir) {
// ÀÌÀüÀÇ °á°ú°ª º¹»ç
current = result;
// Å×½ºÆ® ¿µ¿ª °è»ê
// ÇöÀçÀÇ ¹æÇâ¿¡ µû¶ó Å×½ºÆ®°¡ ÇÊ¿äÇÑ ¿µ¿ªÀÌ Á¤ÇØÁø´Ù.
test = current.GetTestRegion(dir);
if (IsEmpty(test)) {
// ÇØ´ç ¿µ¿ªÀÌ ºñ¾îÀÖ´Â °æ¿ì¿¡´Â °á°ú ¿µ¿ªÀ» È®ÀåÇϰí,
// fail Ä«¿îÆ®¸¦ ÃʱâÈÇÑ´Ù.
failed = 0;
result = current + test;
}
else {
failed++;
}
}
}
// ¿©±â±îÁö ¿Ô´Ù¸é ÃÖ¼ÒÇÑ Á¦ÀÏ Ã³À½ ÁÖ¾îÁø ¿µ¿ª¸¸ÅÀº ºñ¾îÀÖ´Ù´Â ¸»ÀÌ´Ù.
return true;
}
void Merge()
{
// ¸ÊÀÇ Ãà Áß¿¡ °¡Àå ÀÛÀº ÃàÀ» ±âÁØÀ¸·Î ½ÃÀÛÇÑ´Ù.
int MaxSize = min(MapWidth, MapHeight, MapDepth);
// ÃÖ´ë Å©±â¸¦ ÁÙ¿©³ª°¡¸ç ¸ðµÎ Å×½ºÆ®ÇÑ´Ù.
for (int size=MaxSize; size > 0; size--) {
for (int x=0; x+size < MapWidth; ++x) {
for (int y=0; y+size < MapHeight; ++y) {
for (int z=0; z+size < MapDepth; ++z) {
REGION r;
// ÇöÀç ¿µ¿ªÀ» Æ÷ÇÔÇÏ´Â °¡Àå Å« ¿µ¿ªÀ» °è»êÇÑ´Ù.
if (!GetLargestEmptyRegion(x, y, z, size, r))
continue;
// ¿µ¿ª¿¡ Æ÷ÇÔµÈ Å¥ºêµéÀ» »ç¿ëµÈ °ÍÀ¸·Î Ç¥½ÃÇÑ´Ù.
// »ç¿ëµÈ °ÍÀ¸·Î Æ÷ÇÔµÈ Å¥ºêµéÀº IsEmpty() == false°¡ µÈ´Ù.
SetUsed(r, true);
// Area °´Ã¼¸¦ »ý¼ºÇؼ Ä÷º¼Ç¿¡´Ù Ãß°¡ÇÑ´Ù.
collection.Add(r, ...);
}
}
}
}
} ÀÌ·¸°Ô ÇÏ¸é º´ÇÕµÈ À°¸éüµéÀ» ¾ò¾î³¾ ¼ö ÀÖ´Ù. ÀÌ À°¸éüµéÀ» ³ëµå¶ó°í ºÎ¸£°Ú´Ù.
2.3 ÀÎÁ¢ ³ëµå °è»ê
³ëµå¸¸À¸·Î´Â ¾ÆÁ÷ ±×·¡ÇÁ ÇüÅÂÀÇ µ¥ÀÌÅͰ¡ ¾Æ´Ï±â ¶§¹®¿¡, ±æÃ£±â¿¡ ½á¸ÔÀ¸·Á¸é, ¾î´À ³ëµå¿¡ ¾î´À ³ëµå°¡ ºÙ¾îÀÖ´ÂÁö¸¦ ¾Ë¾Æ³»¾ßÇÑ´Ù. ÀÌ´Â °£´ÜÇÑ Ãæµ¹Ã¼Å©(AABB vs AABB)¸¦ ÅëÇØ ¾Ë¾Æ³¾ ¼ö ÀÖ´Ù.
for a in all_nodes
for b in all_nodes
if collide(a, b)
set a, b as neighbor
2.4 ÇÊ¿ä¾ø´Â ³ëµå Á¦°ÅÇϱâ
¸ðµç ³ëµå°¡ ÇÊ¿äÇÑ °ÍÀº ¾Æ´Ï´Ù. °¥ ¼ö ¾ø´Â ³ëµåµéÀ» Ãß·Á³¿À¸·Î¼ Á» ´õ ÀûÀº µ¥ÀÌÅ͸¦ ¸¸µé¾î³¾ ¼ö ÀÖ´Ù. ´Ù¸¸ ¾î¶² ³ëµå°¡ ÇÊ¿ä¾ø´Â°¡´Â ¾ÖÇø®ÄÉÀ̼Ǹ¶´Ù Ʋ¸®´Ù. ¿¹¸¦ µé¾îº¸ÀÚ¸é...
- ÀÌ¿ô ³ëµå°¡ Çϳªµµ ¾ø´Â ³ëµå °°Àº °æ¿ì, ÇØ´ç ³ëµå·Î °¥ ¹æ¹ýÀÌ ¾øÀ¸¹Ç·Î ÇÊ¿ä¾ø´Ù.
- Y ÃàÀ» Á¦¿ÜÇϰí, XZ Æò¸é »óÀ¸·Î ºÃÀ» ¶§ ¿ÏÀüÈ÷ ´Ù¸¥ ³ëµå¿¡ Æ÷ÇԵǴ ³ëµåÀÇ °æ¿ì, °ÔÀÓ »ó¿¡¼ ³¯¾Æ´Ù´Ï´Â °ÍÀÌ ºÒ°¡´ÉÇÏ´Ù¸é ÇÊ¿ä¾ø´Ù.
2.5 Æ÷Å» »ý¼ºÇϱâ
ÀÌ¿ô ³ëµå±îÁö °è»êÀ» ¸¶ÃÆÀ¸¹Ç·Î ±×·¡ÇÁ ÇüÅÂÀÇ µ¥ÀÌÅͰ¡ ¸¸µé¾îÁ³À¸³ª, ¾ÆÁ÷ À̸¦ PathFinding¿¡ ¹Ù·Î ÀÌ¿ëÇÒ ¼ö´Â ¾ø´Ù. ³ëµå¿Í ³ëµå°¡ À̾îÁö´Â ºÎºÐ¿¡ Æ÷Å»À» »ý¼ºÇؾß, °ÔÀÓ ¾È¿¡¼ º®°ú Ãæµ¹ÇÏÁö ¾Ê´Â ¿òÁ÷ÀÓÀ» ¸¸µé¾î³¾ ¼ö ÀÖ´Ù. ³ëµå°¡ À°¸éüÀ̱⠶§¹®¿¡ °£´ÜÈ÷ Æ÷Å»À» °è»êÇÒ ¼ö ÀÖ´Ù. µÎ ³ëµå min, max °ªÀ» ´õÇØ¼ 2·Î ³ª´©¸é ¶¯ÀÌ´Ù.
const D3DXVECTOR3* bmin1 = pLHS->GetAABBMinimum();
const D3DXVECTOR3* bmax1 = pLHS->GetAABBMaximum();
const D3DXVECTOR3* bmin2 = pRHS->GetAABBMinimum();
const D3DXVECTOR3* bmax2 = pRHS->GetAABBMaximum();
D3DXVECTOR3 pos(
(std::max(bmin1->x, bmin2->x) + std::min(bmax1->x, bmax2->x)) * 0.5f,
(std::max(bmin1->y, bmin2->y) + std::min(bmax1->y, bmax2->y)) * 0.5f,
(std::max(bmin1->z, bmin2->z) + std::min(bmax1->z, bmax2->z)) * 0.5f
); ÀÌ Æ÷Å»µéÀ» ((from+,to),portal)ÀÇ Çü½ÄÀ¸·Î ¾îµò°¡¿¡ ÀúÀåÇØµÎ¸é °£´ÜÈ÷ ÀÌ¿ëÇÒ ¼ö ÀÖ´Ù.
2.6 °á°ú¹°
Original Mesh
Generated Volumes
3 Àå/´ÜÁ¡
ÀÏ´Ü ¾ÖÃÊÀÇ ¸ñÀûÀÌ MMORPG ¼¹ö¿ëÀ̾ú´Ù. Ŭ¶óÀÌ¾ðÆ®¿¡¼ »ç¿ëÇϱ⿡´Â ÀåÁ¡º¸´Ù´Â ´ÜÁ¡ÀÌ ¸¹À» °ÍÀÌ´Ù.
3.1 ÀåÁ¡
- ±¸ÇöÀÌ ½±´Ù.
- ¸Þ¸ð¸®°¡ Àû°Ô µé¾î°£´Ù.
- ¹¹ ¶Ç ¾ø³ª... -_-;;
3.2 ´ÜÁ¡
´ÜÁ¡Àº ÁÖ·Î ±âº» ´ÜÀ§°¡ »ç°¢Çü/À°¸éüÀ̱⠶§¹®¿¡ ¹ß»ýÇÑ´Ù.
- °î¸é ¶Ç´Â XYZÃà°ú ¾î±ß³ Æò¸éÀÌ ¸¹Àº ÁöÇüÀ» ó¸®ÇÏ±â ¾î·Æ´Ù. (»ó´çÈ÷ Ä¡¸íÀûÀÎ ´ÜÁ¡ÀÌ´Ù.)
- ½ÇÁ¦ ¿òÁ÷ÀÓÀ» ȸ鿡 ±×¸± ¶§´Â º¸Á¤À» ¸¹ÀÌ ÇØÁà¾ßÇÑ´Ù.
- ´«À¸·Î º¸±â¿¡´Â °¥ ¼ö ÀÖ´Â °÷Àε¥µµ ºÒ±¸Çϰí, °¡Áö ¸øÇÏ´Â °æ¿ì°¡ »ý±æ ¼ö ÀÖ´Ù. (¸Ç À§ÀÇ ±×¸²¿¡ º¸¸é ¿À¸¥ÂÊ ±¸¼®¿¡ º¸ÀÏ °ÍÀÌ´Ù.)
- µ¿ÀûÀÎ ÁöÇüÀ» ó¸®ÇÏ±â ¾î·Æ´Ù.
4 ¸µÅ©
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)