LCOV - code coverage report
Current view: top level - engine/model - vertmodel.cpp (source / functions) Coverage Total Hit
Test: Libprimis Test Coverage Lines: 0.0 % 238 0
Test Date: 2025-04-16 12:09:02 Functions: 0.0 % 31 0

            Line data    Source code
       1              : /* vertmodel.cpp: vertex model support
       2              :  */
       3              : #include "../libprimis-headers/cube.h"
       4              : #include "../../shared/geomexts.h"
       5              : #include "../../shared/glemu.h"
       6              : #include "../../shared/glexts.h"
       7              : 
       8              : #include <format>
       9              : #include <memory>
      10              : #include <optional>
      11              : 
      12              : #include "interface/console.h"
      13              : #include "interface/control.h"
      14              : 
      15              : #include "render/rendergl.h"
      16              : #include "render/renderlights.h"
      17              : #include "render/rendermodel.h"
      18              : #include "render/shader.h"
      19              : #include "render/shaderparam.h"
      20              : #include "render/texture.h"
      21              : 
      22              : #include "world/entities.h"
      23              : #include "world/octaworld.h"
      24              : #include "world/bih.h"
      25              : 
      26              : #include "model.h"
      27              : #include "ragdoll.h"
      28              : #include "animmodel.h"
      29              : #include "vertmodel.h"
      30              : 
      31              : //==============================================================================
      32              : // vertmodel object
      33              : //==============================================================================
      34              : 
      35            0 : vertmodel::meshgroup * vertmodel::loadmeshes(const char *name, float smooth)
      36              : {
      37            0 :     vertmeshgroup *group = newmeshes();
      38            0 :     if(!group->load(name, smooth))
      39              :     {
      40            0 :         delete group;
      41            0 :         return nullptr;
      42              :     }
      43            0 :     return group;
      44              : }
      45              : 
      46            0 : vertmodel::meshgroup * vertmodel::sharemeshes(const char *name, float smooth)
      47              : {
      48            0 :     if(meshgroups.find(name) == meshgroups.end())
      49              :     {
      50            0 :         meshgroup *group = loadmeshes(name, smooth);
      51            0 :         if(!group)
      52              :         {
      53            0 :             return nullptr;
      54              :         }
      55            0 :         meshgroups[group->groupname()] = group;
      56              :     }
      57            0 :     return meshgroups[name];
      58              : }
      59              : 
      60            0 : vertmodel::vertmodel(std::string name) : animmodel(std::move(name))
      61              : {
      62            0 : }
      63              : 
      64              : //==============================================================================
      65              : // vertmodel::vbocacheentry object
      66              : //==============================================================================
      67              : 
      68            0 : vertmodel::vbocacheentry::vbocacheentry() : vbuf(0)
      69              : {
      70            0 :     as.cur.fr1 = as.prev.fr1 = -1;
      71            0 : }
      72              : 
      73              : //==============================================================================
      74              : // vertmodel::vertmesh object
      75              : //==============================================================================
      76              : 
      77            0 : vertmodel::vertmesh::vertmesh() : verts(0), tcverts(0), tris(0)
      78              : {
      79            0 : }
      80              : 
      81            0 : vertmodel::vertmesh::vertmesh(std::string_view name, meshgroup *m) :
      82              :     Mesh(name, m),
      83            0 :     verts(0),
      84            0 :     tcverts(0),
      85            0 :     tris(0)
      86              : {
      87            0 : }
      88              : 
      89            0 : vertmodel::vertmesh::~vertmesh()
      90              : {
      91            0 :     delete[] verts;
      92            0 :     delete[] tcverts;
      93            0 :     delete[] tris;
      94            0 : }
      95              : 
      96            0 : void vertmodel::vertmesh::smoothnorms(float limit, bool areaweight)
      97              : {
      98            0 :     if((static_cast<vertmeshgroup *>(group))->numframes == 1)
      99              :     {
     100            0 :         Mesh::smoothnorms<vertmodel>(verts, numverts, tris, numtris, limit, areaweight);
     101              :     }
     102              :     else
     103              :     {
     104            0 :         buildnorms(areaweight);
     105              :     }
     106            0 : }
     107              : 
     108            0 : void vertmodel::vertmesh::buildnorms(bool areaweight)
     109              : {
     110            0 :     Mesh::buildnorms<vertmodel>(verts, numverts, tris, numtris, areaweight, (static_cast<vertmeshgroup *>(group))->numframes);
     111            0 : }
     112              : 
     113            0 : void vertmodel::vertmesh::calctangents(bool areaweight)
     114              : {
     115            0 :     Mesh::calctangents<vertmodel, vertmodel::tcvert>(verts, tcverts, numverts, tris, numtris, areaweight, (static_cast<vertmeshgroup *>(group))->numframes);
     116            0 : }
     117              : 
     118            0 : void vertmodel::vertmesh::calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) const
     119              : {
     120            0 :     for(int j = 0; j < numverts; ++j)
     121              :     {
     122            0 :         vec v = m.transform(verts[j].pos);
     123            0 :         bbmin.min(v);
     124            0 :         bbmax.max(v);
     125              :     }
     126            0 : }
     127              : 
     128            0 : void vertmodel::vertmesh::genBIH(BIH::mesh &m) const
     129              : {
     130            0 :     m.setmesh(reinterpret_cast<const BIH::mesh::tri *>(tris), numtris,
     131            0 :               reinterpret_cast<const uchar *>(&verts->pos), sizeof(vert),
     132            0 :               reinterpret_cast<const uchar *>(&tcverts->tc), sizeof(tcvert));
     133            0 : }
     134              : 
     135            0 : void vertmodel::vertmesh::genshadowmesh(std::vector<triangle> &out, const matrix4x3 &m) const
     136              : {
     137            0 :     for(int j = 0; j < numtris; ++j)
     138              :     {
     139            0 :         out.emplace_back(m.transform(verts[tris[j].vert[0]].pos),
     140            0 :                          m.transform(verts[tris[j].vert[1]].pos),
     141            0 :                          m.transform(verts[tris[j].vert[2]].pos));
     142              :     }
     143            0 : }
     144              : 
     145            0 : void vertmodel::vertmesh::assignvert(vvertg &vv, const tcvert &tc, const vert &v)
     146              : {
     147            0 :     vv.pos = vec4<half>(v.pos, 1);
     148            0 :     vv.tc = tc.tc;
     149            0 :     vv.tangent = v.tangent;
     150            0 : }
     151              : 
     152            0 : int vertmodel::vertmesh::genvbo(std::vector<uint> &idxs, int offset)
     153              : {
     154            0 :     voffset = offset;
     155            0 :     for(int i = 0; i < numtris; ++i)
     156              :     {
     157            0 :         const tri &t = tris[i];
     158            0 :         for(int j = 0; j < 3; ++j)
     159              :         {
     160            0 :             idxs.push_back(voffset+t.vert[j]);
     161              :         }
     162              :     }
     163            0 :     minvert = voffset;
     164            0 :     maxvert = voffset + numverts-1;
     165            0 :     elen = idxs.size();
     166            0 :     return numverts;
     167              : }
     168              : 
     169            0 : void vertmodel::vertmesh::render() const
     170              : {
     171            0 :     if(!Shader::lastshader)
     172              :     {
     173            0 :         return;
     174              :     }
     175            0 :     glDrawRangeElements(GL_TRIANGLES, minvert, maxvert, elen, GL_UNSIGNED_INT, nullptr);
     176            0 :     glde++;
     177            0 :     xtravertsva += numverts;
     178              : }
     179              : 
     180              : //==============================================================================
     181              : // vertmodel::vertmeshgroup object
     182              : //==============================================================================
     183              : 
     184            0 : vertmodel::vertmeshgroup::vertmeshgroup()
     185            0 :     : numframes(0), tags(nullptr), numtags(0), ebuf(0), vlen(0), vertsize(0), vdata(nullptr)
     186              : {
     187            0 : }
     188              : 
     189            0 : vertmodel::vertmeshgroup::~vertmeshgroup()
     190              : {
     191            0 :     delete[] tags;
     192            0 :     if(ebuf)
     193              :     {
     194            0 :         glDeleteBuffers(1, &ebuf);
     195              :     }
     196            0 :     for(size_t i = 0; i < maxvbocache; ++i)
     197              :     {
     198            0 :         if(vbocache[i].vbuf)
     199              :         {
     200            0 :             glDeleteBuffers(1, &vbocache[i].vbuf);
     201              :         }
     202              :     }
     203            0 :     delete[] vdata;
     204            0 : }
     205              : 
     206            0 : void vertmodel::vertmeshgroup::concattagtransform(int, const matrix4x3 &, matrix4x3 &) const
     207              : {
     208            0 : }
     209              : 
     210            0 : std::optional<size_t> vertmodel::vertmeshgroup::findtag(std::string_view name)
     211              : {
     212            0 :     for(size_t i = 0; i < numtags; ++i)
     213              :     {
     214            0 :         if(tags[i].name == name)
     215              :         {
     216            0 :             return i;
     217              :         }
     218              :     }
     219            0 :     return std::nullopt;
     220              : }
     221              : 
     222            0 : bool vertmodel::vertmeshgroup::addtag(std::string_view name, const matrix4x3 &matrix)
     223              : {
     224            0 :     std::optional<size_t> idx = findtag(name);
     225            0 :     if(idx)
     226              :     {
     227            0 :         if(!testtags)
     228              :         {
     229            0 :             return false;
     230              :         }
     231            0 :         for(int i = 0; i < numframes; ++i)
     232              :         {
     233            0 :             tag &t = tags[i*numtags + *idx];
     234            0 :             t.matrix = matrix;
     235              :         }
     236              :     }
     237              :     else
     238              :     {
     239            0 :         tag *newtags = new tag[(numtags+1)*numframes];
     240            0 :         for(int i = 0; i < numframes; ++i)
     241              :         {
     242            0 :             tag *dst = &newtags[(numtags+1)*i],
     243            0 :                 *src = &tags[numtags*i];
     244            0 :             if(!i)
     245              :             {
     246            0 :                 for(size_t j = 0; j < numtags; ++j)
     247              :                 {
     248            0 :                     std::swap(dst[j].name, src[j].name);
     249              :                 }
     250            0 :                 dst[numtags].name = name;
     251              :             }
     252            0 :             for(size_t j = 0; j < numtags; ++j)
     253              :             {
     254            0 :                 dst[j].matrix = src[j].matrix;
     255              :             }
     256            0 :             dst[numtags].matrix = matrix;
     257              :         }
     258            0 :         if(tags)
     259              :         {
     260            0 :             delete[] tags;
     261              :         }
     262            0 :         tags = newtags;
     263            0 :         numtags++;
     264              :     }
     265            0 :     return true;
     266              : }
     267              : 
     268            0 : int vertmodel::vertmeshgroup::totalframes() const
     269              : {
     270            0 :     return numframes;
     271              : }
     272              : 
     273            0 : void vertmodel::vertmeshgroup::calctagmatrix(const part *p, int i, const AnimState &as, matrix4 &matrix) const
     274              : {
     275            0 :     const matrix4x3 &tag1 = tags[as.cur.fr1*numtags + i].matrix,
     276            0 :                     &tag2 = tags[as.cur.fr2*numtags + i].matrix;
     277            0 :     matrix4x3 tag;
     278            0 :     tag.lerp(tag1, tag2, as.cur.t);
     279            0 :     if(as.interp<1)
     280              :     {
     281            0 :         const matrix4x3 &tag1p = tags[as.prev.fr1*numtags + i].matrix,
     282            0 :                         &tag2p = tags[as.prev.fr2*numtags + i].matrix;
     283            0 :         matrix4x3 tagp;
     284            0 :         tagp.lerp(tag1p, tag2p, as.prev.t);
     285            0 :         tag.lerp(tagp, tag, as.interp);
     286              :     }
     287            0 :     tag.d.mul(p->model->locationsize().w * sizescale);
     288            0 :     matrix = matrix4(tag);
     289            0 : }
     290              : 
     291            0 : void vertmodel::vertmeshgroup::genvbo(vbocacheentry &vc)
     292              : {
     293            0 :     if(!vc.vbuf)
     294              :     {
     295            0 :         glGenBuffers(1, &vc.vbuf);
     296              :     }
     297            0 :     if(ebuf)
     298              :     {
     299            0 :         return;
     300              :     }
     301              : 
     302            0 :     std::vector<uint> idxs;
     303            0 :     std::vector<std::vector<animmodel::Mesh *>::iterator> rendermeshes = getrendermeshes();
     304            0 :     vlen = 0;
     305            0 :     if(numframes>1)
     306              :     {
     307            0 :         vertsize = sizeof(vvert);
     308              : 
     309            0 :         for(auto i : rendermeshes)
     310              :         {
     311            0 :             vlen += static_cast<vertmesh *>(*i)->genvbo(idxs, vlen);
     312              :         }
     313            0 :         delete[] vdata;
     314            0 :         vdata = new uchar[vlen*vertsize];
     315            0 :         for(auto i : rendermeshes)
     316              :         {
     317            0 :             static_cast<vertmesh *>(*i)->fillverts(reinterpret_cast<vvert *>(vdata));
     318              :         }
     319              :     }
     320              :     else
     321              :     {
     322            0 :         vertsize = sizeof(vvertg);
     323            0 :         gle::bindvbo(vc.vbuf);
     324            0 :         size_t numverts = 0,
     325            0 :                htlen = 128;
     326            0 :         for(auto i : rendermeshes)
     327              :         {
     328            0 :             numverts += static_cast<vertmesh *>(*i)->numverts;
     329              :         }
     330            0 :         while(htlen < numverts)
     331              :         {
     332            0 :             htlen *= 2;
     333              :         }
     334            0 :         if(numverts*4 > htlen*3)
     335              :         {
     336            0 :             htlen *= 2;
     337              :         }
     338            0 :         int *htdata = new int[htlen];
     339            0 :         std::memset(htdata, -1, htlen*sizeof(int));
     340            0 :         std::vector<vvertg> vverts;
     341            0 :         for(auto i : rendermeshes)
     342              :         {
     343            0 :             vlen += static_cast<vertmesh *>(*i)->genvbo(idxs, vlen, vverts, htdata, htlen);
     344              :         }
     345            0 :         glBufferData(GL_ARRAY_BUFFER, vverts.size()*sizeof(vvertg), vverts.data(), GL_STATIC_DRAW);
     346            0 :         delete[] htdata;
     347            0 :         htdata = nullptr;
     348            0 :         gle::clearvbo();
     349            0 :     }
     350              : 
     351            0 :     glGenBuffers(1, &ebuf);
     352            0 :     gle::bindebo(ebuf);
     353            0 :     glBufferData(GL_ELEMENT_ARRAY_BUFFER, idxs.size()*sizeof(uint), idxs.data(), GL_STATIC_DRAW);
     354            0 :     gle::clearebo();
     355            0 : }
     356              : 
     357            0 : void vertmodel::vertmeshgroup::bindvbo(const AnimState *as, const part *p, const vbocacheentry &vc)
     358              : {
     359            0 :     if(numframes>1)
     360              :     {
     361            0 :         bindvbo<vvert>(as, p, vc);
     362              :     }
     363              :     else
     364              :     {
     365            0 :         bindvbo<vvertg>(as, p, vc);
     366              :     }
     367            0 : }
     368              : 
     369            0 : void *vertmodel::vertmeshgroup::animkey()
     370              : {
     371            0 :     return this;
     372              : }
     373              : 
     374            0 : void vertmodel::vertmeshgroup::cleanup()
     375              : {
     376            0 :     for(size_t i = 0; i < maxvbocache; ++i)
     377              :     {
     378            0 :         vbocacheentry &c = vbocache[i];
     379            0 :         if(c.vbuf)
     380              :         {
     381            0 :             glDeleteBuffers(1, &c.vbuf);
     382            0 :             c.vbuf = 0;
     383              :         }
     384            0 :         c.as.cur.fr1 = -1;
     385              :     }
     386            0 :     if(ebuf)
     387              :     {
     388            0 :         glDeleteBuffers(1, &ebuf);
     389            0 :         ebuf = 0;
     390              :     }
     391            0 : }
     392              : 
     393            0 : void vertmodel::vertmeshgroup::preload()
     394              : {
     395            0 :     if(numframes > 1)
     396              :     {
     397            0 :         return;
     398              :     }
     399            0 :     if(!vbocache[0].vbuf)
     400              :     {
     401            0 :         genvbo(vbocache[0]);
     402              :     }
     403              : }
     404              : 
     405            0 : void vertmodel::vertmeshgroup::render(const AnimState *as, float, const vec &, const vec &, dynent *, part *p)
     406              : {
     407            0 :     if(as->cur.anim & Anim_NoRender)
     408              :     {
     409            0 :         for(part::linkedpart &l : p->links)
     410              :         {
     411            0 :             calctagmatrix(p, l.tag, *as, l.matrix);
     412              :         }
     413            0 :         return;
     414              :     }
     415            0 :     vbocacheentry *vc = nullptr;
     416            0 :     if(numframes<=1)
     417              :     {
     418            0 :         vc = vbocache.data();
     419              :     }
     420              :     else
     421              :     {
     422            0 :         for(size_t i = 0; i < maxvbocache; ++i)
     423              :         {
     424            0 :             vbocacheentry &c = vbocache[i];
     425            0 :             if(!c.vbuf)
     426              :             {
     427            0 :                 continue;
     428              :             }
     429            0 :             if(c.as==*as)
     430              :             {
     431            0 :                 vc = &c;
     432            0 :                 break;
     433              :             }
     434              :         }
     435            0 :         if(!vc)
     436              :         {
     437            0 :             for(size_t i = 0; i < maxvbocache; ++i)
     438              :             {
     439            0 :                 vc = &vbocache[i];
     440            0 :                 if(!vc->vbuf || vc->millis < lastmillis)
     441              :                 {
     442              :                     break;
     443              :                 }
     444              :             }
     445              :         }
     446              :     }
     447            0 :     if(!vc->vbuf)
     448              :     {
     449            0 :         genvbo(*vc);
     450              :     }
     451            0 :     if(numframes>1)
     452              :     {
     453            0 :         if(vc->as!=*as)
     454              :         {
     455            0 :             vc->as = *as;
     456            0 :             vc->millis = lastmillis;
     457            0 :             auto rendermeshes = getrendermeshes();
     458            0 :             for(auto i : rendermeshes)
     459              :             {
     460            0 :                 static_cast<vertmesh *>(*i)->interpverts(*as, reinterpret_cast<vvert *>(vdata));
     461              :             }
     462            0 :             gle::bindvbo(vc->vbuf);
     463            0 :             glBufferData(GL_ARRAY_BUFFER, vlen*vertsize, vdata, GL_STREAM_DRAW);
     464            0 :         }
     465            0 :         vc->millis = lastmillis;
     466              :     }
     467            0 :     bindvbo(as, p, *vc);
     468            0 :     LOOP_RENDER_MESHES(vertmesh, m,
     469              :     {
     470              :         p->skins[i].bind(m, as); //not a skeletal model, do not need to include trailing params
     471              :         m.render();
     472              :     });
     473            0 :     for(part::linkedpart &l : p->links)
     474              :     {
     475            0 :         calctagmatrix(p, l.tag, *as, l.matrix);
     476              :     }
     477              : }
        

Generated by: LCOV version 2.0-1