// path finding app by Michael Morton // // GPL // // feel free to clean up the code and send me back a copy : ) #include "resource.h" #include "math.h" #include #include using namespace std; #include "d3dx.h" #pragma comment(lib,"d3dx.lib") // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[]="title"; // The title bar text TCHAR szWindowClass[]="classname"; // The title bar tex /********************************************************** * * GLOBAL FUNCTIONS * ***********************************************************/ /* GetTriPoint * * returns a point in the direction a tri faces. * * * new point * * p1 * /\ * / \ * p2 p3 */ D3DXVECTOR3 GetTriPoint(const D3DXVECTOR3 &p1,const D3DXVECTOR3 &p2,const D3DXVECTOR3 &p3) { D3DXVECTOR3 p2p1,p3p1; D3DXVECTOR3 sum; //vector from p2 to p1 p2p1 = p1-p2; D3DXVec3Normalize(&sum,&p2p1); p2p1 = sum; //vector from p3 to p1 p3p1 = p1-p3; D3DXVec3Normalize(&sum,&p3p1); p3p1 = sum; //add the vectors together to produce new vector D3DXVECTOR3 temp; temp=p2p1+p3p1; //normalize the vector to reduce the length to 1 unit D3DXVec3Normalize(&sum,&temp); // scale the vector... no good if its < 1. : ) sum*=5; //add the new vector to p1 (offset it) sum+=p1; return sum; } /************************************************************************************************** Desc: Taken from comp.graphics.algorithms FAQ **************************************************************************************************/ bool IntersectionOfTwoLines(const D3DXVECTOR3 &a,const D3DXVECTOR3 &b,const D3DXVECTOR3 &c, const D3DXVECTOR3 &d, D3DXVECTOR3 &result) { double r,s; double denominator=(b.x-a.x)*(d.y-c.y)-(b.y-a.y)*(d.x-c.x); // If the denominator in above is zero, AB & CD are colinear if (denominator==0) return FALSE; double numeratorR=(a.y-c.y)*(d.x-c.x)-(a.x-c.x)*(d.y-c.y); // If the numerator above is also zero, AB & CD are collinear. // If they are collinear, then the segments may be projected to the x- // or y-axis, and overlap of the projected intervals checked. r=numeratorR/denominator; double numeratorS=(a.y-c.y)*(b.x-a.x)-(a.x-c.x)*(b.y-a.y); s=numeratorS/denominator; // If 0<=r<=1 & 0<=s<=1, intersection exists // r<0 or r>1 or s<0 or s>1 line segments do not intersect if (r<0 || r>1 || s<0 || s>1) return FALSE; /* Note: If the intersection point of the 2 lines are needed (lines in this context mean infinite lines) regardless whether the two line segments intersect, then If r>1, P is located on extension of AB If r<0, P is located on extension of BA If s>1, P is located on extension of CD If s<0, P is located on extension of DC */ // Find intersection point result.x=a.x+(r*(b.x-a.x)); result.y=a.y+(r*(b.y-a.y)); return TRUE; } //get red wingdi pen HANDLE GetRedPen() { static HANDLE redPen=NULL; if(redPen==NULL) { LOGPEN lp; POINT p; p.x=1; p.y=1; lp.lopnColor=RGB(255,0,0); lp.lopnStyle=0; lp.lopnWidth=p; redPen = CreatePenIndirect(&lp); } return redPen; } //get black wingdi pen HANDLE GetBlackPen() { return GetStockObject(BLACK_PEN); } //returns distance between 2 points double GetDistance(D3DXVECTOR3 a,D3DXVECTOR3 b) { D3DXVECTOR3 temp; return sqrt(pow(b.x-a.x,2)+pow(b.y-a.y,2)); } /********************************************************* * * CLASSES * **********************************************************/ class vObstacle { public: vector Point; const vObstacle& operator =(const vObstacle &) { return *this; } }; class vObstacles { public: vector Obstacles; void ClearList(){ while(Obstacles.size()) { while(Obstacles[Obstacles.size()-1].Point.size()) Obstacles[Obstacles.size()-1].Point.pop_back(); Obstacles.pop_back(); } } const vObstacles& operator =(const vObstacles &) { return *this; } }; /********************************************* * * GLOBAL VARIABLES * **********************************************/ vObstacles olist; int CreatingObstacles=0; int CreatingNewObstacle=0; int SettingStart=0; int SettingEnd=0; int RunPath=0; D3DXVECTOR3 startPoint(50,50,0); D3DXVECTOR3 endPoint(150,150,0); class CBeenTo { public: int BeenToObject; std::vector BeenToVertex; }; class pathFinder{ public: D3DXVECTOR3 direction; D3DXVECTOR3 location; float speed; BOOL foundPath; int nextPoint; D3DXVECTOR3 vNextPoint; std::vector BeenToList; std::vector path; int useOptimizedPath; int closestObject; int closestVertex; int foundClosest; float dist; pathFinder() { useOptimizedPath = 1; closestObject=0; closestVertex=0; foundClosest=0; dist=0.0f; foundPath=FALSE; nextPoint=0; speed=10.f; SetStartPoint(); } BOOL haveBeenToObjPoint(int objIndex,int vertexIndex) { int SkipVertex=0; //make shure we havent already tried this point if(BeenToList.size()) { for(int k=0;k2) for(int j=0;j1) { if(olist.Obstacles.size()) if(olist.Obstacles[0].Point.size()>2) { // get prev point D3DXVECTOR3 temp = olist.Obstacles[closestObject].Point[closestVertex==0?olist.Obstacles[closestObject].Point.size()-1:closestVertex-1]; //get next point D3DXVECTOR3 temp2 = olist.Obstacles[closestObject].Point[closestVertex==olist.Obstacles[closestObject].Point.size()-1?0:closestVertex+1]; D3DXVECTOR3 out = GetTriPoint(vNextPoint,temp,temp2); path.push_back(out); vNextPoint = path[path.size()-1]; } if(CheckObstacles(path[path.size()-1],endPoint)==false) { path.pop_back(); break; } else { path.pop_back(); path.pop_back(); vNextPoint = path[path.size()-1]; } } else { break; } } DoCleanPath(); if(olist.Obstacles.size()) if(olist.Obstacles[0].Point.size()>2) { // get prev point D3DXVECTOR3 temp = olist.Obstacles[closestObject].Point[closestVertex==0?olist.Obstacles[closestObject].Point.size()-1:closestVertex-1]; //get next point D3DXVECTOR3 temp2 = olist.Obstacles[closestObject].Point[closestVertex==olist.Obstacles[closestObject].Point.size()-1?0:closestVertex+1]; D3DXVECTOR3 out = GetTriPoint(vNextPoint,temp,temp2); path.push_back(out); vNextPoint = path[path.size()-1]; } path.push_back(endPoint); foundPath=TRUE; } } } void DoCleanPath() { if(useOptimizedPath==1) while(!CleanPath()){} } int CleanPath() { int foundAt=-1; double foundAtDist=100E100; //make shure path is the best possible for(int i=0; i < path.size()-1; i++) { for(int j=i+1; j < path.size(); j++) { if(CheckObstacles(path[i],path[j])==FALSE) { if(j > i +1) { double temp=GetDistance(path[j],endPoint); if(temp < foundAtDist) { foundAt=j; foundAtDist = temp; } } } } if(foundAt!=-1) { for(int k=foundAt-1; k>i; k--) { path.erase(&path.at(k)); } return 0; } } return 1; } void UpdatePosition(HWND hWnd) { if(RunPath) { if(foundPath==TRUE) { if(location!=path[nextPoint]) { direction = path[nextPoint] -startPoint; D3DXVECTOR3 out; D3DXVec3Normalize(&out,&direction); direction=out; if(GetDistance(location,path[nextPoint])<=speed) { location=path[nextPoint]; nextPoint++; } else { location+=direction*speed; } } else { location=path[nextPoint]; nextPoint++; } } if(nextPoint == path.size()) RunPath=0; startPoint=location; InvalidateRect(hWnd,NULL,false); } } void SetStartPoint() { location=startPoint; direction = endPoint-startPoint; D3DXVECTOR3 out; D3DXVec3Normalize(&out,&direction); direction=out; } BOOL CheckObstacles(const D3DXVECTOR3 &point,const D3DXVECTOR3 &dest) { for(int j=0;j