support for roll/pitch on model ellipse collision
parent
63fb76d25b
commit
5bb0779a7a
|
@ -282,27 +282,21 @@ bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist
|
|||
int yaw = e.attr2, pitch = e.attr3, roll = e.attr4;
|
||||
if(yaw != 0)
|
||||
{
|
||||
if(yaw < 0) yaw = 360 + yaw%360;
|
||||
else if(yaw >= 360) yaw %= 360;
|
||||
const vec2 &rot = sincos360[yaw];
|
||||
mo.rotate_around_z(rot.x, -rot.y);
|
||||
mray.rotate_around_z(rot.x, -rot.y);
|
||||
const vec2 &rot = sincosmod360(-yaw);
|
||||
mo.rotate_around_z(rot);
|
||||
mray.rotate_around_z(rot);
|
||||
}
|
||||
if(pitch != 0)
|
||||
{
|
||||
if(pitch < 0) pitch = 360 + pitch%360;
|
||||
else if(pitch >= 360) pitch %= 360;
|
||||
const vec2 &rot = sincos360[pitch];
|
||||
mo.rotate_around_x(rot.x, -rot.y);
|
||||
mray.rotate_around_x(rot.x, -rot.y);
|
||||
const vec2 &rot = sincosmod360(-pitch);
|
||||
mo.rotate_around_x(rot);
|
||||
mray.rotate_around_x(rot);
|
||||
}
|
||||
if(roll != 0)
|
||||
{
|
||||
if(roll < 0) roll = 360 + roll%360;
|
||||
else if(roll >= 360) roll %= 360;
|
||||
const vec2 &rot = sincos360[roll];
|
||||
mo.rotate_around_y(rot.x, rot.y);
|
||||
mray.rotate_around_y(rot.x, rot.y);
|
||||
const vec2 &rot = sincosmod360(roll);
|
||||
mo.rotate_around_y(rot);
|
||||
mray.rotate_around_y(rot);
|
||||
}
|
||||
if(m->bih->traverse(mo, mray, maxdist ? maxdist : 1e16f, dist, mode))
|
||||
{
|
||||
|
|
|
@ -82,17 +82,17 @@ namespace mpr
|
|||
struct EntOBB
|
||||
{
|
||||
physent *ent;
|
||||
quat orient;
|
||||
matrix3x3 orient;
|
||||
float zmargin;
|
||||
|
||||
EntOBB(physent *ent, float zmargin = 0) : ent(ent), orient(vec(0, 0, 1), ent->yaw*RAD), zmargin(zmargin) {}
|
||||
EntOBB(physent *ent, float zmargin = 0) : ent(ent), orient(ent->yaw*RAD, vec(0, 0, 1)), zmargin(zmargin) {}
|
||||
|
||||
vec center() const { vec o(ent->o); o.z += (ent->aboveeye - ent->eyeheight - zmargin)/2; return o; }
|
||||
|
||||
vec contactface(const vec &wn, const vec &wdir) const
|
||||
{
|
||||
vec n = orient.invertedrotate(wn).div(vec(ent->xradius, ent->yradius, (ent->aboveeye + ent->eyeheight + zmargin)/2)),
|
||||
dir = orient.invertedrotate(wdir),
|
||||
vec n = orient.transform(wn).div(vec(ent->xradius, ent->yradius, (ent->aboveeye + ent->eyeheight + zmargin)/2)),
|
||||
dir = orient.transform(wdir),
|
||||
an(fabs(n.x), fabs(n.y), dir.z ? fabs(n.z) : 0),
|
||||
fn(0, 0, 0);
|
||||
if(an.x > an.y)
|
||||
|
@ -102,19 +102,19 @@ namespace mpr
|
|||
}
|
||||
else if(an.y > an.z) fn.y = n.y*dir.y < 0 ? (n.y > 0 ? 1 : -1) : 0;
|
||||
else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
|
||||
return orient.rotate(fn);
|
||||
return orient.transposedtransform(fn);
|
||||
}
|
||||
|
||||
vec supportpoint(const vec &n) const
|
||||
{
|
||||
vec ln = orient.invertedrotate(n), p(0, 0, 0);
|
||||
vec ln = orient.transform(n), p(0, 0, 0);
|
||||
if(ln.x > 0) p.x += ent->xradius;
|
||||
else p.x -= ent->xradius;
|
||||
if(ln.y > 0) p.y += ent->yradius;
|
||||
else p.y -= ent->yradius;
|
||||
if(ln.z > 0) p.z += ent->aboveeye;
|
||||
else p.z -= ent->eyeheight + zmargin;
|
||||
return orient.rotate(p).add(ent->o);
|
||||
return orient.transposedtransform(p).add(ent->o);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -195,20 +195,22 @@ namespace mpr
|
|||
struct ModelOBB
|
||||
{
|
||||
vec o, radius;
|
||||
quat orient;
|
||||
matrix3x3 orient;
|
||||
|
||||
ModelOBB(const vec &ent, const vec ¢er, const vec &radius, float yaw, float pitch, float roll) : o(ent), radius(radius), orient(vec(0, 0, 1), yaw*RAD)
|
||||
ModelOBB(const vec &ent, const vec ¢er, const vec &radius, int yaw, int pitch, int roll) : o(ent), radius(radius)
|
||||
{
|
||||
if(pitch) orient.mul(quat(vec(1, 0, 0), pitch*RAD));
|
||||
if(roll) orient.mul(quat(vec(0, -1, 0), roll*RAD));
|
||||
o.add(orient.rotate(center));
|
||||
orient.identity();
|
||||
if(roll) orient.rotate_around_y(sincosmod360(roll));
|
||||
if(pitch) orient.rotate_around_x(sincosmod360(-pitch));
|
||||
if(yaw) orient.rotate_around_z(sincosmod360(-yaw));
|
||||
o.add(orient.transposedtransform(center));
|
||||
}
|
||||
|
||||
vec center() const { return o; }
|
||||
|
||||
vec contactface(const vec &wn, const vec &wdir) const
|
||||
{
|
||||
vec n = orient.invertedrotate(wn).div(radius), dir = orient.invertedrotate(wdir),
|
||||
vec n = orient.transform(wn).div(radius), dir = orient.transform(wdir),
|
||||
an(fabs(n.x), fabs(n.y), dir.z ? fabs(n.z) : 0),
|
||||
fn(0, 0, 0);
|
||||
if(an.x > an.y)
|
||||
|
@ -218,63 +220,65 @@ namespace mpr
|
|||
}
|
||||
else if(an.y > an.z) fn.y = n.y*dir.y < 0 ? (n.y > 0 ? 1 : -1) : 0;
|
||||
else if(an.z > 0) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
|
||||
return orient.rotate(fn);
|
||||
return orient.transposedtransform(fn);
|
||||
}
|
||||
|
||||
vec supportpoint(const vec &n) const
|
||||
{
|
||||
vec ln = orient.invertedrotate(n), p(0, 0, 0);
|
||||
vec ln = orient.transform(n), p(0, 0, 0);
|
||||
if(ln.x > 0) p.x += radius.x;
|
||||
else p.x -= radius.x;
|
||||
if(ln.y > 0) p.y += radius.y;
|
||||
else p.y -= radius.y;
|
||||
if(ln.z > 0) p.z += radius.z;
|
||||
else p.z -= radius.z;
|
||||
return orient.rotate(p).add(o);
|
||||
return orient.transposedtransform(p).add(o);
|
||||
}
|
||||
};
|
||||
|
||||
struct ModelEllipse
|
||||
{
|
||||
vec o, radius;
|
||||
quat orient;
|
||||
matrix3x3 orient;
|
||||
|
||||
ModelEllipse(const vec &ent, const vec ¢er, const vec &radius, float yaw, float pitch, float roll) : o(ent), radius(radius), orient(vec(0, 0, 1), yaw*RAD)
|
||||
ModelEllipse(const vec &ent, const vec ¢er, const vec &radius, float yaw, float pitch, float roll) : o(ent), radius(radius)
|
||||
{
|
||||
if(pitch) orient.mul(quat(vec(1, 0, 0), pitch*RAD));
|
||||
if(roll) orient.mul(quat(vec(0, -1, 0), roll*RAD));
|
||||
o.add(orient.rotate(center));
|
||||
orient.identity();
|
||||
if(roll) orient.rotate_around_y(sincosmod360(roll));
|
||||
if(pitch) orient.rotate_around_x(sincosmod360(-pitch));
|
||||
if(yaw) orient.rotate_around_z(sincosmod360(-yaw));
|
||||
o.add(orient.transposedtransform(center));
|
||||
}
|
||||
|
||||
vec center() const { return o; }
|
||||
|
||||
vec contactface(const vec &wn, const vec &wdir) const
|
||||
{
|
||||
vec n = orient.invertedrotate(wn).div(radius), dir = orient.invertedrotate(wdir);
|
||||
vec n = orient.transform(wn).div(radius), dir = orient.transform(wdir);
|
||||
float dxy = n.dot2(n), dz = n.z*n.z;
|
||||
vec fn(0, 0, 0);
|
||||
if(dz > dxy && dir.z) fn.z = n.z*dir.z < 0 ? (n.z > 0 ? 1 : -1) : 0;
|
||||
else if(n.dot2(dir) < 0)
|
||||
{
|
||||
fn.x = n.x*radius.x;
|
||||
fn.y = n.y*radius.y;
|
||||
fn.x = n.x*radius.y;
|
||||
fn.y = n.y*radius.x;
|
||||
fn.normalize();
|
||||
}
|
||||
return orient.rotate(fn);
|
||||
return orient.transposedtransform(fn);
|
||||
}
|
||||
|
||||
vec supportpoint(const vec &n) const
|
||||
{
|
||||
vec ln = orient.invertedrotate(n), p(0, 0, 0);
|
||||
vec ln = orient.transform(n), p(0, 0, 0);
|
||||
if(ln.z > 0) p.z += radius.z;
|
||||
else p.z -= radius.z;
|
||||
if(ln.x || ln.y)
|
||||
{
|
||||
float r = n.magnitude2();
|
||||
float r = ln.magnitude2();
|
||||
p.x += ln.x*radius.x/r;
|
||||
p.y += ln.y*radius.y/r;
|
||||
}
|
||||
return orient.rotate(p).add(o);
|
||||
return orient.transposedtransform(p).add(o);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -717,36 +717,13 @@ bool plcollide(physent *d, const vec &dir) // collide with player or monster
|
|||
|
||||
void rotatebb(vec ¢er, vec &radius, int yaw, int pitch, int roll)
|
||||
{
|
||||
if(roll)
|
||||
{
|
||||
if(roll < 0) roll = 360 + roll%360;
|
||||
else if(roll >= 360) roll %= 360;
|
||||
const vec2 &rot = sincos360[roll];
|
||||
center.rotate_around_y(rot.x, -rot.y);
|
||||
vec2 oldradius(radius.x, radius.z);
|
||||
radius.x = fabs(oldradius.x*rot.x) + fabs(oldradius.y*rot.y);
|
||||
radius.z = fabs(oldradius.y*rot.x) + fabs(oldradius.x*rot.y);
|
||||
}
|
||||
if(pitch)
|
||||
{
|
||||
if(pitch < 0) pitch = 360 + pitch%360;
|
||||
else if(pitch >= 360) pitch %= 360;
|
||||
const vec2 &rot = sincos360[pitch];
|
||||
center.rotate_around_x(rot.x, rot.y);
|
||||
vec2 oldradius(radius.y, radius.z);
|
||||
radius.y = fabs(oldradius.x*rot.x) + fabs(oldradius.y*rot.y);
|
||||
radius.z = fabs(oldradius.y*rot.x) + fabs(oldradius.x*rot.y);
|
||||
}
|
||||
if(yaw)
|
||||
{
|
||||
if(yaw < 0) yaw = 360 + yaw%360;
|
||||
else if(yaw >= 360) yaw %= 360;
|
||||
const vec2 &rot = sincos360[yaw];
|
||||
center.rotate_around_z(rot.x, rot.y);
|
||||
vec2 oldradius(radius);
|
||||
radius.x = fabs(oldradius.x*rot.x) + fabs(oldradius.y*rot.y);
|
||||
radius.y = fabs(oldradius.y*rot.x) + fabs(oldradius.x*rot.y);
|
||||
}
|
||||
matrix3x3 orient;
|
||||
orient.identity();
|
||||
if(yaw) orient.rotate_around_z(sincosmod360(yaw));
|
||||
if(pitch) orient.rotate_around_x(sincosmod360(pitch));
|
||||
if(roll) orient.rotate_around_y(sincosmod360(-roll));
|
||||
center = orient.transform(center);
|
||||
radius = orient.abstransform(radius);
|
||||
}
|
||||
|
||||
template<class E, class M>
|
||||
|
@ -768,37 +745,13 @@ static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, con
|
|||
template<class E>
|
||||
static bool fuzzycolliderect(physent *d, const vec &dir, float cutoff, const vec &o, const vec ¢er, const vec &radius, int yaw, int pitch, int roll)
|
||||
{
|
||||
vec bbcenter = center, bbradius = radius;
|
||||
rotatebb(bbcenter, bbradius, yaw, pitch, roll);
|
||||
bbcenter.add(o);
|
||||
mpr::ModelOBB mdlvol(o, center, radius, yaw, pitch, roll);
|
||||
vec bbradius = mdlvol.orient.abstransposedtransform(radius);
|
||||
|
||||
if(fabs(d->o.x - bbcenter.x) > bbradius.x + d->radius || fabs(d->o.y - bbcenter.y) > bbradius.y + d->radius ||
|
||||
d->o.z + d->aboveeye < bbcenter.z - bbradius.z || d->o.z - d->eyeheight > bbcenter.z + bbradius.z)
|
||||
if(fabs(d->o.x - mdlvol.o.x) > bbradius.x + d->radius || fabs(d->o.y - mdlvol.o.y) > bbradius.y + d->radius ||
|
||||
d->o.z + d->aboveeye < mdlvol.o.z - bbradius.z || d->o.z - d->eyeheight > mdlvol.o.z + bbradius.z)
|
||||
return true;
|
||||
|
||||
matrix3x3 orient;
|
||||
orient.identity();
|
||||
if(roll)
|
||||
{
|
||||
if(roll < 0) roll = 360 + roll%360;
|
||||
else if(roll >= 360) roll %= 360;
|
||||
const vec2 &rot = sincos360[roll];
|
||||
orient.rotate_around_y(rot.x, rot.y);
|
||||
}
|
||||
if(pitch)
|
||||
{
|
||||
if(pitch < 0) pitch = 360 + pitch%360;
|
||||
else if(pitch >= 360) pitch %= 360;
|
||||
const vec2 &rot = sincos360[pitch];
|
||||
orient.rotate_around_x(rot.x, -rot.y);
|
||||
}
|
||||
if(yaw)
|
||||
{
|
||||
if(yaw < 0) yaw = 360 + yaw%360;
|
||||
else if(yaw >= 360) yaw %= 360;
|
||||
const vec2 &rot = sincos360[yaw];
|
||||
orient.rotate_around_z(rot.x, -rot.y);
|
||||
}
|
||||
E entvol(d);
|
||||
wall = vec(0, 0, 0);
|
||||
float bestdist = -1e10f;
|
||||
|
@ -808,15 +761,15 @@ static bool fuzzycolliderect(physent *d, const vec &dir, float cutoff, const vec
|
|||
float dist;
|
||||
switch(i)
|
||||
{
|
||||
case 0: w = vec(orient.a).neg(); dist = center.x - radius.x; break;
|
||||
case 1: w = orient.a; dist = -center.x - radius.x; break;
|
||||
case 2: w = vec(orient.b).neg(); dist = center.y - radius.y; break;
|
||||
case 3: w = orient.b; dist = -center.y - radius.y; break;
|
||||
case 4: w = vec(orient.c).neg(); dist = center.z - radius.z; break;
|
||||
case 5: w = orient.c; dist = -center.z - radius.z; break;
|
||||
case 0: w = vec(mdlvol.orient.a).neg(); dist = -radius.x; break;
|
||||
case 1: w = mdlvol.orient.a; dist = -radius.x; break;
|
||||
case 2: w = vec(mdlvol.orient.b).neg(); dist = -radius.y; break;
|
||||
case 3: w = mdlvol.orient.b; dist = -radius.y; break;
|
||||
case 4: w = vec(mdlvol.orient.c).neg(); dist = -radius.z; break;
|
||||
case 5: w = mdlvol.orient.c; dist = -radius.z; break;
|
||||
}
|
||||
vec pw = entvol.supportpoint(vec(w).neg());
|
||||
dist += w.dot(vec(pw).sub(o));
|
||||
dist += w.dot(vec(pw).sub(mdlvol.o));
|
||||
if(dist >= 0) return true;
|
||||
if(dist <= bestdist) continue;
|
||||
wall = vec(0, 0, 0);
|
||||
|
@ -840,6 +793,58 @@ static bool fuzzycolliderect(physent *d, const vec &dir, float cutoff, const vec
|
|||
return false;
|
||||
}
|
||||
|
||||
template<class E>
|
||||
static bool fuzzycollideellipse(physent *d, const vec &dir, float cutoff, const vec &o, const vec ¢er, const vec &radius, int yaw, int pitch, int roll)
|
||||
{
|
||||
E entvol(d);
|
||||
mpr::ModelEllipse mdlvol(o, center, radius, yaw, pitch, roll);
|
||||
if(!mpr::collide(entvol, mdlvol)) return true;
|
||||
|
||||
wall = vec(0, 0, 0);
|
||||
float bestdist = -1e10f;
|
||||
loopi(3)
|
||||
{
|
||||
vec w;
|
||||
float dist;
|
||||
switch(i)
|
||||
{
|
||||
case 0: w = mdlvol.orient.c; dist = -radius.z; break;
|
||||
case 1: w = vec(mdlvol.orient.c).neg(); dist = -radius.z; break;
|
||||
case 2:
|
||||
{
|
||||
vec2 ln(mdlvol.orient.transform(entvol.center().sub(mdlvol.o)));
|
||||
float r = ln.magnitude();
|
||||
if(r < 1e-6f) continue;
|
||||
vec2 lw = vec2(ln.x*radius.y, ln.y*radius.x).normalize();
|
||||
w = mdlvol.orient.transposedtransform(lw);
|
||||
dist = -vec2(ln.x*radius.x, ln.y*radius.y).dot(lw)/r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
vec pw = entvol.supportpoint(vec(w).neg());
|
||||
dist += w.dot(vec(pw).sub(mdlvol.o));
|
||||
if(dist <= bestdist) continue;
|
||||
wall = vec(0, 0, 0);
|
||||
bestdist = dist;
|
||||
if(!dir.iszero())
|
||||
{
|
||||
if(w.dot(dir) >= -cutoff*dir.magnitude()) continue;
|
||||
if(d->type<ENT_CAMERA &&
|
||||
dist < (dir.z*w.z < 0 ?
|
||||
d->zmargin-(d->eyeheight+d->aboveeye)/(dir.z < 0 ? 3.0f : 4.0f) :
|
||||
((dir.x*w.x < 0 || dir.y*w.y < 0) ? -d->radius : 0)))
|
||||
continue;
|
||||
}
|
||||
wall = w;
|
||||
}
|
||||
if(wall.iszero())
|
||||
{
|
||||
inside = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mmcollide(physent *d, const vec &dir, float cutoff, octaentities &oc) // collide with a mapmodel
|
||||
{
|
||||
const vector<extentity *> &ents = entities::getents();
|
||||
|
@ -859,8 +864,11 @@ bool mmcollide(physent *d, const vec &dir, float cutoff, octaentities &oc) // co
|
|||
if(m->ellipsecollide)
|
||||
{
|
||||
//if(!mmcollide<mpr::EntCylinder, mpr::ModelEllipse>(d, dir, e, center, radius, yaw, pitch, roll)) return false;
|
||||
if(pitch || roll) rotatebb(center, radius, 0, pitch, roll);
|
||||
if(!ellipsecollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return false;
|
||||
if(pitch || roll)
|
||||
{
|
||||
if(!fuzzycollideellipse<mpr::EntCapsule>(d, dir, cutoff, e.o, center, radius, yaw, pitch, roll)) return false;
|
||||
}
|
||||
else if(!ellipsecollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return false;
|
||||
}
|
||||
//else if(!mmcollide<mpr::EntCylinder, mpr::ModelOBB>(d, dir, e, center, radius, yaw, pitch, roll)) return false;
|
||||
else if(pitch || roll)
|
||||
|
|
|
@ -1,5 +1,59 @@
|
|||
struct vec;
|
||||
struct vec4;
|
||||
struct vec2;
|
||||
|
||||
struct vec2
|
||||
{
|
||||
union
|
||||
{
|
||||
struct { float x, y; };
|
||||
float v[2];
|
||||
};
|
||||
|
||||
vec2() {}
|
||||
vec2(float x, float y) : x(x), y(y) {}
|
||||
explicit vec2(const vec &v);
|
||||
explicit vec2(const vec4 &v);
|
||||
|
||||
float &operator[](int i) { return v[i]; }
|
||||
float operator[](int i) const { return v[i]; }
|
||||
|
||||
bool operator==(const vec2 &o) const { return x == o.x && y == o.y; }
|
||||
bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; }
|
||||
|
||||
bool iszero() const { return x==0 && y==0; }
|
||||
float dot(const vec2 &o) const { return x*o.x + y*o.y; }
|
||||
float squaredlen() const { return dot(*this); }
|
||||
float magnitude() const { return sqrtf(squaredlen()); }
|
||||
vec2 &normalize() { mul(1/magnitude()); return *this; }
|
||||
float cross(const vec2 &o) const { return x*o.y - y*o.x; }
|
||||
|
||||
vec2 &mul(float f) { x *= f; y *= f; return *this; }
|
||||
vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; }
|
||||
vec2 &div(float f) { x /= f; y /= f; return *this; }
|
||||
vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; }
|
||||
vec2 &add(float f) { x += f; y += f; return *this; }
|
||||
vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; }
|
||||
vec2 &sub(float f) { x -= f; y -= f; return *this; }
|
||||
vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; }
|
||||
vec2 &neg() { x = -x; y = -y; return *this; }
|
||||
|
||||
vec2 &lerp(const vec2 &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; return *this; }
|
||||
vec2 &lerp(const vec2 &a, const vec2 &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; return *this; }
|
||||
vec2 &avg(const vec2 &b) { add(b); mul(0.5f); return *this; }
|
||||
};
|
||||
|
||||
static inline bool htcmp(const vec2 &x, const vec2 &y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
static inline uint hthash(const vec2 &k)
|
||||
{
|
||||
union { uint i; float f; } x, y;
|
||||
x.f = k.x; y.f = k.y;
|
||||
uint v = x.i^y.i;
|
||||
return v + (v>>12);
|
||||
}
|
||||
|
||||
struct vec
|
||||
{
|
||||
|
@ -16,8 +70,8 @@ struct vec
|
|||
vec(float a, float b, float c) : x(a), y(b), z(c) {}
|
||||
explicit vec(int v[3]) : x(v[0]), y(v[1]), z(v[2]) {}
|
||||
explicit vec(const float *v) : x(v[0]), y(v[1]), z(v[2]) {}
|
||||
explicit vec(const vec2 &v, float z = 0) : x(v.x), y(v.y), z(z) {}
|
||||
explicit vec(const vec4 &v);
|
||||
explicit vec(const vec2 &v, float z = 0);
|
||||
|
||||
vec(float yaw, float pitch) : x(-sinf(yaw)*cosf(pitch)), y(cosf(yaw)*cosf(pitch)), z(sinf(pitch)) {}
|
||||
|
||||
|
@ -31,8 +85,10 @@ struct vec
|
|||
|
||||
bool iszero() const { return x==0 && y==0 && z==0; }
|
||||
float squaredlen() const { return x*x + y*y + z*z; }
|
||||
float dot2(const vec2 &o) const { return x*o.x + y*o.y; }
|
||||
float dot2(const vec &o) const { return x*o.x + y*o.y; }
|
||||
float dot(const vec &o) const { return x*o.x + y*o.y + z*o.z; }
|
||||
float absdot(const vec &o) const { return fabs(x*o.x) + fabs(y*o.y) + fabs(z*o.z); }
|
||||
vec &mul(const vec &o) { x *= o.x; y *= o.y; z *= o.z; return *this; }
|
||||
vec &mul(float f) { x *= f; y *= f; z *= f; return *this; }
|
||||
vec &div(const vec &o) { x /= o.x; y /= o.y; z /= o.z; return *this; }
|
||||
|
@ -47,6 +103,7 @@ struct vec
|
|||
vec &max(const vec &o) { x = ::max(x, o.x); y = ::max(y, o.y); z = ::max(z, o.z); return *this; }
|
||||
vec &min(float f) { x = ::min(x, f); y = ::min(y, f); z = ::min(z, f); return *this; }
|
||||
vec &max(float f) { x = ::max(x, f); y = ::max(y, f); z = ::max(z, f); return *this; }
|
||||
vec &abs() { x = fabs(x); y = fabs(y); z = fabs(z); return *this; }
|
||||
vec &clamp(float f, float h) { x = ::clamp(x, f, h); y = ::clamp(y, f, h); z = ::clamp(z, f, h); return *this; }
|
||||
float magnitude2() const { return sqrtf(dot2(*this)); }
|
||||
float magnitude() const { return sqrtf(squaredlen()); }
|
||||
|
@ -98,11 +155,9 @@ struct vec
|
|||
vec &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
|
||||
vec &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
|
||||
|
||||
vec &rotate(float angle, const vec &d)
|
||||
{
|
||||
float c = cosf(angle), s = sinf(angle);
|
||||
return rotate(c, s, d);
|
||||
}
|
||||
vec &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
|
||||
vec &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); }
|
||||
vec &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); }
|
||||
|
||||
vec &rotate(float c, float s, const vec &d)
|
||||
{
|
||||
|
@ -112,6 +167,9 @@ struct vec
|
|||
return *this;
|
||||
}
|
||||
|
||||
vec &rotate(float angle, const vec &d) { return rotate(cosf(angle), sinf(angle), d); }
|
||||
vec &rotate(const vec2 &sc, const vec &d) { return rotate(sc.x, sc.y, d); }
|
||||
|
||||
void orthogonal(const vec &d)
|
||||
{
|
||||
int i = fabs(d.x) > fabs(d.y) ? (fabs(d.x) > fabs(d.z) ? 0 : 2) : (fabs(d.y) > fabs(d.z) ? 1 : 2);
|
||||
|
@ -156,6 +214,8 @@ struct vec
|
|||
int tohexcolor() { return ((int(r*255)>>16)&0xFF)|((int(g*255)>>8)&0xFF)|(int(b*255)&0xFF); }
|
||||
};
|
||||
|
||||
inline vec2::vec2(const vec &v) : x(v.x), y(v.y) {}
|
||||
|
||||
static inline bool htcmp(const vec &x, const vec &y)
|
||||
{
|
||||
return x == y;
|
||||
|
@ -242,66 +302,15 @@ struct vec4
|
|||
vec4 &rotate_around_z(float angle) { return rotate_around_z(cosf(angle), sinf(angle)); }
|
||||
vec4 &rotate_around_x(float angle) { return rotate_around_x(cosf(angle), sinf(angle)); }
|
||||
vec4 &rotate_around_y(float angle) { return rotate_around_y(cosf(angle), sinf(angle)); }
|
||||
|
||||
vec4 &rotate_around_z(const vec2 &sc) { return rotate_around_z(sc.x, sc.y); }
|
||||
vec4 &rotate_around_x(const vec2 &sc) { return rotate_around_x(sc.x, sc.y); }
|
||||
vec4 &rotate_around_y(const vec2 &sc) { return rotate_around_y(sc.x, sc.y); }
|
||||
};
|
||||
|
||||
inline vec2::vec2(const vec4 &v) : x(v.x), y(v.y) {}
|
||||
inline vec::vec(const vec4 &v) : x(v.x), y(v.y), z(v.z) {}
|
||||
|
||||
struct vec2
|
||||
{
|
||||
union
|
||||
{
|
||||
struct { float x, y; };
|
||||
float v[2];
|
||||
};
|
||||
|
||||
vec2() {}
|
||||
vec2(float x, float y) : x(x), y(y) {}
|
||||
explicit vec2(const vec &v) : x(v.x), y(v.y) {}
|
||||
explicit vec2(const vec4 &v) : x(v.x), y(v.y) {}
|
||||
|
||||
float &operator[](int i) { return v[i]; }
|
||||
float operator[](int i) const { return v[i]; }
|
||||
|
||||
bool operator==(const vec2 &o) const { return x == o.x && y == o.y; }
|
||||
bool operator!=(const vec2 &o) const { return x != o.x || y != o.y; }
|
||||
|
||||
bool iszero() const { return x==0 && y==0; }
|
||||
float dot(const vec2 &o) const { return x*o.x + y*o.y; }
|
||||
float squaredlen() const { return dot(*this); }
|
||||
float magnitude() const { return sqrtf(squaredlen()); }
|
||||
vec2 &normalize() { mul(1/magnitude()); return *this; }
|
||||
float cross(const vec2 &o) const { return x*o.y - y*o.x; }
|
||||
|
||||
vec2 &mul(float f) { x *= f; y *= f; return *this; }
|
||||
vec2 &mul(const vec2 &o) { x *= o.x; y *= o.y; return *this; }
|
||||
vec2 &div(float f) { x /= f; y /= f; return *this; }
|
||||
vec2 &div(const vec2 &o) { x /= o.x; y /= o.y; return *this; }
|
||||
vec2 &add(float f) { x += f; y += f; return *this; }
|
||||
vec2 &add(const vec2 &o) { x += o.x; y += o.y; return *this; }
|
||||
vec2 &sub(float f) { x -= f; y -= f; return *this; }
|
||||
vec2 &sub(const vec2 &o) { x -= o.x; y -= o.y; return *this; }
|
||||
vec2 &neg() { x = -x; y = -y; return *this; }
|
||||
|
||||
vec2 &lerp(const vec2 &b, float t) { x += (b.x-x)*t; y += (b.y-y)*t; return *this; }
|
||||
vec2 &lerp(const vec2 &a, const vec2 &b, float t) { x = a.x + (b.x-a.x)*t; y = a.y + (b.y-a.y)*t; return *this; }
|
||||
vec2 &avg(const vec2 &b) { add(b); mul(0.5f); return *this; }
|
||||
};
|
||||
|
||||
inline vec::vec(const vec2 &v, float z) : x(v.x), y(v.y), z(z) {}
|
||||
|
||||
static inline bool htcmp(const vec2 &x, const vec2 &y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
static inline uint hthash(const vec2 &k)
|
||||
{
|
||||
union { uint i; float f; } x, y;
|
||||
x.f = k.x; y.f = k.y;
|
||||
uint v = x.i^y.i;
|
||||
return v + (v>>12);
|
||||
}
|
||||
|
||||
struct matrix3x3;
|
||||
struct matrix3x4;
|
||||
|
||||
|
@ -650,11 +659,17 @@ struct matrix3x3
|
|||
vec transform(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
|
||||
vec transposedtransform(const vec &o) const
|
||||
{
|
||||
return vec(a.x*o.x + b.x*o.y + c.x*o.z,
|
||||
a.y*o.x + b.y*o.y + c.y*o.z,
|
||||
a.z*o.x + b.z*o.y + c.z*o.z);
|
||||
return vec(a).mul(o.x).add(vec(b).mul(o.y)).add(vec(c).mul(o.z));
|
||||
}
|
||||
|
||||
vec abstransform(const vec &o) const
|
||||
{
|
||||
return vec(a.absdot(o), b.absdot(o), c.absdot(o));
|
||||
}
|
||||
vec abstransposedtransform(const vec &o) const
|
||||
{
|
||||
return vec(a).mul(o.x).abs().add(vec(b).mul(o.y).abs()).add(vec(c).mul(o.z).abs());
|
||||
}
|
||||
|
||||
void identity()
|
||||
{
|
||||
a = vec(1, 0, 0);
|
||||
|
@ -670,6 +685,7 @@ struct matrix3x3
|
|||
c.rotate_around_x(ck, sk);
|
||||
}
|
||||
void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
|
||||
|
||||
void rotate_around_y(float ck, float sk)
|
||||
{
|
||||
|
@ -679,6 +695,7 @@ struct matrix3x3
|
|||
c.rotate_around_y(ck, sk);
|
||||
}
|
||||
void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
|
||||
|
||||
void rotate_around_z(float ck, float sk)
|
||||
{
|
||||
|
@ -688,8 +705,10 @@ struct matrix3x3
|
|||
c.rotate_around_z(ck, sk);
|
||||
}
|
||||
void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
|
||||
|
||||
vec transform(const vec2 &o) const { return vec(a.x*o.x + a.y*o.y, b.x*o.x + b.y*o.y, c.x*o.y + c.y*o.y); }
|
||||
vec transform(const vec2 &o) const { return vec(a.dot2(o), b.dot2(o), c.dot2(o)); }
|
||||
vec transposedtransform(const vec2 &o) { return vec(a).mul(o.x).add(vec(b).mul(o.y)); }
|
||||
};
|
||||
|
||||
struct matrix3x4
|
||||
|
@ -855,6 +874,7 @@ struct matrix3x4
|
|||
c.rotate_around_x(ck, sk);
|
||||
}
|
||||
void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
|
||||
|
||||
void rotate_around_y(float ck, float sk)
|
||||
{
|
||||
|
@ -864,6 +884,7 @@ struct matrix3x4
|
|||
c.rotate_around_y(ck, sk);
|
||||
}
|
||||
void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
|
||||
|
||||
void rotate_around_z(float ck, float sk)
|
||||
{
|
||||
|
@ -873,6 +894,7 @@ struct matrix3x4
|
|||
c.rotate_around_z(ck, sk);
|
||||
}
|
||||
void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
|
||||
|
||||
vec transform(const vec &o) const { return vec(a.dot(o), b.dot(o), c.dot(o)); }
|
||||
vec transposedtransform(const vec &o) const
|
||||
|
@ -1241,32 +1263,35 @@ struct glmatrix
|
|||
: a(m.a.x, m.b.x, m.c.x, 0), b(m.a.y, m.b.y, m.c.y, 0), c(m.a.z, m.b.z, m.c.z, 0), d(m.a.w, m.b.w, m.c.w, 1)
|
||||
{}
|
||||
|
||||
void rotate_around_x(float angle)
|
||||
void rotate_around_x(float ck, float sk)
|
||||
{
|
||||
float ck = cosf(angle), sk = sinf(angle);
|
||||
vec4 rb = vec4(b).mul(ck).add(vec4(c).mul(sk)),
|
||||
rc = vec4(c).mul(ck).sub(vec4(b).mul(sk));
|
||||
b = rb;
|
||||
c = rc;
|
||||
}
|
||||
void rotate_around_x(float angle) { rotate_around_x(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_x(const vec2 &sc) { rotate_around_x(sc.x, sc.y); }
|
||||
|
||||
void rotate_around_y(float angle)
|
||||
void rotate_around_y(float ck, float sk)
|
||||
{
|
||||
float ck = cosf(angle), sk = sinf(angle);
|
||||
vec4 rc = vec4(c).mul(ck).add(vec4(a).mul(sk)),
|
||||
ra = vec4(a).mul(ck).sub(vec4(c).mul(sk));
|
||||
c = rc;
|
||||
a = ra;
|
||||
}
|
||||
void rotate_around_y(float angle) { rotate_around_y(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_y(const vec2 &sc) { rotate_around_y(sc.x, sc.y); }
|
||||
|
||||
void rotate_around_z(float angle)
|
||||
void rotate_around_z(float ck, float sk)
|
||||
{
|
||||
float ck = cosf(angle), sk = sinf(angle);
|
||||
vec4 ra = vec4(a).mul(ck).add(vec4(b).mul(sk)),
|
||||
rb = vec4(b).mul(ck).sub(vec4(a).mul(sk));
|
||||
a = ra;
|
||||
b = rb;
|
||||
}
|
||||
void rotate_around_z(float angle) { rotate_around_z(cosf(angle), sinf(angle)); }
|
||||
void rotate_around_z(const vec2 &sc) { rotate_around_z(sc.x, sc.y); }
|
||||
|
||||
void rotate(float ck, float sk, const vec &dir)
|
||||
{
|
||||
|
@ -1281,11 +1306,8 @@ struct glmatrix
|
|||
c = rc;
|
||||
}
|
||||
|
||||
void rotate(float angle, const vec &dir)
|
||||
{
|
||||
float ck = cosf(angle), sk = sinf(angle);
|
||||
rotate(ck, sk, dir);
|
||||
}
|
||||
void rotate(float angle, const vec &dir) { rotate(cosf(angle), sinf(angle), dir); }
|
||||
void rotate(const vec2 &sc, const vec &dir) { rotate(sc.x, sc.y, dir); }
|
||||
|
||||
void mul(const glmatrix &x, const glmatrix &y)
|
||||
{
|
||||
|
@ -1535,3 +1557,12 @@ extern bool linecylinderintersect(const vec &from, const vec &to, const vec &sta
|
|||
|
||||
extern const vec2 sincos360[];
|
||||
|
||||
static inline int mod360(int angle)
|
||||
{
|
||||
if(angle < 0) angle = 360 + (angle <= -360 ? angle%360 : angle);
|
||||
else if(angle >= 360) angle %= 360;
|
||||
return angle;
|
||||
}
|
||||
|
||||
static inline const vec2 &sincosmod360(int angle) { return sincos360[mod360(angle)]; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue