📄 routemap.cpp.svn-base
字号:
#pragma warning(disable: 4996)
#include <string>
#include <cassert>
#include <vector>
#include <map>
#include <algorithm>
#include "map.h"
#include "mapObj.h"
#include "staticMapObj.h"
#include "common/entityManager.h"
#include "common/graphicEntity.h"
#include "delaunay.h"
using std::vector;
using std::map;
using std::find;
using std::swap;
using std::sort;
void RouteMapObjSpace::addEntity(size_t dataId, DataType dataType, const Rectf &box)
{
RouteMapObjSpace *qs = this;
while(qs->child)
{
size_t cid = qs->getChildId(box);
if (cid == size_t(-1))
break;
else
qs = &qs->getChild(cid);
}
Node n;
n.dataType = dataType;
n.dataId = dataId;
n.boundingBox = box;
qs->entities.push_back(n);
}
size_t RouteMapObjSpace::getClosestEntity(const Point2f &point, float &minDistance, unsigned short filter) const
{
size_t entityId = size_t(-1);
minDistance = FLT_MAX;
for (size_t i = 0; i < entities.size(); i++)
{
if ((filter & entities[i].dataType) == 0)
continue;
float distance = entities[i].boundingBox.distance(point);
if (distance < minDistance)
{
minDistance = distance;
entityId = entities[i].dataId;
}
}
if (child)
{
for (size_t i = 0; i < NumSubSpaces; i++)
{
float distance = getChild(i).getRange().distance(point);
if (distance < minDistance)
{
size_t eid = getChild(i).getClosestEntity(point, distance, filter);
if (distance < minDistance)
{
minDistance = distance;
entityId = eid;
}
}
}
}
return entityId;
}
class DistanceCompare
{
public:
DistanceCompare() : minDistance(FLT_MAX)
{
}
virtual bool filter(DataType dt) const = 0;
virtual bool operator () (const Point2f &point, size_t id) = 0;
float getMinDistance() const
{
return minDistance;
}
void resetDistance()
{
minDistance = FLT_MAX;
}
protected:
float minDistance;
};
size_t RouteMapObjSpace::getClosestEntity(const Point2f &point, DistanceCompare &cmp) const
{
size_t entityId = size_t(-1);
for (size_t i = 0; i < entities.size(); i++)
{
if (!cmp.filter(entities[i].dataType))
continue;
float distance = entities[i].boundingBox.distance(point);
if (distance < cmp.getMinDistance() && cmp(point, entities[i].dataId))
{
entityId = entities[i].dataId;
}
}
if (child)
{
for (size_t i = 0; i < NumSubSpaces; i++)
{
float distance = getChild(i).getRange().distance(point);
if (distance < cmp.getMinDistance())
{
size_t eid = getChild(i).getClosestEntity(point, cmp);
if (eid != size_t(-1))
entityId = eid;
}
}
}
return entityId;
}
class RouteMapTriangleDistanceCompare : public DistanceCompare
{
public:
RouteMapTriangleDistanceCompare(const RouteMap &_rmap) : rmap(_rmap)
{
}
virtual bool filter(DataType dt) const
{
return (filterDataType & dt) != 0;
}
virtual bool operator () (const Point2f &point, size_t id)
{
assert(id < rmap.triangles.size());
const Point2f ¢er = rmap.getCenter(rmap.triangles[id]);
float len = (center - point).Length();
if (len < minDistance)
{
minDistance = len;
return true;
}
return false;
}
unsigned short filterDataType;
protected:
const RouteMap &rmap;
};
void RouteMap::renderDebug() const
{
float alpha = 128;
vector<size_t> objects;
MapObjCuller culler(objects);
culler.viewer = RenderQueue::getSingleton().getWindowViewer();
culler.dataType = DT_Triangle;
space.cull(culler);
#define ROUTEMAP_RENDERDEBUG_INTERSECT_POINTS 0
#define ROUTEMAP_RENDERDEBUG_TRIANGLE_EDGES 1
#define ROUTEMAP_RENDERDEBUG_BLOCK_TRIANGLE_EDGES 1
#define ROUTEMAP_RENDERDEBUG_FILL_BLOCK_AREA 1
for (size_t i = 0; i < objects.size(); i++)
{
size_t tid = objects[i];
assert(tid < triangles.size());
const Triangle &tri = triangles[tid];
const Point2f center = getCenter(tri);
//if (!tri.block)
const Point2f &pa = verticesBuffer[tri.v[Triangle::PointA]];
const Point2f &pb = verticesBuffer[tri.v[Triangle::PointB]];
const Point2f &pc = verticesBuffer[tri.v[Triangle::PointC]];
const Point2f &da = (pa - center).Normalize();
const Point2f &db = (pb - center).Normalize();
const Point2f &dc = (pc - center).Normalize();
#if ROUTEMAP_RENDERDEBUG_INTERSECT_POINTS
if (tri.va >= numOriginalVertices)
{
RenderQueue::getSingleton().render(pa - Point2f(3, 0), pa + Point2f(2, 0), ARGB(255, 0, 0, 255));
RenderQueue::getSingleton().render(pa - Point2f(0, 3), pa + Point2f(0, 2), ARGB(255, 0, 0, 255));
}
if (tri.vb >= numOriginalVertices)
{
RenderQueue::getSingleton().render(pb - Point2f(3, 0), pb + Point2f(2, 0), ARGB(255, 0, 0, 255));
RenderQueue::getSingleton().render(pb - Point2f(0, 3), pb + Point2f(0, 2), ARGB(255, 0, 0, 255));
}
if (tri.vc >= numOriginalVertices)
{
RenderQueue::getSingleton().render(pc - Point2f(3, 0), pc + Point2f(2, 0), ARGB(255, 0, 0, 255));
RenderQueue::getSingleton().render(pc - Point2f(0, 3), pc + Point2f(0, 2), ARGB(255, 0, 0, 255));
}
#endif
#if ROUTEMAP_RENDERDEBUG_TRIANGLE_EDGES
#if ROUTEMAP_RENDERDEBUG_BLOCK_TRIANGLE_EDGES
if (!tri.block)
#endif
{
// 宁可画2遍,也不愿意做一次检测...
DWORD c1 = ARGB(alpha, 128, 255, 128);
DWORD c2 = ARGB(alpha, 255, 255, 0);
DWORD c3 = ARGB(alpha, 255, 0, 255);
size_t eid = tri.e[Triangle::EdgeAB];
DWORD c = c1;
if (eid < edges.size())
{
if (edges[eid].bBad)
c = c2;
else if (edges[eid].failedToTurn)
c = c3;
}
RenderQueue::getSingleton().render(pa, pb, c);
eid = tri.e[Triangle::EdgeBC];
c = c1;
if (eid < edges.size())
{
if (edges[eid].bBad)
c = c2;
else if (edges[eid].failedToTurn)
c = c3;
}
RenderQueue::getSingleton().render(pc, pb, c);
eid = tri.e[Triangle::EdgeAC];
c = c1;
if (eid < edges.size())
{
if (edges[eid].bBad)
c = c2;
else if (edges[eid].failedToTurn)
c = c3;
}
RenderQueue::getSingleton().render(pa, pc, c);
}
#endif
#if 0
const Point2f p2[3] = {pa + da * -3, pb + db * -3, pc + dc * -3, };
for (int i = 0; i < 3; i++)
{
//if (tri.t[i] == size_t(-1))
{
RenderQueue::getSingleton().render(p2[(i + 2) % 3], p2[(i + 1) % 3], ARGB(alpha, 255, 128, 255));
}
/*
else
{
assert(tri.t[i] < triangles.size());
const Triangle &tOther = triangles[tri.t[i]];
const Point2f &cOther = getCenter(tOther);
RenderQueue::getSingleton().render(center, cOther , ARGB(64, 0, 0, 128));
}
*/
}
#endif
if (!tri.block)
{
}
#if ROUTEMAP_RENDERDEBUG_FILL_BLOCK_AREA
else
{
// 障碍物,填充红色
hgeTriple t;
t.v[0].x = pa.x;
t.v[0].y = pa.y;
t.v[0].z = 0;
t.v[0].col = ARGB(48, 255, 0, 0);
t.v[0].tx = t.v[0].ty = 0;
t.v[1].x = pb.x;
t.v[1].y = pb.y;
t.v[1].z = 0;
t.v[1].col = ARGB(48, 255, 0, 0);
t.v[1].tx = t.v[1].ty = 0;
t.v[2].x = pc.x;
t.v[2].y = pc.y;
t.v[2].z = 0;
t.v[2].col = ARGB(48, 255, 0, 0);
t.v[2].tx = t.v[2].ty = 0;
t.tex = 0;
t.blend = BLEND_DEFAULT;
RenderQueue::getSingleton().render(Point2f(), t);
}
#endif
}
objects.clear();
culler.dataType = DT_Edge;
polySpace.cull(culler);
HGE *hge = hgeCreate(HGE_VERSION);
Point2f mousePos;
hge->Input_GetMousePos(&mousePos.x, &mousePos.y);
hge->Release();
RenderQueue::getSingleton().screenToGame(mousePos);
vector<size_t> picked;
MapObjCuller pickCuller(picked);
pickCuller.viewer.leftTop = mousePos + Point2f(-10, -10);
pickCuller.viewer.rightBottom = mousePos + Point2f(10, 10);
pickCuller.dataType = DT_Edge;
space.cull(pickCuller);
RenderQueue::getSingleton().render(pickCuller.viewer.leftTop, pickCuller.viewer.rightBottom, ARGB(255, 255, 0, 255));
for (size_t p = 0; p < picked.size(); p++)
{
size_t peid = picked[p];
assert(peid < edges.size());
const Edge &pe = edges[peid];
const Point2f &pea = verticesBuffer[pe.va];
const Point2f &peb = verticesBuffer[pe.vb];
RenderQueue::getSingleton().render(pea, peb, ARGB(255, 255, 128, 128));
Point2f crossPoint0;
if (::LineCrossPoint(pea, peb, pickCuller.viewer.leftTop, pickCuller.viewer.rightBottom, crossPoint0))
{
for (size_t i = 0; i < objects.size(); i++)
{
size_t eid = objects[i];
assert(eid < polyEdges.size());
const Edge &e = polyEdges[eid];
const Point2f &pa = verticesBuffer[e.va];
const Point2f &pb = verticesBuffer[e.vb];
Point2f crossPoint;
if (LineCrossPoint(e, pe, crossPoint)) // 求交点
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -