📄 ogreopcodemath.h
字号:
if (bb.vmin.z<vmin.z) vmin.z=bb.vmin.z;
if (bb.vmax.x>vmax.x) vmax.x=bb.vmax.x;
if (bb.vmax.y>vmax.y) vmax.y=bb.vmax.y;
if (bb.vmax.z>vmax.z) vmax.z=bb.vmax.z;
};
// get point of intersection of 3d line with planes
// on const x,y,z
bool isect_const_x(const float x, const line3& l, Ogre::Vector3& out) const
{
if (l.m.x != 0.0f)
{
float t = (x - l.b.x) / l.m.x;
if ((t>=0.0f) && (t<=1.0f))
{
// point of intersection...
out = l.ipol(t);
return true;
}
}
return false;
}
bool isect_const_y(const float y, const line3& l, Ogre::Vector3& out) const
{
if (l.m.y != 0.0f)
{
float t = (y - l.b.y) / l.m.y;
if ((t>=0.0f) && (t<=1.0f))
{
// point of intersection...
out = l.ipol(t);
return true;
}
}
return false;
}
bool isect_const_z(const float z, const line3& l, Ogre::Vector3& out) const
{
if (l.m.z != 0.0f)
{
float t = (z - l.b.z) / l.m.z;
if ((t>=0.0f) && (t<=1.0f))
{
// point of intersection...
out = l.ipol(t);
return true;
}
}
return false;
}
// point in polygon check for sides with constant x,y and z
bool pip_const_x(const Ogre::Vector3& p) const
{
if ((p.y>=vmin.y)&&(p.y<=vmax.y)&&(p.z>=vmin.z)&&(p.z<=vmax.z)) return true;
else return false;
}
bool pip_const_y(const Ogre::Vector3& p) const
{
if ((p.x>=vmin.x)&&(p.x<=vmax.x)&&(p.z>=vmin.z)&&(p.z<=vmax.z)) return true;
else return false;
}
bool pip_const_z(const Ogre::Vector3& p) const
{
if ((p.x>=vmin.x)&&(p.x<=vmax.x)&&(p.y>=vmin.y)&&(p.y<=vmax.y)) return true;
else return false;
}
//--- check if box intersects or contains line ------------------
bool intersect(const line3& line) const
{
// For each side of box, check if point of intersection
// lies within this sides 2d rectangle. If at least one
// intersection occurs, the line intersects the box
// (usually, there will be 2 intersections).
// The line parameter t for the intersection is computed
// by resolving the formula:
// p = line.b + line.m*t
// after t:
// t = (p - line.b) / line.m
// if line.m is zero, the line is parallel to the plane in
// question.
// MAY BE EXTENDED TO RETURN CLOSEST POINT OF INTERSECTION!
// check if at least one of the 2 points is included in the volume
Ogre::Vector3 s(line.start());
Ogre::Vector3 e(line.end());
if (((s.x>=vmin.x) && (s.y>=vmin.y) && (s.z>=vmin.z) &&
(s.x<=vmax.x) && (s.y<=vmax.y) && (s.z<=vmax.z)) ||
((e.x>=vmin.x) && (e.y>=vmin.y) && (e.z>=vmin.z) &&
(e.x<=vmax.x) && (e.y<=vmax.y) && (e.z<=vmax.z)))
{
return true;
} else
{
// otherwise do intersection check
int i;
Ogre::Vector3 ipos;
for (i=0; i<6; i++)
{
switch (i)
{
// left side, vmin.x is constant
case 0:
if (isect_const_x(vmin.x,line,ipos) && pip_const_x(ipos)) return true;
break;
case 1:
if (isect_const_x(vmax.x,line,ipos) && pip_const_x(ipos)) return true;
break;
case 2:
if (isect_const_y(vmin.y,line,ipos) && pip_const_y(ipos)) return true;
break;
case 3:
if (isect_const_y(vmax.y,line,ipos) && pip_const_y(ipos)) return true;
break;
case 4:
if (isect_const_z(vmin.z,line,ipos) && pip_const_z(ipos)) return true;
break;
case 5:
if (isect_const_z(vmax.z,line,ipos) && pip_const_z(ipos)) return true;
break;
}
}
}
return false;
}
/**
@brief Gets closest intersection with AABB.
If the line starts inside the box, start point is returned in ipos.
@param line the pick ray
@param ipos closest point of intersection if successful, trash otherwise
@return true if an intersection occurs
*/
bool intersect(const line3& line, Ogre::Vector3& ipos) const
{
// Handle special case for start point inside box
if (line.b.x >= vmin.x && line.b.y >= vmin.y && line.b.z >= vmin.z &&
line.b.x <= vmax.x && line.b.y <= vmax.y && line.b.z <= vmax.z)
{
ipos = line.b;
return true;
}
// Order planes to check, closest three only
int plane[3];
if (line.m.x > 0) plane[0] = 0;
else plane[0] = 1;
if (line.m.y > 0) plane[1] = 2;
else plane[1] = 3;
if (line.m.z > 0) plane[2] = 4;
else plane[2] = 5;
for (int i = 0; i < 3; ++i)
{
switch (plane[i])
{
case 0:
if (isect_const_x(vmin.x,line,ipos) && pip_const_x(ipos)) return true;
break;
case 1:
if (isect_const_x(vmax.x,line,ipos) && pip_const_x(ipos)) return true;
break;
case 2:
if (isect_const_y(vmin.y,line,ipos) && pip_const_y(ipos)) return true;
break;
case 3:
if (isect_const_y(vmax.y,line,ipos) && pip_const_y(ipos)) return true;
break;
case 4:
if (isect_const_z(vmin.z,line,ipos) && pip_const_z(ipos)) return true;
break;
case 5:
if (isect_const_z(vmax.z,line,ipos) && pip_const_z(ipos)) return true;
break;
}
}
return false;
}
//--- check if box intersects, contains or is contained in other box
//--- by doing 3 projection tests for each dimension, if all 3 test
//--- return true, then the 2 boxes intersect
int line_test(float v0, float v1, float w0, float w1)
{
// quick rejection test
if ((v1<w0) || (v0>w1)) return OUTSIDE;
else if ((v0==w0) && (v1==w1)) return ISEQUAL;
else if ((v0>=w0) && (v1<=w1)) return ISCONTAINED;
else if ((v0<=w0) && (v1>=w1)) return CONTAINS;
else return CLIPS;
}
int intersect(bbox3 box)
{
int and_code = 0xffff;
int or_code = 0;
int cx,cy,cz;
cx = line_test(vmin.x,vmax.x,box.vmin.x,box.vmax.x);
and_code&=cx; or_code|=cx;
cy = line_test(vmin.y,vmax.y,box.vmin.y,box.vmax.y);
and_code&=cy; or_code|=cy;
cz = line_test(vmin.z,vmax.z,box.vmin.z,box.vmax.z);
and_code&=cz; or_code|=cz;
if (or_code == 0) return OUTSIDE;
else if (and_code != 0)
{
return and_code;
} else
{
// only if all test produced a non-outside result,
// an intersection has occured
if (cx && cy && cz) return CLIPS;
else return OUTSIDE;
}
}
};
/// Just for ease of use, let bbox be an AABB. :P
typedef bbox3 Aabb;
class sphere
{
public:
Ogre::Vector3 p; // position
Ogre::Real r; // radius
//--- constructors ----------------------------------------------
sphere() : r(1.0f) {};
sphere(const Ogre::Vector3& _p, Ogre::Real _r) : p(_p), r(_r) {};
sphere(const sphere& s) : p(s.p), r(s.r) {};
sphere(Ogre::Real _x, Ogre::Real _y, Ogre::Real _z, Ogre::Real _r)
: r(_r)
{
p = Ogre::Vector3(_x,_y,_z);
};
//--- set position and radius ---
void set(const Ogre::Vector3& _p, Ogre::Real _r)
{
p = _p;
r = _r;
};
void set(Ogre::Real _x, Ogre::Real _y, Ogre::Real _z, Ogre::Real _r)
{
p = Ogre::Vector3(_x, _y, _z);
r = _r;
};
//--- check if 2 spheres overlap, without contact point ---------
bool intersects(const sphere& s) const
{
Ogre::Vector3 d(s.p-p);
Ogre::Real rsum = s.r+r;
if (d.squaredLength() <= (rsum*rsum)) return true;
else return false;
};
//--- check if 2 moving spheres have contact --------------------
//--- taken from "Simple Intersection Tests For Games" ----------
//--- article in Gamasutra, Oct 18 1999 -------------------------
bool intersect_sweep(const Ogre::Vector3& va, // in: distance travelled by 'this'
const sphere& sb, // in: the other sphere
const Ogre::Vector3& vb, // in: distance travelled by 'sb'
Ogre::Real& u0, // out: normalized intro contact u0
Ogre::Real& u1) // out: normalized outro contact u1
{
Ogre::Vector3 vab(vb - va);
Ogre::Vector3 ab(sb.p - p);
Ogre::Real rab = r + sb.r;
// check if spheres are currently overlapping...
if ((ab.dotProduct(ab)) <= (rab*rab))
{
u0 = 0.0f;
u1 = 0.0f;
return true;
} else
{
// check if they hit each other
Ogre::Real a = vab.dotProduct(vab);
if ((a<-TINY) || (a>+TINY))
{
// if a is '0' then the objects don't move relative to each other
Ogre::Real b = (vab.dotProduct(ab)) * 2.0f;
Ogre::Real c = (ab.dotProduct(ab)) - (rab * rab);
Ogre::Real q = b*b - 4*a*c;
if (q >= 0.0f) {
// 1 or 2 contacts
Ogre::Real sq = (Ogre::Real)sqrt(q);
Ogre::Real d = 1.0f / (2.0f*a);
Ogre::Real r1 = (-b + sq) * d;
Ogre::Real r2 = (-b - sq) * d;
if (r1 < r2)
{
u0 = r1;
u1 = r2;
} else
{
u0 = r2;
u1 = r1;
}
return true;
} else
return false;
} else
return false;
}
};
};
// includes the OBB header. looks strange, huh ? :P
//#include "OgreOrientedBox.h"
/* Triangle/triangle intersection test routine,
* by Tomas Moller, 1997.
* See article "A Fast Triangle-Triangle Intersection Test",
* Journal of Graphics Tools, 2(2), 1997
* updated: 2001-06-20 (added line of intersection)
*
* 2005-04-15 ported to CS by Andrew Dai
* 2006-06-21 ported to Ogre by Jacob Moen
*/
/**
* A 3D line segment. (Nicked from CrystalSpace)
*/
class Segment3
{
private:
/// Start.
Ogre::Vector3 _start;
/// End.
Ogre::Vector3 _end;
public:
/// Make a new segment and initialize with the given values.
Segment3 (const Ogre::Vector3& s, const Ogre::Vector3& e) { _start = s; _end = e; }
/// Make a new uninitialized segment.
Segment3 () { }
/// Set segment to given values.
inline void set (const Ogre::Vector3& s, const Ogre::Vector3& e)
{ _start = s; _end = e; }
/// Set the start of the segment.
inline void setStart (const Ogre::Vector3& s) { _start = s; }
/// Set the end of the segment.
inline void setEnd (const Ogre::Vector3& e) { _end = e; }
/// Get the start of the segment.
inline const Ogre::Vector3& start () const { return _start; }
/// Get the end of the segment.
inline const Ogre::Vector3& end () const { return _end; }
/// Get the start of the segment.
inline Ogre::Vector3& start () { return _start; }
/// Get the end of the segment.
inline Ogre::Vector3& end () { return _end; }
};
class Intersect3
{
public:
/**
* Test intersection between two triangles.
* \param tri1 Vertices of triangle 1
* \param tri2 Vertices of triangle 2
* \return true if the triangles intersect, otherwise false
*/
static bool triangleTriangle (const Ogre::Vector3 tri1[3],
const Ogre::Vector3 tri2[3]);
/**
* Calculate intersection between two triangles and return it
* in isectline.
* \param tri1 Vertices of triangle 1
* \param tri2 Vertices of triangle 2
* \param[out] isectline The line segment where they intersect
* \param[out] coplanar Returns whether the triangles are coplanar
* \return true if the triangles intersect, otherwise false
*/
static bool triangleTriangle (const Ogre::Vector3 tri1[3],
const Ogre::Vector3 tri2[3],
Segment3& isectline, bool& coplanar);
};
Ogre::String decimalToBinary(unsigned int i);
bool powerOf2(unsigned int i);
}
}
#endif // __OgreOpcodeMath_h__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -