[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__
#define __REVISION_NR_H__
#define REVISION_NR "10174"
#define REVISION_NR "10175"
#endif // __REVISION_NR_H__

View file

@ -34,13 +34,18 @@ namespace VMAP
class MapRayCallback
{
public:
MapRayCallback(ModelInstance *val): prims(val) {}
ModelInstance *prims;
MapRayCallback(ModelInstance *val): prims(val), hit(false) {}
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
{
return prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
//std::cout << "trying to intersect '" << entity->name << "'\n";
bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
if (result)
hit = true;
return result;
}
bool didHit(){ return hit; }
protected:
ModelInstance *prims;
bool hit;
};
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;
MapRayCallback intersectionCallBack(iTreeValues);
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 result = true;
float maxDist = (pos2 - pos1).magnitude();
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too:
ASSERT(maxDist < std::numeric_limits<float>::max());
@ -154,12 +161,10 @@ namespace VMAP
return true;
// direction with length of 1
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
float resultDist = getIntersectionTime(ray, maxDist, true);
if (resultDist < maxDist)
{
result = false;
}
return result;
if (getIntersectionTime(ray, maxDist, true))
return false;
return true;
}
//=========================================================
/**
@ -181,8 +186,8 @@ namespace VMAP
}
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
G3D::Ray ray(pPos1, dir);
float dist = getIntersectionTime(ray, maxDist, false);
if (dist < maxDist)
float dist = maxDist;
if (getIntersectionTime(ray, dist, false))
{
pResultHitPos = pPos1 + dir * dist;
if (pModifyDist < 0)
@ -218,10 +223,9 @@ namespace VMAP
Vector3 dir = Vector3(0,0,-1);
G3D::Ray ray(pPos, dir); // direction with length of 1
float maxDist = VMapDefinitions::getMaxCanFallDistance();
float dist = getIntersectionTime(ray, maxDist, false);
if (dist < maxDist)
if (getIntersectionTime(ray, maxDist, false))
{
height = pPos.z - dist;
height = pPos.z - maxDist;
}
return(height);
}

View file

@ -57,7 +57,7 @@ namespace VMAP
std::string iBasePath;
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)); }
public:
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);

View file

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