mapmodel pitch and scale

master
lsalzman 2013-05-14 10:09:32 +03:00
parent f19755574b
commit 104a988a4b
7 changed files with 68 additions and 28 deletions

View File

@ -275,9 +275,11 @@ bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist
else if((mode&RAY_ENTS)!=RAY_ENTS && (!m->collide || e.flags&extentity::F_NOCOLLIDE)) return false;
if(!m->bih && !m->setBIH()) return false;
vec mo = vec(o).sub(e.o), mray(ray);
int scale = e.attr4;
if(scale > 0) mo.mul(100.0f/scale);
float v = mo.dot(mray), inside = m->bih->radius - mo.squaredlen();
if((inside < 0 && v > 0) || inside + v*v < 0) return false;
int yaw = e.attr1;
int yaw = e.attr1, pitch = e.attr3;
if(yaw != 0)
{
if(yaw < 0) yaw = 360 + yaw%360;
@ -286,6 +288,19 @@ bool mmintersect(const extentity &e, const vec &o, const vec &ray, float maxdist
mo.rotate_around_z(rot.x, -rot.y);
mray.rotate_around_z(rot.x, -rot.y);
}
return m->bih->traverse(mo, mray, maxdist ? maxdist : 1e16f, dist, mode);
if(pitch != 0)
{
if(pitch < 0) pitch = 360 + pitch%360;
else if(pitch >= 360) pitch %= 360;
const vec2 &rot = sincos360[pitch];
mo.rotate_around_y(rot.x, rot.y);
mray.rotate_around_y(rot.x, rot.y);
}
if(m->bih->traverse(mo, mray, maxdist ? maxdist : 1e16f, dist, mode))
{
if(scale > 0) dist *= scale/100.0f;
return true;
}
return false;
}

View File

@ -608,7 +608,7 @@ extern void clearchanges(int type);
extern void mousemove(int dx, int dy);
extern bool pointincube(const clipplanes &p, const vec &v);
extern bool overlapsdynent(const vec &o, float radius);
extern void rotatebb(vec &center, vec &radius, int yaw);
extern void rotatebb(vec &center, vec &radius, int yaw, int pitch);
extern float shadowray(const vec &o, const vec &ray, float radius, int mode, extentity *t = NULL);
struct ShadowRayCache;
extern ShadowRayCache *newshadowraycache();

View File

@ -197,8 +197,9 @@ namespace mpr
vec o, radius;
quat orient;
ModelOBB(const vec &ent, const vec &center, const vec &radius, float yaw) : o(ent), radius(radius), orient(vec(0, 0, 1), yaw*RAD)
ModelOBB(const vec &ent, const vec &center, const vec &radius, float yaw, float pitch) : o(ent), radius(radius), orient(vec(0, 0, 1), yaw*RAD)
{
if(pitch) orient.mul(quat(vec(0, 1, 0), pitch*RAD), quat(orient));
o.add(orient.rotate(center));
}
@ -237,8 +238,9 @@ namespace mpr
vec o, radius;
quat orient;
ModelEllipse(const vec &ent, const vec &center, const vec &radius, float yaw) : o(ent), radius(radius), orient(vec(0, 0, 1), yaw*RAD)
ModelEllipse(const vec &ent, const vec &center, const vec &radius, float yaw, float pitch) : o(ent), radius(radius), orient(vec(0, 0, 1), yaw*RAD)
{
if(pitch) orient.mul(quat(vec(0, 1, 0), pitch*RAD), quat(orient));
o.add(orient.rotate(center));
}

View File

@ -715,23 +715,37 @@ bool plcollide(physent *d, const vec &dir) // collide with player or monster
return true;
}
void rotatebb(vec &center, vec &radius, int yaw)
void rotatebb(vec &center, vec &radius, int yaw, int pitch)
{
if(yaw < 0) yaw = 360 + yaw%360;
else if(yaw >= 360) yaw %= 360;
const vec2 &rot = sincos360[yaw];
vec2 oldcenter(center), oldradius(radius);
center.x = oldcenter.x*rot.x - oldcenter.y*rot.y;
center.y = oldcenter.y*rot.x + oldcenter.x*rot.y;
radius.x = fabs(oldradius.x*rot.x) + fabs(oldradius.y*rot.y);
radius.y = 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];
vec2 oldcenter(center.x, center.z), oldradius(radius.x, radius.z);
center.x = oldcenter.x*rot.x - oldcenter.y*rot.y;
center.z = oldcenter.y*rot.x + oldcenter.x*rot.y;
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(yaw)
{
if(yaw < 0) yaw = 360 + yaw%360;
else if(yaw >= 360) yaw %= 360;
const vec2 &rot = sincos360[yaw];
vec2 oldcenter(center), oldradius(radius);
center.x = oldcenter.x*rot.x - oldcenter.y*rot.y;
center.y = oldcenter.y*rot.x + oldcenter.x*rot.y;
radius.x = fabs(oldradius.x*rot.x) + fabs(oldradius.y*rot.y);
radius.y = fabs(oldradius.y*rot.x) + fabs(oldradius.x*rot.y);
}
}
template<class E, class M>
static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, const vec &center, const vec &radius, float yaw)
static inline bool mmcollide(physent *d, const vec &dir, const extentity &e, const vec &center, const vec &radius, float yaw, float pitch)
{
E entvol(d);
M mdlvol(e.o, center, radius, yaw);
M mdlvol(e.o, center, radius, yaw, pitch);
vec cp;
if(mpr::collide(entvol, mdlvol, NULL, NULL, &cp))
{
@ -754,28 +768,30 @@ bool mmcollide(physent *d, const vec &dir, octaentities &oc) // co
if(!m || !m->collide) continue;
vec center, radius;
m->collisionbox(center, radius);
float yaw = e.attr1;
if(e.attr4 > 0) { float scale = e.attr4/100.f; center.mul(scale); radius.mul(scale); }
float yaw = e.attr1, pitch = e.attr3;
switch(d->collidetype)
{
case COLLIDE_ELLIPSE:
if(pitch) rotatebb(center, radius, 0, pitch);
if(m->ellipsecollide)
{
//if(!mmcollide<mpr::EntCylinder, mpr::ModelEllipse>(d, dir, e, center, radius, yaw)) return false;
//if(!mmcollide<mpr::EntCylinder, mpr::ModelEllipse>(d, dir, e, center, radius, yaw, pitch)) return false;
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)) return false;
//else if(!mmcollide<mpr::EntCylinder, mpr::ModelOBB>(d, dir, e, center, radius, yaw, pitch)) return false;
else if(!ellipserectcollide(d, dir, e.o, center, yaw, radius.x, radius.y, radius.z, radius.z)) return false;
break;
case COLLIDE_OBB:
if(m->ellipsecollide)
{
if(!mmcollide<mpr::EntOBB, mpr::ModelEllipse>(d, dir, e, center, radius, yaw)) return false;
if(!mmcollide<mpr::EntOBB, mpr::ModelEllipse>(d, dir, e, center, radius, yaw, pitch)) return false;
}
else if(!mmcollide<mpr::EntOBB, mpr::ModelOBB>(d, dir, e, center, radius, yaw)) return false;
else if(!mmcollide<mpr::EntOBB, mpr::ModelOBB>(d, dir, e, center, radius, yaw, pitch)) return false;
break;
case COLLIDE_AABB:
default:
rotatebb(center, radius, e.attr1);
rotatebb(center, radius, e.attr1, e.attr3);
if(!rectcollide(d, dir, center.add(e.o), radius.x, radius.y, radius.z, radius.z)) return false;
break;
}

View File

@ -1157,7 +1157,7 @@ void setbbfrommodel(dynent *d, const char *mdl)
{
d->collidetype = COLLIDE_OBB;
//d->collidetype = COLLIDE_AABB;
//rotatebb(center, radius, int(d->yaw));
//rotatebb(center, radius, int(d->yaw), int(d->pitch));
}
d->xradius = radius.x + fabs(center.x);
d->yradius = radius.y + fabs(center.y);

View File

@ -407,7 +407,7 @@ static inline void rendermapmodel(extentity &e)
{
int anim = ANIM_MAPMODEL|ANIM_LOOP, basetime = 0;
if(e.flags&extentity::F_ANIM) entities::animatemapmodel(e, anim, basetime);
rendermapmodel(e.attr2, anim, e.o, e.attr1, 0, MDL_CULL_VFC | MDL_CULL_DIST, basetime);
rendermapmodel(e.attr2, anim, e.o, e.attr1, e.attr3, MDL_CULL_VFC | MDL_CULL_DIST, basetime, e.attr4 > 0 ? e.attr4/100.0f : 1.0f);
}
void rendermapmodels()

View File

@ -23,8 +23,13 @@ bool getentboundingbox(extentity &e, ivec &o, ivec &r)
{
vec center, radius;
m->boundbox(center, radius);
rotatebb(center, radius, e.attr1);
if(e.attr4 > 0)
{
float scale = e.attr4/100.0f;
center.mul(scale);
radius.mul(scale);
}
rotatebb(center, radius, e.attr1, e.attr3);
o = e.o;
o.add(center);
r = radius;
@ -477,7 +482,8 @@ void entselectionbox(const entity &e, vec &eo, vec &es)
else if(e.type == ET_MAPMODEL && (m = loadmodel(NULL, e.attr2)))
{
m->collisionbox(eo, es);
rotatebb(eo, es, e.attr1);
if(e.attr4 > 0) { float scale = e.attr4/100.0f; eo.mul(scale); es.mul(scale); }
rotatebb(eo, es, e.attr1, e.attr3);
#if 0
if(m->collide)
eo.z -= player->aboveeye; // wacky but true. see physics collide
@ -811,7 +817,8 @@ bool dropentity(entity &e, int drop = -1)
{
vec center;
m->boundbox(center, radius);
rotatebb(center, radius, e.attr1);
if(e.attr4 > 0) { float scale = e.attr4/100.0f; center.mul(scale); radius.mul(scale); }
rotatebb(center, radius, e.attr1, e.attr3);
radius.x += fabs(center.x);
radius.y += fabs(center.y);
}