#include "stdafx.h" #include "NaviMesh.h" #include "Ray.h" #include "NaviMeshNode.h" //#include "CameraManager.h" cNaviMesh* cNaviMesh::mSingleton = 0; cNaviMesh::cNaviMesh() : mCellCount( 0 ) , mLineCount( 0 ) , mMetersPerVertex( 0.0f ) , mUnitsPerMeter( 0 ) , mUnitsPerVertex( 0.0f ) , mUnitsPerLeafNode( 0.0f ) , mSegmentLength( 0.0f ) , mRootNode( 0 ) , mHeights( 0 ) , mLoadArray( 0 ) , mLoadCount( 0 ) , mLoadIndex( 0 ) { assert( mSingleton == 0 && "bad singleton!" ); mSingleton = this; } cNaviMesh::~cNaviMesh() { Clear(); mSingleton = 0; } void cNaviMesh::Clear() { delete mRootNode; mRootNode = 0; delete [] mHeights; mHeights = 0; mCellCount = 0; mLineCount = 0; mMetersPerVertex = 0.0f; mUnitsPerMeter = 0; mUnitsPerVertex = 0.0f; mUnitsPerLeafNode = 0.0f; mSegmentLength = 0.0f; mNodeArray.Clear(); /// ·Îµù ¹è¿­À» Á¦°Å delete [] mLoadArray; mLoadArray = 0; mLoadCount = 0; mLoadIndex = 0; } bool cNaviMesh::Pick( NiPoint3* pos, int mouseX, int mouseY ) { assert( pos ); assert( mRootNode ); NiPoint3 origin, dir; // CAMERAMAN->GetRayFromWindowPoint( &origin, &dir, mouseX, mouseY ); return Pick( pos, cRay(origin, dir) ); } bool cNaviMesh::Pick( NiPoint3* pos, const cRay& ray ) { float dist = NI_INFINITY; cNaviMeshNode::mRay = &ray; cNaviMeshNode::mMaxDistance = NI_INFINITY; cNaviMeshNode::mDistance = &dist; cNaviMeshNode::mContact = pos; return mRootNode->CollideRay(); } bool cNaviMesh::Pick( NiPoint3* pos, float* dist, const cRay& ray, float maxDistance ) { if( mRootNode ) { cNaviMeshNode::mRay = &ray; cNaviMeshNode::mMaxDistance = maxDistance; cNaviMeshNode::mDistance = dist; cNaviMeshNode::mContact = pos; return mRootNode->CollideRay(); } else { return false; } } bool cNaviMesh::CalcHeight( float* height, float x, float y ) const { assert( height ); /// ÇØ´ç À§Ä¡°¡ ÁöÇü ¾È¿¡ µé¾î¿À´ÂÁö °Ë»ç const cBox& box = mRootNode->GetBoundBox(); if( x < box.GetMin().x || y < box.GetMin().y || x > box.GetMax().x || y > box.GetMax().y ) { return false; } /// ±â¿ï±â¸¦ °Ë»ç int xi = (int)(x / 100.0f); int yi = (int)(y / 100.0f); float x0 = xi * 100.0f; float y0 = yi * 100.0f; float d = 1.0f; if( x != x0 ) { d = (y - y0) / (x - x0); assert( d >= 0.0f ); } if( d >= 1.0f ) { /// ¿ÞÂÊ À§ »ï°¢Çü NiPoint3 p0( x0, y0 + 100.0f, mHeights[(yi+1) * mLineCount + xi] ); NiPoint3 p1( x0 + 100.0f, y0 + 100.0f, mHeights[(yi+1) * mLineCount + xi+1] ); NiPoint3 p2( x0, y0, mHeights[yi * mLineCount + xi] ); *height = p0.z + ((p1.z - p0.z) / (p1.x - p0.x)) * (x - p0.x) + ((p2.z - p0.z) / (p0.y - p2.y)) * (p0.y - y); } else { /// ¿À¸¥ÂÊ ¾Æ·¡ »ï°¢Çü NiPoint3 p0( x0 + 100.0f, y0, mHeights[yi * mLineCount + xi+1] ); NiPoint3 p1( x0, y0, mHeights[yi * mLineCount + xi] ); NiPoint3 p2( x0 + 100.0f, y0 + 100.0f, mHeights[mLineCount * (yi+1) + xi+1] ); *height = p0.z + ((p1.z - p0.z) / (p0.x - p1.x)) * (p0.x - x) + ((p2.z - p0.z) / (p2.y - p0.y)) * (y - p0.y); } return true; } bool cNaviMesh::CheckCellCount( unsigned int cellCount ) { if( cellCount % NAVIMESH_DEFAULT_RESOLUTION != 0 ) { assert( 0 ); return false; } cNaviMeshLeafNode::mCellCount = NAVIMESH_LEAF_CELL_COUNT; cNaviMeshLeafNode::mLineCount = NAVIMESH_LEAF_LINE_COUNT; return true; } void cNaviMesh::SetLeafNode( unsigned int xi, unsigned int yi, cNaviMeshLeafNode* node ) { assert( node ); unsigned int nodeCount = mCellCount / cNaviMeshLeafNode::mCellCount; mNodeArray[yi * nodeCount + xi] = node; } const cBox& cNaviMesh::GetBoundBox() const { return mRootNode->GetBoundBox(); } cNaviMeshLeafNode* cNaviMesh::GetLeafNode( float x, float y ) const { /// ÇØ´ç À§Ä¡°¡ ÁöÇü ¾È¿¡ µé¾î¿À´ÂÁö °Ë»ç const cBox& box = mRootNode->GetBoundBox(); if( x < box.GetMin().x || y < box.GetMin().y || x > box.GetMax().x || y > box.GetMax().y ) { return 0; } /// ¹üÀ§ °è»ê int xi = (int)(x / mUnitsPerLeafNode); int yi = (int)(y / mUnitsPerLeafNode); int nodeCount = (int)(mCellCount / cNaviMeshLeafNode::mCellCount); if( xi < 0 ) xi = 0; if( yi < 0 ) yi = 0; if( xi > nodeCount - 1 ) xi = nodeCount - 1; if( yi > nodeCount - 1 ) yi = nodeCount - 1; return (cNaviMeshLeafNode*)mNodeArray[yi * nodeCount + xi]; }