diff options
| author | xolatile | 2025-08-04 22:53:42 +0200 |
|---|---|---|
| committer | xolatile | 2025-08-04 22:53:42 +0200 |
| commit | d309df4ce4d8ad0ed995a8e1c4267412a7782021 (patch) | |
| tree | 999ca8d785ecc1681e5eb7538ce2e6a18d244fa5 /src/engine/rendermodel.cpp | |
| parent | 29d613d9cb65a0faa7e3f80e75bea0b6d910cb9a (diff) | |
| download | xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.xz xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.zst | |
Bunch of small changes...
Diffstat (limited to 'src/engine/rendermodel.cpp')
| -rw-r--r-- | src/engine/rendermodel.cpp | 1434 |
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 ¢er, 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 ¢er, 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 ¢er, 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; + } } |
