summaryrefslogtreecommitdiff
path: root/src/engine/rendermodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/rendermodel.cpp')
-rw-r--r--src/engine/rendermodel.cpp1434
1 files changed, 717 insertions, 717 deletions
diff --git a/src/engine/rendermodel.cpp b/src/engine/rendermodel.cpp
index c8a7eb6..5c8a219 100644
--- a/src/engine/rendermodel.cpp
+++ b/src/engine/rendermodel.cpp
@@ -14,14 +14,14 @@ static model *(__cdecl *modeltypes[NUMMODELTYPES])(const char *);
static int addmodeltype(int type, model *(__cdecl *loader)(const char *))
{
- modeltypes[type] = loader;
- return type;
+ modeltypes[type] = loader;
+ return type;
}
#define MODELTYPE(modeltype, modelclass) \
static model *__loadmodel__##modelclass(const char *filename) \
{ \
- return new modelclass(filename); \
+ return new modelclass(filename); \
} \
UNUSED static int __dummy__##modelclass = addmodeltype((modeltype), __loadmodel__##modelclass);
@@ -37,281 +37,281 @@ MODELTYPE(MDL_IQM, iqm);
void mdlcullface(int *cullface)
{
- checkmdl;
- loadingmodel->setcullface(*cullface!=0);
+ checkmdl;
+ loadingmodel->setcullface(*cullface!=0);
}
COMMAND(mdlcullface, "i");
void mdlcollide(int *collide)
{
- checkmdl;
- loadingmodel->collide = *collide!=0;
+ checkmdl;
+ loadingmodel->collide = *collide!=0;
}
COMMAND(mdlcollide, "i");
void mdlellipsecollide(int *collide)
{
- checkmdl;
- loadingmodel->ellipsecollide = *collide!=0;
+ checkmdl;
+ loadingmodel->ellipsecollide = *collide!=0;
}
COMMAND(mdlellipsecollide, "i");
void mdlspec(int *percent)
{
- checkmdl;
- float spec = 1.0f;
- if(*percent>0) spec = *percent/100.0f;
- else if(*percent<0) spec = 0.0f;
- loadingmodel->setspec(spec);
+ checkmdl;
+ float spec = 1.0f;
+ if(*percent>0) spec = *percent/100.0f;
+ else if(*percent<0) spec = 0.0f;
+ loadingmodel->setspec(spec);
}
COMMAND(mdlspec, "i");
void mdlambient(int *percent)
{
- checkmdl;
- float ambient = 0.3f;
- if(*percent>0) ambient = *percent/100.0f;
- else if(*percent<0) ambient = 0.0f;
- loadingmodel->setambient(ambient);
+ checkmdl;
+ float ambient = 0.3f;
+ if(*percent>0) ambient = *percent/100.0f;
+ else if(*percent<0) ambient = 0.0f;
+ loadingmodel->setambient(ambient);
}
COMMAND(mdlambient, "i");
void mdlalphatest(float *cutoff)
{
- checkmdl;
- loadingmodel->setalphatest(max(0.0f, min(1.0f, *cutoff)));
+ checkmdl;
+ loadingmodel->setalphatest(max(0.0f, min(1.0f, *cutoff)));
}
COMMAND(mdlalphatest, "f");
void mdlalphablend(int *blend)
{
- checkmdl;
- loadingmodel->setalphablend(*blend!=0);
+ checkmdl;
+ loadingmodel->setalphablend(*blend!=0);
}
COMMAND(mdlalphablend, "i");
void mdlalphadepth(int *depth)
{
- checkmdl;
- loadingmodel->alphadepth = *depth!=0;
+ checkmdl;
+ loadingmodel->alphadepth = *depth!=0;
}
COMMAND(mdlalphadepth, "i");
void mdldepthoffset(int *offset)
{
- checkmdl;
- loadingmodel->depthoffset = *offset!=0;
+ checkmdl;
+ loadingmodel->depthoffset = *offset!=0;
}
COMMAND(mdldepthoffset, "i");
void mdlglow(int *percent, int *delta, float *pulse)
{
- checkmdl;
- float glow = 3.0f, glowdelta = *delta/100.0f, glowpulse = *pulse > 0 ? *pulse/1000.0f : 0;
- if(*percent>0) glow = *percent/100.0f;
- else if(*percent<0) glow = 0.0f;
- glowdelta -= glow;
- loadingmodel->setglow(glow, glowdelta, glowpulse);
+ checkmdl;
+ float glow = 3.0f, glowdelta = *delta/100.0f, glowpulse = *pulse > 0 ? *pulse/1000.0f : 0;
+ if(*percent>0) glow = *percent/100.0f;
+ else if(*percent<0) glow = 0.0f;
+ glowdelta -= glow;
+ loadingmodel->setglow(glow, glowdelta, glowpulse);
}
COMMAND(mdlglow, "iif");
void mdlglare(float *specglare, float *glowglare)
{
- checkmdl;
- loadingmodel->setglare(*specglare, *glowglare);
+ checkmdl;
+ loadingmodel->setglare(*specglare, *glowglare);
}
COMMAND(mdlglare, "ff");
void mdlenvmap(float *envmapmax, float *envmapmin, char *envmap)
{
- checkmdl;
- loadingmodel->setenvmap(*envmapmin, *envmapmax, envmap[0] ? cubemapload(envmap) : NULL);
+ checkmdl;
+ loadingmodel->setenvmap(*envmapmin, *envmapmax, envmap[0] ? cubemapload(envmap) : NULL);
}
COMMAND(mdlenvmap, "ffs");
void mdlfullbright(float *fullbright)
{
- checkmdl;
- loadingmodel->setfullbright(*fullbright);
+ checkmdl;
+ loadingmodel->setfullbright(*fullbright);
}
COMMAND(mdlfullbright, "f");
void mdlshader(char *shader)
{
- checkmdl;
- loadingmodel->setshader(lookupshaderbyname(shader));
+ checkmdl;
+ loadingmodel->setshader(lookupshaderbyname(shader));
}
COMMAND(mdlshader, "s");
void mdlspin(float *yaw, float *pitch)
{
- checkmdl;
- loadingmodel->spinyaw = *yaw;
- loadingmodel->spinpitch = *pitch;
+ checkmdl;
+ loadingmodel->spinyaw = *yaw;
+ loadingmodel->spinpitch = *pitch;
}
COMMAND(mdlspin, "ff");
void mdlscale(int *percent)
{
- checkmdl;
- float scale = 1.0f;
- if(*percent>0) scale = *percent/100.0f;
- loadingmodel->scale = scale;
+ checkmdl;
+ float scale = 1.0f;
+ if(*percent>0) scale = *percent/100.0f;
+ loadingmodel->scale = scale;
}
COMMAND(mdlscale, "i");
void mdltrans(float *x, float *y, float *z)
{
- checkmdl;
- loadingmodel->translate = vec(*x, *y, *z);
+ checkmdl;
+ loadingmodel->translate = vec(*x, *y, *z);
}
COMMAND(mdltrans, "fff");
void mdlyaw(float *angle)
{
- checkmdl;
- loadingmodel->offsetyaw = *angle;
+ checkmdl;
+ loadingmodel->offsetyaw = *angle;
}
COMMAND(mdlyaw, "f");
void mdlpitch(float *angle)
{
- checkmdl;
- loadingmodel->offsetpitch = *angle;
+ checkmdl;
+ loadingmodel->offsetpitch = *angle;
}
COMMAND(mdlpitch, "f");
void mdlshadow(int *shadow)
{
- checkmdl;
- loadingmodel->shadow = *shadow!=0;
+ checkmdl;
+ loadingmodel->shadow = *shadow!=0;
}
COMMAND(mdlshadow, "i");
void mdlbb(float *rad, float *h, float *eyeheight)
{
- checkmdl;
- loadingmodel->collidexyradius = *rad;
- loadingmodel->collideheight = *h;
- loadingmodel->eyeheight = *eyeheight;
+ checkmdl;
+ loadingmodel->collidexyradius = *rad;
+ loadingmodel->collideheight = *h;
+ loadingmodel->eyeheight = *eyeheight;
}
COMMAND(mdlbb, "fff");
void mdlextendbb(float *x, float *y, float *z)
{
- checkmdl;
- loadingmodel->bbextend = vec(*x, *y, *z);
+ checkmdl;
+ loadingmodel->bbextend = vec(*x, *y, *z);
}
COMMAND(mdlextendbb, "fff");
void mdlname()
{
- checkmdl;
- result(loadingmodel->name);
+ checkmdl;
+ result(loadingmodel->name);
}
COMMAND(mdlname, "");
#define checkragdoll \
- checkmdl; \
- if(!loadingmodel->skeletal()) { conoutf(CON_ERROR, "not loading a skeletal model"); return; } \
- skelmodel *m = (skelmodel *)loadingmodel; \
- if(m->parts.empty()) return; \
- skelmodel::skelmeshgroup *meshes = (skelmodel::skelmeshgroup *)m->parts.last()->meshes; \
- if(!meshes) return; \
- skelmodel::skeleton *skel = meshes->skel; \
- if(!skel->ragdoll) skel->ragdoll = new ragdollskel; \
- ragdollskel *ragdoll = skel->ragdoll; \
- if(ragdoll->loaded) return;
+ checkmdl; \
+ if(!loadingmodel->skeletal()) { conoutf(CON_ERROR, "not loading a skeletal model"); return; } \
+ skelmodel *m = (skelmodel *)loadingmodel; \
+ if(m->parts.empty()) return; \
+ skelmodel::skelmeshgroup *meshes = (skelmodel::skelmeshgroup *)m->parts.last()->meshes; \
+ if(!meshes) return; \
+ skelmodel::skeleton *skel = meshes->skel; \
+ if(!skel->ragdoll) skel->ragdoll = new ragdollskel; \
+ ragdollskel *ragdoll = skel->ragdoll; \
+ if(ragdoll->loaded) return;
void rdvert(float *x, float *y, float *z, float *radius)
{
- checkragdoll;
- ragdollskel::vert &v = ragdoll->verts.add();
- v.pos = vec(*x, *y, *z);
- v.radius = *radius > 0 ? *radius : 1;
+ checkragdoll;
+ ragdollskel::vert &v = ragdoll->verts.add();
+ v.pos = vec(*x, *y, *z);
+ v.radius = *radius > 0 ? *radius : 1;
}
COMMAND(rdvert, "ffff");
void rdeye(int *v)
{
- checkragdoll;
- ragdoll->eye = *v;
+ checkragdoll;
+ ragdoll->eye = *v;
}
COMMAND(rdeye, "i");
void rdtri(int *v1, int *v2, int *v3)
{
- checkragdoll;
- ragdollskel::tri &t = ragdoll->tris.add();
- t.vert[0] = *v1;
- t.vert[1] = *v2;
- t.vert[2] = *v3;
+ checkragdoll;
+ ragdollskel::tri &t = ragdoll->tris.add();
+ t.vert[0] = *v1;
+ t.vert[1] = *v2;
+ t.vert[2] = *v3;
}
COMMAND(rdtri, "iii");
void rdjoint(int *n, int *t, int *v1, int *v2, int *v3)
{
- checkragdoll;
- if(*n < 0 || *n >= skel->numbones) return;
- ragdollskel::joint &j = ragdoll->joints.add();
- j.bone = *n;
- j.tri = *t;
- j.vert[0] = *v1;
- j.vert[1] = *v2;
- j.vert[2] = *v3;
+ checkragdoll;
+ if(*n < 0 || *n >= skel->numbones) return;
+ ragdollskel::joint &j = ragdoll->joints.add();
+ j.bone = *n;
+ j.tri = *t;
+ j.vert[0] = *v1;
+ j.vert[1] = *v2;
+ j.vert[2] = *v3;
}
COMMAND(rdjoint, "iibbb");
void rdlimitdist(int *v1, int *v2, float *mindist, float *maxdist)
{
- checkragdoll;
- ragdollskel::distlimit &d = ragdoll->distlimits.add();
- d.vert[0] = *v1;
- d.vert[1] = *v2;
- d.mindist = *mindist;
- d.maxdist = max(*maxdist, *mindist);
+ checkragdoll;
+ ragdollskel::distlimit &d = ragdoll->distlimits.add();
+ d.vert[0] = *v1;
+ d.vert[1] = *v2;
+ d.mindist = *mindist;
+ d.maxdist = max(*maxdist, *mindist);
}
COMMAND(rdlimitdist, "iiff");
void rdlimitrot(int *t1, int *t2, float *maxangle, float *qx, float *qy, float *qz, float *qw)
{
- checkragdoll;
- ragdollskel::rotlimit &r = ragdoll->rotlimits.add();
- r.tri[0] = *t1;
- r.tri[1] = *t2;
- r.maxangle = *maxangle * RAD;
- r.middle = matrix3(quat(*qx, *qy, *qz, *qw));
+ checkragdoll;
+ ragdollskel::rotlimit &r = ragdoll->rotlimits.add();
+ r.tri[0] = *t1;
+ r.tri[1] = *t2;
+ r.maxangle = *maxangle * RAD;
+ r.middle = matrix3(quat(*qx, *qy, *qz, *qw));
}
COMMAND(rdlimitrot, "iifffff");
void rdanimjoints(int *on)
{
- checkragdoll;
- ragdoll->animjoints = *on!=0;
+ checkragdoll;
+ ragdoll->animjoints = *on!=0;
}
COMMAND(rdanimjoints, "i");
@@ -321,20 +321,20 @@ vector<mapmodelinfo> mapmodels;
void mmodel(char *name)
{
- mapmodelinfo &mmi = mapmodels.add();
- copystring(mmi.name, name);
- mmi.m = NULL;
+ mapmodelinfo &mmi = mapmodels.add();
+ copystring(mmi.name, name);
+ mmi.m = NULL;
}
void mapmodelcompat(int *rad, int *h, int *tex, char *name, char *shadow)
{
- mmodel(name);
+ mmodel(name);
}
void mapmodelreset(int *n)
{
- if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return;
- mapmodels.shrink(clamp(*n, 0, mapmodels.length()));
+ if(!(identflags&IDF_OVERRIDDEN) && !game::allowedittoggle()) return;
+ mapmodels.shrink(clamp(*n, 0, mapmodels.length()));
}
mapmodelinfo *getmminfo(int i) { return mapmodels.inrange(i) ? &mapmodels[i] : 0; }
@@ -355,185 +355,185 @@ vector<const char *> preloadmodels;
void preloadmodel(const char *name)
{
- if(!name || !name[0] || models.access(name)) return;
- preloadmodels.add(newstring(name));
+ if(!name || !name[0] || models.access(name)) return;
+ preloadmodels.add(newstring(name));
}
void flushpreloadedmodels(bool msg)
{
- loopv(preloadmodels)
- {
- loadprogress = float(i+1)/preloadmodels.length();
- model *m = loadmodel(preloadmodels[i], -1, msg);
- if(!m) { if(msg) conoutf(CON_WARN, "could not load model: %s", preloadmodels[i]); }
- else
- {
- m->preloadmeshes();
- }
- }
- preloadmodels.deletearrays();
- loadprogress = 0;
+ loopv(preloadmodels)
+ {
+ loadprogress = float(i+1)/preloadmodels.length();
+ model *m = loadmodel(preloadmodels[i], -1, msg);
+ if(!m) { if(msg) conoutf(CON_WARN, "could not load model: %s", preloadmodels[i]); }
+ else
+ {
+ m->preloadmeshes();
+ }
+ }
+ preloadmodels.deletearrays();
+ loadprogress = 0;
}
void preloadusedmapmodels(bool msg, bool bih)
{
- vector<extentity *> &ents = entities::getents();
- vector<int> mapmodels;
- loopv(ents)
- {
- extentity &e = *ents[i];
- if(e.type==ET_MAPMODEL && e.attr2 >= 0 && mapmodels.find(e.attr2) < 0) mapmodels.add(e.attr2);
- }
-
- loopv(mapmodels)
- {
- loadprogress = float(i+1)/mapmodels.length();
- int mmindex = mapmodels[i];
- mapmodelinfo *mmi = getmminfo(mmindex);
- if(!mmi) { if(msg) conoutf(CON_WARN, "could not find map model: %d", mmindex); }
- else if(mmi->name[0] && !loadmodel(NULL, mmindex, msg)) { if(msg) conoutf(CON_WARN, "could not load model: %s", mmi->name); }
- else if(mmi->m)
- {
- if(bih) mmi->m->preloadBIH();
- mmi->m->preloadmeshes();
- }
- }
- loadprogress = 0;
+ vector<extentity *> &ents = entities::getents();
+ vector<int> mapmodels;
+ loopv(ents)
+ {
+ extentity &e = *ents[i];
+ if(e.type==ET_MAPMODEL && e.attr2 >= 0 && mapmodels.find(e.attr2) < 0) mapmodels.add(e.attr2);
+ }
+
+ loopv(mapmodels)
+ {
+ loadprogress = float(i+1)/mapmodels.length();
+ int mmindex = mapmodels[i];
+ mapmodelinfo *mmi = getmminfo(mmindex);
+ if(!mmi) { if(msg) conoutf(CON_WARN, "could not find map model: %d", mmindex); }
+ else if(mmi->name[0] && !loadmodel(NULL, mmindex, msg)) { if(msg) conoutf(CON_WARN, "could not load model: %s", mmi->name); }
+ else if(mmi->m)
+ {
+ if(bih) mmi->m->preloadBIH();
+ mmi->m->preloadmeshes();
+ }
+ }
+ loadprogress = 0;
}
bool modelloaded(const char *name)
{
- return models.find(name, NULL) != NULL;
+ return models.find(name, NULL) != NULL;
}
model *loadmodel(const char *name, int i, bool msg)
{
- if(!name)
- {
- if(!mapmodels.inrange(i)) return NULL;
- mapmodelinfo &mmi = mapmodels[i];
- if(mmi.m) return mmi.m;
- name = mmi.name;
- }
- model **mm = models.access(name);
- model *m;
- if(mm) m = *mm;
- else
- {
- if(!name[0] || loadingmodel || lightmapping > 1) return NULL;
- if(msg)
- {
- defformatstring(filename, "packages/models/%s", name);
- renderprogress(loadprogress, filename);
- }
- loopi(NUMMODELTYPES)
- {
- m = modeltypes[i](name);
- if(!m) continue;
- loadingmodel = m;
- if(m->load()) break;
- DELETEP(m);
- }
- loadingmodel = NULL;
- if(!m) return NULL;
- models.access(m->name, m);
- m->preloadshaders();
- }
- if(mapmodels.inrange(i) && !mapmodels[i].m) mapmodels[i].m = m;
- return m;
+ if(!name)
+ {
+ if(!mapmodels.inrange(i)) return NULL;
+ mapmodelinfo &mmi = mapmodels[i];
+ if(mmi.m) return mmi.m;
+ name = mmi.name;
+ }
+ model **mm = models.access(name);
+ model *m;
+ if(mm) m = *mm;
+ else
+ {
+ if(!name[0] || loadingmodel || lightmapping > 1) return NULL;
+ if(msg)
+ {
+ defformatstring(filename, "packages/models/%s", name);
+ renderprogress(loadprogress, filename);
+ }
+ loopi(NUMMODELTYPES)
+ {
+ m = modeltypes[i](name);
+ if(!m) continue;
+ loadingmodel = m;
+ if(m->load()) break;
+ DELETEP(m);
+ }
+ loadingmodel = NULL;
+ if(!m) return NULL;
+ models.access(m->name, m);
+ m->preloadshaders();
+ }
+ if(mapmodels.inrange(i) && !mapmodels[i].m) mapmodels[i].m = m;
+ return m;
}
void preloadmodelshaders(bool force)
{
- if(initing) return;
- enumerate(models, model *, m, m->preloadshaders(force));
+ if(initing) return;
+ enumerate(models, model *, m, m->preloadshaders(force));
}
void clear_mdls()
{
- enumerate(models, model *, m, delete m);
+ enumerate(models, model *, m, delete m);
}
void cleanupmodels()
{
- enumerate(models, model *, m, m->cleanup());
+ enumerate(models, model *, m, m->cleanup());
}
void clearmodel(char *name)
{
- model **m = models.access(name);
- if(!m) { conoutf(CON_WARN, "model %s is not loaded", name); return; }
- loopv(mapmodels) if(mapmodels[i].m==*m) mapmodels[i].m = NULL;
- models.remove(name);
- (*m)->cleanup();
- delete *m;
- conoutf("cleared model %s", name);
+ model **m = models.access(name);
+ if(!m) { conoutf(CON_WARN, "model %s is not loaded", name); return; }
+ loopv(mapmodels) if(mapmodels[i].m==*m) mapmodels[i].m = NULL;
+ models.remove(name);
+ (*m)->cleanup();
+ delete *m;
+ conoutf("cleared model %s", name);
}
COMMAND(clearmodel, "s");
bool modeloccluded(const vec &center, float radius)
{
- ivec bbmin(vec(center).sub(radius)), bbmax(ivec(center).add(radius+1));
- return bboccluded(bbmin, bbmax);
+ ivec bbmin(vec(center).sub(radius)), bbmax(ivec(center).add(radius+1));
+ return bboccluded(bbmin, bbmax);
}
VAR(showboundingbox, 0, 0, 2);
void render2dbox(vec &o, float x, float y, float z)
{
- gle::begin(GL_LINE_LOOP);
- gle::attribf(o.x, o.y, o.z);
- gle::attribf(o.x, o.y, o.z+z);
- gle::attribf(o.x+x, o.y+y, o.z+z);
- gle::attribf(o.x+x, o.y+y, o.z);
- xtraverts += gle::end();
+ gle::begin(GL_LINE_LOOP);
+ gle::attribf(o.x, o.y, o.z);
+ gle::attribf(o.x, o.y, o.z+z);
+ gle::attribf(o.x+x, o.y+y, o.z+z);
+ gle::attribf(o.x+x, o.y+y, o.z);
+ xtraverts += gle::end();
}
void render3dbox(vec &o, float tofloor, float toceil, float xradius, float yradius)
{
- if(yradius<=0) yradius = xradius;
- vec c = o;
- c.sub(vec(xradius, yradius, tofloor));
- float xsz = xradius*2, ysz = yradius*2;
- float h = tofloor+toceil;
- gle::colorf(1, 1, 1);
- gle::defvertex();
- render2dbox(c, xsz, 0, h);
- render2dbox(c, 0, ysz, h);
- c.add(vec(xsz, ysz, 0));
- render2dbox(c, -xsz, 0, h);
- render2dbox(c, 0, -ysz, h);
+ if(yradius<=0) yradius = xradius;
+ vec c = o;
+ c.sub(vec(xradius, yradius, tofloor));
+ float xsz = xradius*2, ysz = yradius*2;
+ float h = tofloor+toceil;
+ gle::colorf(1, 1, 1);
+ gle::defvertex();
+ render2dbox(c, xsz, 0, h);
+ render2dbox(c, 0, ysz, h);
+ c.add(vec(xsz, ysz, 0));
+ render2dbox(c, -xsz, 0, h);
+ render2dbox(c, 0, -ysz, h);
}
void renderellipse(vec &o, float xradius, float yradius, float yaw)
{
- gle::colorf(0.5f, 0.5f, 0.5f);
- gle::defvertex();
- gle::begin(GL_LINE_LOOP);
- loopi(15)
- {
- const vec2 &sc = sincos360[i*(360/15)];
- gle::attrib(vec(xradius*sc.x, yradius*sc.y, 0).rotate_around_z((yaw+90)*RAD).add(o));
- }
- xtraverts += gle::end();
+ gle::colorf(0.5f, 0.5f, 0.5f);
+ gle::defvertex();
+ gle::begin(GL_LINE_LOOP);
+ loopi(15)
+ {
+ const vec2 &sc = sincos360[i*(360/15)];
+ gle::attrib(vec(xradius*sc.x, yradius*sc.y, 0).rotate_around_z((yaw+90)*RAD).add(o));
+ }
+ xtraverts += gle::end();
}
struct batchedmodel
{
- vec pos, color, dir;
- int anim;
- float yaw, pitch, transparent;
- int basetime, basetime2, flags;
- dynent *d;
- int attached;
- occludequery *query;
+ vec pos, color, dir;
+ int anim;
+ float yaw, pitch, transparent;
+ int basetime, basetime2, flags;
+ dynent *d;
+ int attached;
+ occludequery *query;
};
struct modelbatch
{
- model *m;
- int flags;
- vector<batchedmodel> batched;
+ model *m;
+ int flags;
+ vector<batchedmodel> batched;
};
static vector<modelbatch *> batches;
static vector<modelattach> modelattached;
@@ -542,487 +542,487 @@ static occludequery *modelquery = NULL;
void startmodelbatches()
{
- numbatches = 0;
- modelattached.setsize(0);
+ numbatches = 0;
+ modelattached.setsize(0);
}
modelbatch &addbatchedmodel(model *m)
{
- modelbatch *b = NULL;
- if(m->batch>=0 && m->batch<numbatches && batches[m->batch]->m==m) b = batches[m->batch];
- else
- {
- if(numbatches<batches.length())
- {
- b = batches[numbatches];
- b->batched.setsize(0);
- }
- else b = batches.add(new modelbatch);
- b->m = m;
- b->flags = 0;
- m->batch = numbatches++;
- }
- return *b;
+ modelbatch *b = NULL;
+ if(m->batch>=0 && m->batch<numbatches && batches[m->batch]->m==m) b = batches[m->batch];
+ else
+ {
+ if(numbatches<batches.length())
+ {
+ b = batches[numbatches];
+ b->batched.setsize(0);
+ }
+ else b = batches.add(new modelbatch);
+ b->m = m;
+ b->flags = 0;
+ m->batch = numbatches++;
+ }
+ return *b;
}
void renderbatchedmodel(model *m, batchedmodel &b)
{
- modelattach *a = NULL;
- if(b.attached>=0) a = &modelattached[b.attached];
+ modelattach *a = NULL;
+ if(b.attached>=0) a = &modelattached[b.attached];
- int anim = b.anim;
- if(shadowmapping)
- {
- anim |= ANIM_NOSKIN;
- GLOBALPARAMF(shadowintensity, b.transparent);
- }
- else
- {
- if(b.flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT;
- if(b.flags&MDL_GHOST) anim |= ANIM_GHOST;
- }
+ int anim = b.anim;
+ if(shadowmapping)
+ {
+ anim |= ANIM_NOSKIN;
+ GLOBALPARAMF(shadowintensity, b.transparent);
+ }
+ else
+ {
+ if(b.flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT;
+ if(b.flags&MDL_GHOST) anim |= ANIM_GHOST;
+ }
- m->render(anim, b.basetime, b.basetime2, b.pos, b.yaw, b.pitch, b.d, a, b.color, b.dir, b.transparent);
+ m->render(anim, b.basetime, b.basetime2, b.pos, b.yaw, b.pitch, b.d, a, b.color, b.dir, b.transparent);
}
struct transparentmodel
{
- model *m;
- batchedmodel *batched;
- float dist;
+ model *m;
+ batchedmodel *batched;
+ float dist;
};
static inline bool sorttransparentmodels(const transparentmodel &x, const transparentmodel &y)
{
- return x.dist < y.dist;
+ return x.dist < y.dist;
}
void endmodelbatches()
{
- vector<transparentmodel> transparent;
- loopi(numbatches)
- {
- modelbatch &b = *batches[i];
- if(b.batched.empty()) continue;
-
- bool rendered = false;
- occludequery *query = NULL;
- if(b.flags&MDL_GHOST)
- {
- loopvj(b.batched)
- {
- batchedmodel &bm = b.batched[j];
- if((bm.flags&(MDL_CULL_VFC|MDL_GHOST))!=MDL_GHOST || bm.query) continue;
- if(!rendered) { b.m->startrender(); rendered = true; }
- renderbatchedmodel(b.m, bm);
- }
- if(rendered)
- {
- b.m->endrender();
- rendered = false;
- }
- }
- loopvj(b.batched)
- {
- batchedmodel &bm = b.batched[j];
- if(bm.flags&(MDL_CULL_VFC|MDL_GHOST)) continue;
- if(bm.query!=query)
- {
- if(query) endquery(query);
- query = bm.query;
- if(query) startquery(query);
- }
- if(bm.transparent < 1 && (!query || query->owner==bm.d) && !shadowmapping)
- {
- transparentmodel &tm = transparent.add();
- tm.m = b.m;
- tm.batched = &bm;
- tm.dist = camera1->o.dist(bm.d && bm.d->ragdoll ? bm.d->ragdoll->center : bm.pos);
- continue;
- }
- if(!rendered) { b.m->startrender(); rendered = true; }
- renderbatchedmodel(b.m, bm);
- }
- if(query) endquery(query);
- if(rendered) b.m->endrender();
- }
- if(transparent.length())
- {
- transparent.sort(sorttransparentmodels);
- model *lastmodel = NULL;
- occludequery *query = NULL;
- loopv(transparent)
- {
- transparentmodel &tm = transparent[i];
- if(lastmodel!=tm.m)
- {
- if(lastmodel) lastmodel->endrender();
- (lastmodel = tm.m)->startrender();
- }
- if(query!=tm.batched->query)
- {
- if(query) endquery(query);
- query = tm.batched->query;
- if(query) startquery(query);
- }
- renderbatchedmodel(tm.m, *tm.batched);
- }
- if(query) endquery(query);
- if(lastmodel) lastmodel->endrender();
- }
- numbatches = -1;
+ vector<transparentmodel> transparent;
+ loopi(numbatches)
+ {
+ modelbatch &b = *batches[i];
+ if(b.batched.empty()) continue;
+
+ bool rendered = false;
+ occludequery *query = NULL;
+ if(b.flags&MDL_GHOST)
+ {
+ loopvj(b.batched)
+ {
+ batchedmodel &bm = b.batched[j];
+ if((bm.flags&(MDL_CULL_VFC|MDL_GHOST))!=MDL_GHOST || bm.query) continue;
+ if(!rendered) { b.m->startrender(); rendered = true; }
+ renderbatchedmodel(b.m, bm);
+ }
+ if(rendered)
+ {
+ b.m->endrender();
+ rendered = false;
+ }
+ }
+ loopvj(b.batched)
+ {
+ batchedmodel &bm = b.batched[j];
+ if(bm.flags&(MDL_CULL_VFC|MDL_GHOST)) continue;
+ if(bm.query!=query)
+ {
+ if(query) endquery(query);
+ query = bm.query;
+ if(query) startquery(query);
+ }
+ if(bm.transparent < 1 && (!query || query->owner==bm.d) && !shadowmapping)
+ {
+ transparentmodel &tm = transparent.add();
+ tm.m = b.m;
+ tm.batched = &bm;
+ tm.dist = camera1->o.dist(bm.d && bm.d->ragdoll ? bm.d->ragdoll->center : bm.pos);
+ continue;
+ }
+ if(!rendered) { b.m->startrender(); rendered = true; }
+ renderbatchedmodel(b.m, bm);
+ }
+ if(query) endquery(query);
+ if(rendered) b.m->endrender();
+ }
+ if(transparent.length())
+ {
+ transparent.sort(sorttransparentmodels);
+ model *lastmodel = NULL;
+ occludequery *query = NULL;
+ loopv(transparent)
+ {
+ transparentmodel &tm = transparent[i];
+ if(lastmodel!=tm.m)
+ {
+ if(lastmodel) lastmodel->endrender();
+ (lastmodel = tm.m)->startrender();
+ }
+ if(query!=tm.batched->query)
+ {
+ if(query) endquery(query);
+ query = tm.batched->query;
+ if(query) startquery(query);
+ }
+ renderbatchedmodel(tm.m, *tm.batched);
+ }
+ if(query) endquery(query);
+ if(lastmodel) lastmodel->endrender();
+ }
+ numbatches = -1;
}
void startmodelquery(occludequery *query)
{
- modelquery = query;
+ modelquery = query;
}
void endmodelquery()
{
- int querybatches = 0;
- loopi(numbatches)
- {
- modelbatch &b = *batches[i];
- if(b.batched.empty() || b.batched.last().query!=modelquery) continue;
- querybatches++;
- }
- if(querybatches<=1)
- {
- if(!querybatches) modelquery->fragments = 0;
- modelquery = NULL;
- return;
- }
- int minattached = modelattached.length();
- startquery(modelquery);
- loopi(numbatches)
- {
- modelbatch &b = *batches[i];
- if(b.batched.empty() || b.batched.last().query!=modelquery) continue;
- b.m->startrender();
- do
- {
- batchedmodel &bm = b.batched.pop();
- if(bm.attached>=0) minattached = min(minattached, bm.attached);
- renderbatchedmodel(b.m, bm);
- }
- while(b.batched.length() && b.batched.last().query==modelquery);
- b.m->endrender();
- }
- endquery(modelquery);
- modelquery = NULL;
- modelattached.setsize(minattached);
+ int querybatches = 0;
+ loopi(numbatches)
+ {
+ modelbatch &b = *batches[i];
+ if(b.batched.empty() || b.batched.last().query!=modelquery) continue;
+ querybatches++;
+ }
+ if(querybatches<=1)
+ {
+ if(!querybatches) modelquery->fragments = 0;
+ modelquery = NULL;
+ return;
+ }
+ int minattached = modelattached.length();
+ startquery(modelquery);
+ loopi(numbatches)
+ {
+ modelbatch &b = *batches[i];
+ if(b.batched.empty() || b.batched.last().query!=modelquery) continue;
+ b.m->startrender();
+ do
+ {
+ batchedmodel &bm = b.batched.pop();
+ if(bm.attached>=0) minattached = min(minattached, bm.attached);
+ renderbatchedmodel(b.m, bm);
+ }
+ while(b.batched.length() && b.batched.last().query==modelquery);
+ b.m->endrender();
+ }
+ endquery(modelquery);
+ modelquery = NULL;
+ modelattached.setsize(minattached);
}
VAR(maxmodelradiusdistance, 10, 200, 1000);
static inline void enablecullmodelquery()
{
- startbb();
+ startbb();
}
static inline void rendercullmodelquery(model *m, dynent *d, const vec &center, float radius)
{
- if(fabs(camera1->o.x-center.x) < radius+1 &&
- fabs(camera1->o.y-center.y) < radius+1 &&
- fabs(camera1->o.z-center.z) < radius+1)
- {
- d->query = NULL;
- return;
- }
- d->query = newquery(d);
- if(!d->query) return;
- startquery(d->query);
- int br = int(radius*2)+1;
- drawbb(ivec(int(center.x-radius), int(center.y-radius), int(center.z-radius)), ivec(br, br, br));
- endquery(d->query);
+ if(fabs(camera1->o.x-center.x) < radius+1 &&
+ fabs(camera1->o.y-center.y) < radius+1 &&
+ fabs(camera1->o.z-center.z) < radius+1)
+ {
+ d->query = NULL;
+ return;
+ }
+ d->query = newquery(d);
+ if(!d->query) return;
+ startquery(d->query);
+ int br = int(radius*2)+1;
+ drawbb(ivec(int(center.x-radius), int(center.y-radius), int(center.z-radius)), ivec(br, br, br));
+ endquery(d->query);
}
static inline void disablecullmodelquery()
{
- endbb();
+ endbb();
}
static inline int cullmodel(model *m, const vec &center, float radius, int flags, dynent *d = NULL, bool shadow = false)
{
- if(flags&MDL_CULL_DIST && center.dist(camera1->o)/radius>maxmodelradiusdistance) return MDL_CULL_DIST;
- if(flags&MDL_CULL_VFC)
- {
- if(reflecting || refracting)
- {
- if(reflecting || refracting>0)
- {
- if(center.z+radius<=reflectz) return MDL_CULL_VFC;
- }
- else
- {
- if(fogging && center.z+radius<reflectz-refractfog) return MDL_CULL_VFC;
- if(!shadow && center.z-radius>=reflectz) return MDL_CULL_VFC;
- }
- if(center.dist(camera1->o)-radius>reflectdist) return MDL_CULL_VFC;
- }
- if(isfoggedsphere(radius, center)) return MDL_CULL_VFC;
- if(shadowmapping && !isshadowmapcaster(center, radius)) return MDL_CULL_VFC;
- }
- if(shadowmapping)
- {
- if(d)
- {
- if(flags&MDL_CULL_OCCLUDED && d->occluded>=OCCLUDE_PARENT) return MDL_CULL_OCCLUDED;
- if(flags&MDL_CULL_QUERY && d->occluded+1>=OCCLUDE_BB && d->query && d->query->owner==d && checkquery(d->query)) return MDL_CULL_QUERY;
- }
- if(!addshadowmapcaster(center, radius, radius)) return MDL_CULL_VFC;
- }
- else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius))
- {
- if(!reflecting && !refracting && d) d->occluded = OCCLUDE_PARENT;
- return MDL_CULL_OCCLUDED;
- }
- else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query))
- {
- if(!reflecting && !refracting && d->occluded<OCCLUDE_BB) d->occluded++;
- return MDL_CULL_QUERY;
- }
- return 0;
+ if(flags&MDL_CULL_DIST && center.dist(camera1->o)/radius>maxmodelradiusdistance) return MDL_CULL_DIST;
+ if(flags&MDL_CULL_VFC)
+ {
+ if(reflecting || refracting)
+ {
+ if(reflecting || refracting>0)
+ {
+ if(center.z+radius<=reflectz) return MDL_CULL_VFC;
+ }
+ else
+ {
+ if(fogging && center.z+radius<reflectz-refractfog) return MDL_CULL_VFC;
+ if(!shadow && center.z-radius>=reflectz) return MDL_CULL_VFC;
+ }
+ if(center.dist(camera1->o)-radius>reflectdist) return MDL_CULL_VFC;
+ }
+ if(isfoggedsphere(radius, center)) return MDL_CULL_VFC;
+ if(shadowmapping && !isshadowmapcaster(center, radius)) return MDL_CULL_VFC;
+ }
+ if(shadowmapping)
+ {
+ if(d)
+ {
+ if(flags&MDL_CULL_OCCLUDED && d->occluded>=OCCLUDE_PARENT) return MDL_CULL_OCCLUDED;
+ if(flags&MDL_CULL_QUERY && d->occluded+1>=OCCLUDE_BB && d->query && d->query->owner==d && checkquery(d->query)) return MDL_CULL_QUERY;
+ }
+ if(!addshadowmapcaster(center, radius, radius)) return MDL_CULL_VFC;
+ }
+ else if(flags&MDL_CULL_OCCLUDED && modeloccluded(center, radius))
+ {
+ if(!reflecting && !refracting && d) d->occluded = OCCLUDE_PARENT;
+ return MDL_CULL_OCCLUDED;
+ }
+ else if(flags&MDL_CULL_QUERY && d->query && d->query->owner==d && checkquery(d->query))
+ {
+ if(!reflecting && !refracting && d->occluded<OCCLUDE_BB) d->occluded++;
+ return MDL_CULL_QUERY;
+ }
+ return 0;
}
void rendermodel(entitylight *light, const char *mdl, int anim, const vec &o, float yaw, float pitch, int flags, dynent *d, modelattach *a, int basetime, int basetime2, float trans)
{
- if(shadowmapping && !(flags&(MDL_SHADOW|MDL_DYNSHADOW))) return;
- model *m = loadmodel(mdl);
- if(!m) return;
- vec center(0, 0, 0), bbradius(0, 0, 0);
- float radius = 0;
- bool shadow = !shadowmap && !glaring && (flags&(MDL_SHADOW|MDL_DYNSHADOW));
-
- if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW))
- {
- if(flags&MDL_CULL_QUERY)
- {
- if(!oqfrags || !oqdynent || !d) flags &= ~MDL_CULL_QUERY;
- }
-
- m->boundbox(center, bbradius);
- radius = bbradius.magnitude();
- if(d && d->ragdoll)
- {
- radius = max(radius, d->ragdoll->radius);
- center = d->ragdoll->center;
- }
- else
- {
- center.rotate_around_z(yaw*RAD);
- center.add(o);
- }
-
- int culled = cullmodel(m, center, radius, flags, d, shadow);
- if(culled)
- {
- if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY && !reflecting && !refracting)
- {
- enablecullmodelquery();
- rendercullmodelquery(m, d, center, radius);
- disablecullmodelquery();
- }
- return;
- }
-
- if(reflecting || refracting || shadowmapping) flags &= ~MDL_CULL_QUERY;
- }
-
- if(flags&MDL_NORENDER) anim |= ANIM_NORENDER;
- else if(showboundingbox && !shadowmapping && !reflecting && !refracting && editmode)
- {
- notextureshader->set();
- if(d && showboundingbox==1)
- {
- render3dbox(d->o, d->eyeheight, d->aboveeye, d->radius);
- renderellipse(d->o, d->xradius, d->yradius, d->yaw);
- }
- else
- {
- vec center, radius;
- if(showboundingbox==1) m->collisionbox(center, radius);
- else m->boundbox(center, radius);
- rotatebb(center, radius, int(yaw));
- center.add(o);
- render3dbox(center, radius.z, radius.z, radius.x, radius.y);
- }
- }
-
- vec lightcolor(1, 1, 1), lightdir(0, 0, 1);
- if(!shadowmapping)
- {
- vec pos = o;
- if(d)
- {
- if(!reflecting && !refracting) d->occluded = OCCLUDE_NOTHING;
- if(!light) light = &d->light;
- if(flags&MDL_LIGHT && light->millis!=lastmillis)
- {
- if(d->ragdoll)
- {
- pos = d->ragdoll->center;
- pos.z += radius/2;
- }
- else if(d->type < ENT_CAMERA) pos.z += 0.75f*(d->eyeheight + d->aboveeye);
- lightreaching(pos, light->color, light->dir, (flags&MDL_LIGHT_FAST)!=0);
- dynlightreaching(pos, light->color, light->dir, (flags&MDL_HUD)!=0);
- game::lighteffects(d, light->color, light->dir);
- light->millis = lastmillis;
- }
- }
- else if(flags&MDL_LIGHT)
- {
- if(!light)
- {
- lightreaching(pos, lightcolor, lightdir, (flags&MDL_LIGHT_FAST)!=0);
- dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0);
- }
- else if(light->millis!=lastmillis)
- {
- lightreaching(pos, light->color, light->dir, (flags&MDL_LIGHT_FAST)!=0);
- dynlightreaching(pos, light->color, light->dir, (flags&MDL_HUD)!=0);
- light->millis = lastmillis;
- }
- }
- if(light) { lightcolor = light->color; lightdir = light->dir; }
- if(flags&MDL_DYNLIGHT) dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0);
- }
-
- if(a) for(int i = 0; a[i].tag; i++)
- {
- if(a[i].name) a[i].m = loadmodel(a[i].name);
- //if(a[i].m && a[i].m->type()!=m->type()) a[i].m = NULL;
- }
-
- if(numbatches>=0)
- {
- modelbatch &mb = addbatchedmodel(m);
- batchedmodel &b = mb.batched.add();
- b.query = modelquery;
- b.pos = o;
- b.color = lightcolor;
- b.dir = lightdir;
- b.anim = anim;
- b.yaw = yaw;
- b.pitch = pitch;
- b.basetime = basetime;
- b.basetime2 = basetime2;
- b.transparent = trans;
- b.flags = flags & ~(MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
- if(!shadow || reflecting || refracting>0)
- {
- b.flags &= ~(MDL_SHADOW|MDL_DYNSHADOW);
- if((flags&MDL_CULL_VFC) && refracting<0 && center.z-radius>=reflectz) b.flags |= MDL_CULL_VFC;
- }
- mb.flags |= b.flags;
- b.d = d;
- b.attached = a ? modelattached.length() : -1;
- if(a) for(int i = 0;; i++) { modelattached.add(a[i]); if(!a[i].tag) break; }
- if(flags&MDL_CULL_QUERY) d->query = b.query = newquery(d);
- return;
- }
-
- m->startrender();
-
- if(shadowmapping)
- {
- anim |= ANIM_NOSKIN;
- GLOBALPARAMF(shadowintensity, trans);
- }
- else
- {
- if(flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT;
- if(flags&MDL_GHOST) anim |= ANIM_GHOST;
- }
-
- if(flags&MDL_CULL_QUERY)
- {
- d->query = newquery(d);
- if(d->query) startquery(d->query);
- }
-
- m->render(anim, basetime, basetime2, o, yaw, pitch, d, a, lightcolor, lightdir, trans);
-
- if(flags&MDL_CULL_QUERY && d->query) endquery(d->query);
-
- m->endrender();
+ if(shadowmapping && !(flags&(MDL_SHADOW|MDL_DYNSHADOW))) return;
+ model *m = loadmodel(mdl);
+ if(!m) return;
+ vec center(0, 0, 0), bbradius(0, 0, 0);
+ float radius = 0;
+ bool shadow = !shadowmap && !glaring && (flags&(MDL_SHADOW|MDL_DYNSHADOW));
+
+ if(flags&(MDL_CULL_VFC|MDL_CULL_DIST|MDL_CULL_OCCLUDED|MDL_CULL_QUERY|MDL_SHADOW|MDL_DYNSHADOW))
+ {
+ if(flags&MDL_CULL_QUERY)
+ {
+ if(!oqfrags || !oqdynent || !d) flags &= ~MDL_CULL_QUERY;
+ }
+
+ m->boundbox(center, bbradius);
+ radius = bbradius.magnitude();
+ if(d && d->ragdoll)
+ {
+ radius = max(radius, d->ragdoll->radius);
+ center = d->ragdoll->center;
+ }
+ else
+ {
+ center.rotate_around_z(yaw*RAD);
+ center.add(o);
+ }
+
+ int culled = cullmodel(m, center, radius, flags, d, shadow);
+ if(culled)
+ {
+ if(culled&(MDL_CULL_OCCLUDED|MDL_CULL_QUERY) && flags&MDL_CULL_QUERY && !reflecting && !refracting)
+ {
+ enablecullmodelquery();
+ rendercullmodelquery(m, d, center, radius);
+ disablecullmodelquery();
+ }
+ return;
+ }
+
+ if(reflecting || refracting || shadowmapping) flags &= ~MDL_CULL_QUERY;
+ }
+
+ if(flags&MDL_NORENDER) anim |= ANIM_NORENDER;
+ else if(showboundingbox && !shadowmapping && !reflecting && !refracting && editmode)
+ {
+ notextureshader->set();
+ if(d && showboundingbox==1)
+ {
+ render3dbox(d->o, d->eyeheight, d->aboveeye, d->radius);
+ renderellipse(d->o, d->xradius, d->yradius, d->yaw);
+ }
+ else
+ {
+ vec center, radius;
+ if(showboundingbox==1) m->collisionbox(center, radius);
+ else m->boundbox(center, radius);
+ rotatebb(center, radius, int(yaw));
+ center.add(o);
+ render3dbox(center, radius.z, radius.z, radius.x, radius.y);
+ }
+ }
+
+ vec lightcolor(1, 1, 1), lightdir(0, 0, 1);
+ if(!shadowmapping)
+ {
+ vec pos = o;
+ if(d)
+ {
+ if(!reflecting && !refracting) d->occluded = OCCLUDE_NOTHING;
+ if(!light) light = &d->light;
+ if(flags&MDL_LIGHT && light->millis!=lastmillis)
+ {
+ if(d->ragdoll)
+ {
+ pos = d->ragdoll->center;
+ pos.z += radius/2;
+ }
+ else if(d->type < ENT_CAMERA) pos.z += 0.75f*(d->eyeheight + d->aboveeye);
+ lightreaching(pos, light->color, light->dir, (flags&MDL_LIGHT_FAST)!=0);
+ dynlightreaching(pos, light->color, light->dir, (flags&MDL_HUD)!=0);
+ game::lighteffects(d, light->color, light->dir);
+ light->millis = lastmillis;
+ }
+ }
+ else if(flags&MDL_LIGHT)
+ {
+ if(!light)
+ {
+ lightreaching(pos, lightcolor, lightdir, (flags&MDL_LIGHT_FAST)!=0);
+ dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0);
+ }
+ else if(light->millis!=lastmillis)
+ {
+ lightreaching(pos, light->color, light->dir, (flags&MDL_LIGHT_FAST)!=0);
+ dynlightreaching(pos, light->color, light->dir, (flags&MDL_HUD)!=0);
+ light->millis = lastmillis;
+ }
+ }
+ if(light) { lightcolor = light->color; lightdir = light->dir; }
+ if(flags&MDL_DYNLIGHT) dynlightreaching(pos, lightcolor, lightdir, (flags&MDL_HUD)!=0);
+ }
+
+ if(a) for(int i = 0; a[i].tag; i++)
+ {
+ if(a[i].name) a[i].m = loadmodel(a[i].name);
+ //if(a[i].m && a[i].m->type()!=m->type()) a[i].m = NULL;
+ }
+
+ if(numbatches>=0)
+ {
+ modelbatch &mb = addbatchedmodel(m);
+ batchedmodel &b = mb.batched.add();
+ b.query = modelquery;
+ b.pos = o;
+ b.color = lightcolor;
+ b.dir = lightdir;
+ b.anim = anim;
+ b.yaw = yaw;
+ b.pitch = pitch;
+ b.basetime = basetime;
+ b.basetime2 = basetime2;
+ b.transparent = trans;
+ b.flags = flags & ~(MDL_CULL_VFC | MDL_CULL_DIST | MDL_CULL_OCCLUDED);
+ if(!shadow || reflecting || refracting>0)
+ {
+ b.flags &= ~(MDL_SHADOW|MDL_DYNSHADOW);
+ if((flags&MDL_CULL_VFC) && refracting<0 && center.z-radius>=reflectz) b.flags |= MDL_CULL_VFC;
+ }
+ mb.flags |= b.flags;
+ b.d = d;
+ b.attached = a ? modelattached.length() : -1;
+ if(a) for(int i = 0;; i++) { modelattached.add(a[i]); if(!a[i].tag) break; }
+ if(flags&MDL_CULL_QUERY) d->query = b.query = newquery(d);
+ return;
+ }
+
+ m->startrender();
+
+ if(shadowmapping)
+ {
+ anim |= ANIM_NOSKIN;
+ GLOBALPARAMF(shadowintensity, trans);
+ }
+ else
+ {
+ if(flags&MDL_FULLBRIGHT) anim |= ANIM_FULLBRIGHT;
+ if(flags&MDL_GHOST) anim |= ANIM_GHOST;
+ }
+
+ if(flags&MDL_CULL_QUERY)
+ {
+ d->query = newquery(d);
+ if(d->query) startquery(d->query);
+ }
+
+ m->render(anim, basetime, basetime2, o, yaw, pitch, d, a, lightcolor, lightdir, trans);
+
+ if(flags&MDL_CULL_QUERY && d->query) endquery(d->query);
+
+ m->endrender();
}
void abovemodel(vec &o, const char *mdl)
{
- model *m = loadmodel(mdl);
- if(!m) return;
- o.z += m->above();
+ model *m = loadmodel(mdl);
+ if(!m) return;
+ o.z += m->above();
}
bool matchanim(const char *name, const char *pattern)
{
- for(;; pattern++)
- {
- const char *s = name;
- char c;
- for(;; pattern++)
- {
- c = *pattern;
- if(!c || c=='|') break;
- else if(c=='*')
- {
- if(!*s || iscubespace(*s)) break;
- do s++; while(*s && !iscubespace(*s));
- }
- else if(c!=*s) break;
- else s++;
- }
- if(!*s && (!c || c=='|')) return true;
- pattern = strchr(pattern, '|');
- if(!pattern) break;
- }
- return false;
+ for(;; pattern++)
+ {
+ const char *s = name;
+ char c;
+ for(;; pattern++)
+ {
+ c = *pattern;
+ if(!c || c=='|') break;
+ else if(c=='*')
+ {
+ if(!*s || iscubespace(*s)) break;
+ do s++; while(*s && !iscubespace(*s));
+ }
+ else if(c!=*s) break;
+ else s++;
+ }
+ if(!*s && (!c || c=='|')) return true;
+ pattern = strchr(pattern, '|');
+ if(!pattern) break;
+ }
+ return false;
}
void findanims(const char *pattern, vector<int> &anims)
{
- loopi(sizeof(animnames)/sizeof(animnames[0])) if(matchanim(animnames[i], pattern)) anims.add(i);
+ loopi(sizeof(animnames)/sizeof(animnames[0])) if(matchanim(animnames[i], pattern)) anims.add(i);
}
ICOMMAND(findanims, "s", (char *name),
{
- vector<int> anims;
- findanims(name, anims);
- vector<char> buf;
- string num;
- loopv(anims)
- {
- formatstring(num, "%d", anims[i]);
- if(i > 0) buf.add(' ');
- buf.put(num, strlen(num));
- }
- buf.add('\0');
- result(buf.getbuf());
+ vector<int> anims;
+ findanims(name, anims);
+ vector<char> buf;
+ string num;
+ loopv(anims)
+ {
+ formatstring(num, "%d", anims[i]);
+ if(i > 0) buf.add(' ');
+ buf.put(num, strlen(num));
+ }
+ buf.add('\0');
+ result(buf.getbuf());
});
void loadskin(const char *dir, const char *altdir, Texture *&skin, Texture *&masks) // model skin sharing
{
#define ifnoload(tex, path) if((tex = textureload(path, 0, true, false))==notexture)
#define tryload(tex, prefix, cmd, name) \
- ifnoload(tex, makerelpath(mdir, name ".jpg", prefix, cmd)) \
- { \
- ifnoload(tex, makerelpath(mdir, name ".png", prefix, cmd)) \
- { \
- ifnoload(tex, makerelpath(maltdir, name ".jpg", prefix, cmd)) \
- { \
- ifnoload(tex, makerelpath(maltdir, name ".png", prefix, cmd)) return; \
- } \
- } \
- }
-
- defformatstring(mdir, "packages/models/%s", dir);
- defformatstring(maltdir, "packages/models/%s", altdir);
- masks = notexture;
- tryload(skin, NULL, NULL, "skin");
- tryload(masks, NULL, NULL, "masks");
+ ifnoload(tex, makerelpath(mdir, name ".jpg", prefix, cmd)) \
+ { \
+ ifnoload(tex, makerelpath(mdir, name ".png", prefix, cmd)) \
+ { \
+ ifnoload(tex, makerelpath(maltdir, name ".jpg", prefix, cmd)) \
+ { \
+ ifnoload(tex, makerelpath(maltdir, name ".png", prefix, cmd)) return; \
+ } \
+ } \
+ }
+
+ defformatstring(mdir, "packages/models/%s", dir);
+ defformatstring(maltdir, "packages/models/%s", altdir);
+ masks = notexture;
+ tryload(skin, NULL, NULL, "skin");
+ tryload(masks, NULL, NULL, "masks");
}
// convenient function that covers the usual anims for players/monsters/npcs
@@ -1033,86 +1033,86 @@ VAR(testpitch, -90, 0, 90);
void renderclient(dynent *d, const char *mdlname, modelattach *attachments, int hold, int attack, int attackdelay, int lastaction, int lastpain, float fade, bool ragdoll)
{
- int anim = hold ? hold : ANIM_IDLE|ANIM_LOOP;
- float yaw = testanims && d==player ? 0 : d->yaw+90,
- pitch = testpitch && d==player ? testpitch : d->pitch;
- vec o = d->feetpos();
- int basetime = 0;
- if(animoverride) anim = (animoverride<0 ? ANIM_ALL : animoverride)|ANIM_LOOP;
- else if(d->state==CS_DEAD)
- {
- anim = ANIM_DYING|ANIM_NOPITCH;
- basetime = lastpain;
- if(ragdoll)
- {
- if(!d->ragdoll || d->ragdoll->millis < basetime)
- {
- DELETEP(d->ragdoll);
- anim |= ANIM_RAGDOLL;
- }
- }
- else if(lastmillis-basetime>1000) anim = ANIM_DEAD|ANIM_LOOP|ANIM_NOPITCH;
- }
- else if(d->state==CS_EDITING || d->state==CS_SPECTATOR) anim = ANIM_EDIT|ANIM_LOOP;
- else if(d->state==CS_LAGGED) anim = ANIM_LAG|ANIM_LOOP;
- else
- {
- if(lastmillis-lastpain < 300)
- {
- anim = ANIM_PAIN;
- basetime = lastpain;
- }
- else if(lastpain < lastaction && (attack < 0 || (d->type != ENT_AI && lastmillis-lastaction < attackdelay)))
- {
- anim = attack < 0 ? -attack : attack;
- basetime = lastaction;
- }
-
- if(d->inwater && d->physstate<=PHYS_FALL) anim |= (((game::allowmove(d) && (d->move || d->strafe)) || d->vel.z+d->falling.z>0 ? ANIM_SWIM : ANIM_SINK)|ANIM_LOOP)<<ANIM_SECONDARY;
- else if(d->timeinair>100) anim |= (ANIM_JUMP|ANIM_END)<<ANIM_SECONDARY;
- else if(game::allowmove(d) && (d->move || d->strafe))
- {
- if(d->move>0) anim |= (ANIM_FORWARD|ANIM_LOOP)<<ANIM_SECONDARY;
- else if(d->strafe)
- {
- if(d->move<0) anim |= ((d->strafe>0 ? ANIM_RIGHT : ANIM_LEFT)|ANIM_REVERSE|ANIM_LOOP)<<ANIM_SECONDARY;
- else anim |= ((d->strafe>0 ? ANIM_LEFT : ANIM_RIGHT)|ANIM_LOOP)<<ANIM_SECONDARY;
- }
- else if(d->move<0) anim |= (ANIM_BACKWARD|ANIM_LOOP)<<ANIM_SECONDARY;
- }
-
- if((anim&ANIM_INDEX)==ANIM_IDLE && (anim>>ANIM_SECONDARY)&ANIM_INDEX) anim >>= ANIM_SECONDARY;
- }
- if(d->ragdoll && (!ragdoll || (anim&ANIM_INDEX)!=ANIM_DYING)) DELETEP(d->ragdoll);
- if(!((anim>>ANIM_SECONDARY)&ANIM_INDEX)) anim |= (ANIM_IDLE|ANIM_LOOP)<<ANIM_SECONDARY;
- int flags = MDL_LIGHT;
- if(d!=player && !(anim&ANIM_RAGDOLL)) flags |= MDL_CULL_VFC | MDL_CULL_OCCLUDED | MDL_CULL_QUERY;
- if(d->type==ENT_PLAYER) flags |= MDL_FULLBRIGHT;
- else flags |= MDL_CULL_DIST;
- if(d->state==CS_LAGGED) fade = min(fade, 0.3f);
- else flags |= MDL_DYNSHADOW;
- if(drawtex == DRAWTEX_MODELPREVIEW) flags &= ~(MDL_LIGHT | MDL_FULLBRIGHT | MDL_CULL_VFC | MDL_CULL_OCCLUDED | MDL_CULL_QUERY | MDL_CULL_DIST | MDL_DYNSHADOW);
- rendermodel(NULL, mdlname, anim, o, yaw, pitch, flags, d, attachments, basetime, 0, fade);
+ int anim = hold ? hold : ANIM_IDLE|ANIM_LOOP;
+ float yaw = testanims && d==player ? 0 : d->yaw+90,
+ pitch = testpitch && d==player ? testpitch : d->pitch;
+ vec o = d->feetpos();
+ int basetime = 0;
+ if(animoverride) anim = (animoverride<0 ? ANIM_ALL : animoverride)|ANIM_LOOP;
+ else if(d->state==CS_DEAD)
+ {
+ anim = ANIM_DYING|ANIM_NOPITCH;
+ basetime = lastpain;
+ if(ragdoll)
+ {
+ if(!d->ragdoll || d->ragdoll->millis < basetime)
+ {
+ DELETEP(d->ragdoll);
+ anim |= ANIM_RAGDOLL;
+ }
+ }
+ else if(lastmillis-basetime>1000) anim = ANIM_DEAD|ANIM_LOOP|ANIM_NOPITCH;
+ }
+ else if(d->state==CS_EDITING || d->state==CS_SPECTATOR) anim = ANIM_EDIT|ANIM_LOOP;
+ else if(d->state==CS_LAGGED) anim = ANIM_LAG|ANIM_LOOP;
+ else
+ {
+ if(lastmillis-lastpain < 300)
+ {
+ anim = ANIM_PAIN;
+ basetime = lastpain;
+ }
+ else if(lastpain < lastaction && (attack < 0 || (d->type != ENT_AI && lastmillis-lastaction < attackdelay)))
+ {
+ anim = attack < 0 ? -attack : attack;
+ basetime = lastaction;
+ }
+
+ if(d->inwater && d->physstate<=PHYS_FALL) anim |= (((game::allowmove(d) && (d->move || d->strafe)) || d->vel.z+d->falling.z>0 ? ANIM_SWIM : ANIM_SINK)|ANIM_LOOP)<<ANIM_SECONDARY;
+ else if(d->timeinair>100) anim |= (ANIM_JUMP|ANIM_END)<<ANIM_SECONDARY;
+ else if(game::allowmove(d) && (d->move || d->strafe))
+ {
+ if(d->move>0) anim |= (ANIM_FORWARD|ANIM_LOOP)<<ANIM_SECONDARY;
+ else if(d->strafe)
+ {
+ if(d->move<0) anim |= ((d->strafe>0 ? ANIM_RIGHT : ANIM_LEFT)|ANIM_REVERSE|ANIM_LOOP)<<ANIM_SECONDARY;
+ else anim |= ((d->strafe>0 ? ANIM_LEFT : ANIM_RIGHT)|ANIM_LOOP)<<ANIM_SECONDARY;
+ }
+ else if(d->move<0) anim |= (ANIM_BACKWARD|ANIM_LOOP)<<ANIM_SECONDARY;
+ }
+
+ if((anim&ANIM_INDEX)==ANIM_IDLE && (anim>>ANIM_SECONDARY)&ANIM_INDEX) anim >>= ANIM_SECONDARY;
+ }
+ if(d->ragdoll && (!ragdoll || (anim&ANIM_INDEX)!=ANIM_DYING)) DELETEP(d->ragdoll);
+ if(!((anim>>ANIM_SECONDARY)&ANIM_INDEX)) anim |= (ANIM_IDLE|ANIM_LOOP)<<ANIM_SECONDARY;
+ int flags = MDL_LIGHT;
+ if(d!=player && !(anim&ANIM_RAGDOLL)) flags |= MDL_CULL_VFC | MDL_CULL_OCCLUDED | MDL_CULL_QUERY;
+ if(d->type==ENT_PLAYER) flags |= MDL_FULLBRIGHT;
+ else flags |= MDL_CULL_DIST;
+ if(d->state==CS_LAGGED) fade = min(fade, 0.3f);
+ else flags |= MDL_DYNSHADOW;
+ if(drawtex == DRAWTEX_MODELPREVIEW) flags &= ~(MDL_LIGHT | MDL_FULLBRIGHT | MDL_CULL_VFC | MDL_CULL_OCCLUDED | MDL_CULL_QUERY | MDL_CULL_DIST | MDL_DYNSHADOW);
+ rendermodel(NULL, mdlname, anim, o, yaw, pitch, flags, d, attachments, basetime, 0, fade);
}
void setbbfrommodel(dynent *d, const char *mdl)
{
- model *m = loadmodel(mdl);
- if(!m) return;
- vec center, radius;
- m->collisionbox(center, radius);
- if(d->type==ENT_INANIMATE && !m->ellipsecollide)
- d->collidetype = COLLIDE_OBB;
- d->xradius = radius.x + fabs(center.x);
- d->yradius = radius.y + fabs(center.y);
- d->radius = d->collidetype==COLLIDE_OBB ? sqrtf(d->xradius*d->xradius + d->yradius*d->yradius) : max(d->xradius, d->yradius);
- d->eyeheight = (center.z-radius.z) + radius.z*2*m->eyeheight;
- d->aboveeye = radius.z*2*(1.0f-m->eyeheight);
- if (d->aboveeye + d->eyeheight <= 0.5f)
- {
- float zrad = (0.5f - (d->aboveeye + d->eyeheight)) / 2;
- d->aboveeye += zrad;
- d->eyeheight += zrad;
- }
+ model *m = loadmodel(mdl);
+ if(!m) return;
+ vec center, radius;
+ m->collisionbox(center, radius);
+ if(d->type==ENT_INANIMATE && !m->ellipsecollide)
+ d->collidetype = COLLIDE_OBB;
+ d->xradius = radius.x + fabs(center.x);
+ d->yradius = radius.y + fabs(center.y);
+ d->radius = d->collidetype==COLLIDE_OBB ? sqrtf(d->xradius*d->xradius + d->yradius*d->yradius) : max(d->xradius, d->yradius);
+ d->eyeheight = (center.z-radius.z) + radius.z*2*m->eyeheight;
+ d->aboveeye = radius.z*2*(1.0f-m->eyeheight);
+ if (d->aboveeye + d->eyeheight <= 0.5f)
+ {
+ float zrad = (0.5f - (d->aboveeye + d->eyeheight)) / 2;
+ d->aboveeye += zrad;
+ d->eyeheight += zrad;
+ }
}