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

Generated by: LCOV version 2.0-1