LCOV - code coverage report
Current view: top level - engine/model - vertmodel.cpp (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 0 238 0.0 %
Date: 2024-11-22 05:07:59 Functions: 0 31 0.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(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, int j, 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<uint> &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(int 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<uint> 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 1.14