[10175] Fix incorrectly blocked line of sight in certain locations.

I really should know by now that floats are not infinitely precise...
This commit is contained in:
Lynx3d 2010-07-10 04:18:49 +02:00
parent 695f0f1655
commit 00751347e5
4 changed files with 30 additions and 23 deletions

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "10174" #define REVISION_NR "10175"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -34,13 +34,18 @@ namespace VMAP
class MapRayCallback class MapRayCallback
{ {
public: public:
MapRayCallback(ModelInstance *val): prims(val) {} MapRayCallback(ModelInstance *val): prims(val), hit(false) {}
ModelInstance *prims;
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
{ {
return prims[entry].intersectRay(ray, distance, pStopAtFirstHit); bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
//std::cout << "trying to intersect '" << entity->name << "'\n"; if (result)
hit = true;
return result;
} }
bool didHit(){ return hit; }
protected:
ModelInstance *prims;
bool hit;
}; };
class AreaInfoCallback class AreaInfoCallback
@ -131,21 +136,23 @@ namespace VMAP
//========================================================= //=========================================================
/** /**
return dist to hit or inf() if no hit If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true.
Else, pMaxDist is not modified and returns false;
*/ */
float StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const
{ {
float distance = pMaxDist; float distance = pMaxDist;
MapRayCallback intersectionCallBack(iTreeValues); MapRayCallback intersectionCallBack(iTreeValues);
iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit); iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit);
return distance; if (intersectionCallBack.didHit())
pMaxDist = distance;
return intersectionCallBack.didHit();
} }
//========================================================= //=========================================================
bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const
{ {
bool result = true;
float maxDist = (pos2 - pos1).magnitude(); float maxDist = (pos2 - pos1).magnitude();
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too: // valid map coords should *never ever* produce float overflow, but this would produce NaNs too:
ASSERT(maxDist < std::numeric_limits<float>::max()); ASSERT(maxDist < std::numeric_limits<float>::max());
@ -154,12 +161,10 @@ namespace VMAP
return true; return true;
// direction with length of 1 // direction with length of 1
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist); G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
float resultDist = getIntersectionTime(ray, maxDist, true); if (getIntersectionTime(ray, maxDist, true))
if (resultDist < maxDist) return false;
{
result = false; return true;
}
return result;
} }
//========================================================= //=========================================================
/** /**
@ -181,8 +186,8 @@ namespace VMAP
} }
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
G3D::Ray ray(pPos1, dir); G3D::Ray ray(pPos1, dir);
float dist = getIntersectionTime(ray, maxDist, false); float dist = maxDist;
if (dist < maxDist) if (getIntersectionTime(ray, dist, false))
{ {
pResultHitPos = pPos1 + dir * dist; pResultHitPos = pPos1 + dir * dist;
if (pModifyDist < 0) if (pModifyDist < 0)
@ -218,10 +223,9 @@ namespace VMAP
Vector3 dir = Vector3(0,0,-1); Vector3 dir = Vector3(0,0,-1);
G3D::Ray ray(pPos, dir); // direction with length of 1 G3D::Ray ray(pPos, dir); // direction with length of 1
float maxDist = VMapDefinitions::getMaxCanFallDistance(); float maxDist = VMapDefinitions::getMaxCanFallDistance();
float dist = getIntersectionTime(ray, maxDist, false); if (getIntersectionTime(ray, maxDist, false))
if (dist < maxDist)
{ {
height = pPos.z - dist; height = pPos.z - maxDist;
} }
return(height); return(height);
} }

View file

@ -57,7 +57,7 @@ namespace VMAP
std::string iBasePath; std::string iBasePath;
private: private:
float getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const; bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const;
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
public: public:
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);

View file

@ -54,8 +54,11 @@ namespace VMAP
Ray modRay(p, iInvRot * pRay.direction()); Ray modRay(p, iInvRot * pRay.direction());
float distance = pMaxDist * iInvScale; float distance = pMaxDist * iInvScale;
bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit); bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit);
distance *= iScale; if(hit)
pMaxDist = distance; {
distance *= iScale;
pMaxDist = distance;
}
return hit; return hit;
} }