LCOV - code coverage report
Current view: top level - engine/model - vertmodel.h (source / functions) Hit Total Coverage
Test: Libprimis Test Coverage Lines: 16 132 12.1 %
Date: 2024-11-22 05:07:59 Functions: 3 13 23.1 %

          Line data    Source code
       1             : class vertmodel : public animmodel
       2             : {
       3             :     public:
       4             :         struct vert final
       5             :         {
       6             :             vec pos, norm;
       7             :             vec4<float> tangent;
       8             :         };
       9             : 
      10             :         struct vvert final
      11             :         {
      12             :             vec pos;
      13             :             GenericVec2<half> tc;
      14             :             squat tangent;
      15             :         };
      16             : 
      17             :         struct vvertg final
      18             :         {
      19             :             vec4<half> pos;
      20             :             GenericVec2<half> tc;
      21             :             squat tangent;
      22             :         };
      23             : 
      24             :         struct tcvert final
      25             :         {
      26             :             vec2 tc;
      27             :         };
      28             : 
      29             :         struct tri final
      30             :         {
      31             :             uint vert[3];
      32             :         };
      33             : 
      34             :         struct vbocacheentry final
      35             :         {
      36             :             GLuint vbuf;
      37             :             AnimState as;
      38             :             int millis;
      39             : 
      40             :             vbocacheentry();
      41             :         };
      42             : 
      43             :         struct vertmesh : Mesh
      44             :         {
      45             :             public:
      46             :                 vert *verts;
      47             :                 tcvert *tcverts;
      48             :                 tri *tris;
      49             :                 int numverts, numtris;
      50             : 
      51             :                 vertmesh();
      52             :                 vertmesh(std::string_view name, meshgroup *m);
      53             : 
      54             :                 virtual ~vertmesh();
      55             : 
      56             :                 void smoothnorms(float limit = 0, bool areaweight = true);
      57             :                 void buildnorms(bool areaweight = true);
      58             :                 void calctangents(bool areaweight = true);
      59             :                 void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) const override final;
      60             :                 void genBIH(BIH::mesh &m) const override final;
      61             :                 void genshadowmesh(std::vector<triangle> &out, const matrix4x3 &m) const override final;
      62             : 
      63             :                 static void assignvert(vvertg &vv, int j, const tcvert &tc, const vert &v);
      64             : 
      65             :                 template<class T>
      66           0 :                 int genvbo(std::vector<uint> &idxs, int offset, std::vector<T> &vverts, int *htdata, int htlen)
      67             :                 {
      68           0 :                     voffset = offset;
      69           0 :                     minvert = UINT_MAX;
      70           0 :                     for(int i = 0; i < numtris; ++i)
      71             :                     {
      72           0 :                         const tri &t = tris[i];
      73           0 :                         for(int j = 0; j < 3; ++j)
      74             :                         {
      75           0 :                             const int index = t.vert[j];
      76           0 :                             const vert &v = verts[index];
      77           0 :                             const tcvert &tc = tcverts[index];
      78           0 :                             T vv;
      79           0 :                             assignvert(vv, index, tc, v);
      80             :                             const auto hashfn = std::hash<vec>();
      81           0 :                             const int htidx = hashfn(v.pos)&(htlen-1);
      82           0 :                             for(int k = 0; k < htlen; ++k)
      83             :                             {
      84           0 :                                 int &vidx = htdata[(htidx+k)&(htlen-1)];
      85           0 :                                 if(vidx < 0)
      86             :                                 {
      87           0 :                                     idxs.push_back(vverts.size());
      88           0 :                                     vidx = idxs.back();
      89           0 :                                     vverts.push_back(vv);
      90           0 :                                     break;
      91             :                                 }
      92           0 :                                 else if(!std::memcmp(&vverts[vidx], &vv, sizeof(vv)))
      93             :                                 {
      94           0 :                                     idxs.push_back(static_cast<uint>(vidx));
      95           0 :                                     minvert = std::min(minvert, idxs.back());
      96           0 :                                     break;
      97             :                                 }
      98             :                             }
      99             :                         }
     100             :                     }
     101           0 :                     minvert = std::min(minvert, static_cast<uint>(voffset));
     102           0 :                     maxvert = std::max(minvert, static_cast<uint>(vverts.size()-1));
     103           0 :                     elen = idxs.size();
     104           0 :                     return vverts.size()-voffset;
     105             :                 }
     106             : 
     107             :                 int genvbo(std::vector<uint> &idxs, int offset);
     108             : 
     109             :                 template<class T>
     110           0 :                 static void fillvert(T &vv, tcvert &tc, vert &v)
     111             :                 {
     112           0 :                     vv.tc = tc.tc;
     113           0 :                 }
     114             : 
     115             :                 template<class T>
     116           0 :                 void fillverts(T *vdata)
     117             :                 {
     118           0 :                     vdata += voffset;
     119           0 :                     for(int i = 0; i < numverts; ++i)
     120             :                     {
     121           0 :                         fillvert(vdata[i], tcverts[i], verts[i]);
     122             :                     }
     123           0 :                 }
     124             : 
     125             :                 template<class T>
     126           0 :                 void interpverts(const AnimState &as, T * RESTRICT vdata)
     127             :                 {
     128           0 :                     vdata += voffset;
     129           0 :                     const vert * RESTRICT vert1 = &verts[as.cur.fr1 * numverts],
     130           0 :                                * RESTRICT vert2 = &verts[as.cur.fr2 * numverts],
     131           0 :                                * RESTRICT pvert1 = as.interp<1 ? &verts[as.prev.fr1 * numverts] : nullptr,
     132           0 :                                * RESTRICT pvert2 = as.interp<1 ? &verts[as.prev.fr2 * numverts] : nullptr;
     133           0 :                     if(as.interp<1)
     134             :                     {
     135           0 :                         for(int i = 0; i < numverts; ++i)
     136             :                         {
     137           0 :                             T &v = vdata[i];
     138           0 :                             v.pos.lerp(vec().lerp(pvert1[i].pos, pvert2[i].pos, as.prev.t),
     139           0 :                                        vec().lerp(vert1[i].pos, vert2[i].pos, as.cur.t),
     140           0 :                                        as.interp);
     141           0 :                             v.tangent.lerp(vec4<float>().lerp(pvert1[i].tangent, pvert2[i].tangent, as.prev.t),
     142           0 :                                            vec4<float>().lerp(vert1[i].tangent, vert2[i].tangent, as.cur.t),
     143           0 :                                            as.interp);
     144             :                         }
     145             :                     }
     146             :                     else
     147             :                     {
     148           0 :                         for(int i = 0; i < numverts; ++i)
     149             :                         {
     150           0 :                             T &v = vdata[i];
     151           0 :                             v.pos.lerp(vert1[i].pos, vert2[i].pos, as.cur.t);
     152           0 :                             v.tangent.lerp(vert1[i].tangent, vert2[i].tangent, as.cur.t);
     153             :                         }
     154             :                     }
     155           0 :                 }
     156             : 
     157             :                 void render() const;
     158             :             private:
     159             :                 int voffset, elen;
     160             :                 uint minvert, maxvert;
     161             :         };
     162             : 
     163             :         struct tag final
     164             :         {
     165             :             std::string name;
     166             :             matrix4x3 matrix;
     167             : 
     168           0 :             tag() {}
     169             :         };
     170             : 
     171             :         struct vertmeshgroup : meshgroup
     172             :         {
     173             :             int numframes;
     174             :             //size equal to numtags * numframes
     175             :             //tags are ordered beneath frames; tag1frame1, tag2frame1, tag3frame1, tag1frame2, etc
     176             :             //deleted and re-created whenever a new tag is added with addtag();
     177             :             tag *tags;
     178             :             size_t numtags;
     179             : 
     180             :             static constexpr size_t maxvbocache = 16;
     181             :             std::array<vbocacheentry, 16> vbocache;
     182             : 
     183             :             GLuint ebuf;
     184             :             int vlen, vertsize;
     185             :             uchar *vdata;
     186             : 
     187             :             vertmeshgroup();
     188             :             virtual ~vertmeshgroup();
     189             : 
     190             :             virtual void concattagtransform(int i, const matrix4x3 &m, matrix4x3 &n) const override final;
     191             :             bool addtag(std::string_view name, const matrix4x3 &matrix);
     192             :             std::optional<size_t> findtag(std::string_view name) override final;
     193             : 
     194             :             /**
     195             :              * @brief Returns the number of frames associated with this model.
     196             :              *
     197             :              * This is the numframes field in the meshgroup object.
     198             :              */
     199             :             int totalframes() const override final;
     200             :             void calctagmatrix(const part *p, int i, const AnimState &as, matrix4 &matrix) const;
     201             : 
     202             :             void genvbo(vbocacheentry &vc);
     203             : 
     204             :             template<class T>
     205           0 :             void bindvbo(const AnimState *as, const part *p, const vbocacheentry &vc)
     206             :             {
     207           0 :                 const T *vverts = 0;
     208           0 :                 bindpos(ebuf, vc.vbuf, &vverts->pos, vertsize);
     209           0 :                 if(as->cur.anim & Anim_NoSkin)
     210             :                 {
     211           0 :                     if(enabletangents)
     212             :                     {
     213           0 :                         disabletangents();
     214             :                     }
     215           0 :                     if(p->alphatested())
     216             :                     {
     217           0 :                         bindtc(&vverts->tc, vertsize);
     218             :                     }
     219           0 :                     else if(enabletc)
     220             :                     {
     221           0 :                         disabletc();
     222             :                     }
     223             :                 }
     224             :                 else
     225             :                 {
     226           0 :                     bindtangents(&vverts->tangent, vertsize);
     227           0 :                     bindtc(&vverts->tc, vertsize);
     228             :                 }
     229           0 :                 if(enablebones)
     230             :                 {
     231           0 :                     disablebones();
     232             :                 }
     233           0 :             }
     234             : 
     235             :             void bindvbo(const AnimState *as, const part *p, const vbocacheentry &vc);
     236             :             /**
     237             :              * @brief Returns a pointer to this object.
     238             :              *
     239             :              * There is no appropriate pointer to pass other than itself, since
     240             :              * this is not a skeletal model
     241             :              */
     242             :             void *animkey() override final;
     243             :             void cleanup() override final;
     244             :             void preload() override final;
     245             :             void render(const AnimState *as, float, const vec &, const vec &, dynent *, part *p) override final;
     246             : 
     247             :             virtual bool load(const char *name, float smooth) = 0;
     248             :         };
     249             : 
     250             :         virtual vertmeshgroup *newmeshes() = 0;
     251             : 
     252             :         meshgroup *sharemeshes(const char *name, float smooth = 2);
     253             : 
     254             :         vertmodel(std::string name);
     255             : 
     256             :     private:
     257             :         meshgroup *loadmeshes(const char *name, float smooth = 2);
     258             : 
     259             : };
     260             : 
     261             : template<class MDL>
     262             : struct vertloader : modelloader<MDL, vertmodel>
     263             : {
     264           0 :     vertloader(std::string name) : modelloader<MDL, vertmodel>(name) {}
     265             : };
     266             : 
     267             : template<class MDL>
     268             : struct vertcommands : modelcommands<MDL>
     269             : {
     270             :     typedef struct MDL::vertmeshgroup meshgroup;
     271             :     typedef class  MDL::part part;
     272             :     typedef class  MDL::skin skin;
     273             : 
     274           1 :     static void loadpart(const char *model, const float *smooth)
     275             :     {
     276           1 :         if(!MDL::loading)
     277             :         {
     278           1 :             conoutf("not loading an %s", MDL::formatname());
     279           1 :             return;
     280             :         }
     281           0 :         DEF_FORMAT_STRING(filename, "%s/%s", MDL::dir.c_str(), model);
     282           0 :         part &mdl = MDL::loading->addpart();
     283           0 :         if(mdl.index)
     284             :         {
     285           0 :             mdl.disablepitch();
     286             :         }
     287           0 :         mdl.meshes = MDL::loading->sharemeshes(path(filename), *smooth > 0 ? std::cos(std::clamp(*smooth, 0.0f, 180.0f)/RAD) : 2);
     288           0 :         if(!mdl.meshes)
     289             :         {
     290           0 :             conoutf("could not load %s", filename);
     291             :         }
     292             :         else
     293             :         {
     294           0 :             mdl.initskins();
     295             :         }
     296             :     }
     297             : 
     298           1 :     static void settag(const char *tagname, const float *tx, const float *ty, const float *tz, const float *rx, const float *ry, const float *rz)
     299             :     {
     300           1 :         if(!MDL::loading || MDL::loading->parts.empty())
     301             :         {
     302           1 :             conoutf("not loading an %s", MDL::formatname());
     303           1 :             return;
     304             :         }
     305           0 :         const part &mdl = *static_cast<part *>(MDL::loading->parts.back());
     306           0 :         float cx = *rx ? std::cos(*rx/(2*RAD)) : 1,
     307           0 :               sx = *rx ? std::sin(*rx/(2*RAD)) : 0,
     308           0 :               cy = *ry ? std::cos(*ry/(2*RAD)) : 1,
     309           0 :               sy = *ry ? std::sin(*ry/(2*RAD)) : 0,
     310           0 :               cz = *rz ? std::cos(*rz/(2*RAD)) : 1,
     311           0 :               sz = *rz ? std::sin(*rz/(2*RAD)) : 0;
     312             :         //matrix m created from (matrix3 created from quat) + (vec) appended afterwards
     313           0 :         matrix4x3 m(static_cast<matrix3>(quat(sx*cy*cz - cx*sy*sz,
     314           0 :                                               cx*sy*cz + sx*cy*sz,
     315           0 :                                               cx*cy*sz - sx*sy*cz,
     316           0 :                                               cx*cy*cz + sx*sy*sz)),
     317           0 :                     vec(*tx, *ty, *tz));
     318             : 
     319           0 :         static_cast<meshgroup *>(mdl.meshes)->addtag(tagname, m);
     320             :     }
     321             : 
     322           0 :     static void setpitch(const float *pitchscale, const float *pitchoffset, const float *pitchmin, const float *pitchmax)
     323             :     {
     324           0 :         if(!MDL::loading || MDL::loading->parts.empty())
     325             :         {
     326           0 :             conoutf("not loading an %s", MDL::formatname());
     327           0 :             return;
     328             :         }
     329           0 :         part &mdl = *MDL::loading->parts.back();
     330           0 :         mdl.pitchscale = *pitchscale;
     331           0 :         mdl.pitchoffset = *pitchoffset;
     332           0 :         if(*pitchmin || *pitchmax)
     333             :         {
     334           0 :             mdl.pitchmin = *pitchmin;
     335           0 :             mdl.pitchmax = *pitchmax;
     336             :         }
     337             :         else
     338             :         {
     339           0 :             mdl.pitchmin = -360*std::fabs(mdl.pitchscale) + mdl.pitchoffset;
     340           0 :             mdl.pitchmax =  360*std::fabs(mdl.pitchscale) + mdl.pitchoffset;
     341             :         }
     342             :     }
     343             : 
     344           0 :     static void setanim(const char *anim, const int *frame, const int *range, const float *speed, const int *priority)
     345             :     {
     346           0 :         if(!MDL::loading || MDL::loading->parts.empty())
     347             :         {
     348           0 :             conoutf("not loading an %s", MDL::formatname());
     349           0 :             return;
     350             :         }
     351           0 :         std::vector<size_t> anims = findanims(anim);
     352           0 :         if(anims.empty())
     353             :         {
     354           0 :             conoutf("could not find animation %s", anim);
     355             :         }
     356             :         else
     357             :         {
     358           0 :             for(const size_t &i : anims)
     359             :             {
     360           0 :                 MDL::loading->parts.back()->setanim(0, i, *frame, *range, *speed, *priority);
     361             :             }
     362             :         }
     363           0 :     }
     364             : 
     365           1 :     vertcommands()
     366           1 :     {
     367           1 :         if(MDL::multiparted())
     368             :         {
     369           1 :             this->modelcommand(loadpart, "load", "sf"); //<fmt>load [model] [smooth]
     370             :         }
     371           1 :         this->modelcommand(settag, "tag", "sffffff"); //<fmt>tag [tagname] [tx] [ty] [tz] [rx] [ry] [rz]
     372           1 :         this->modelcommand(setpitch, "pitch", "ffff"); //<fmt>pitch [scale] [offset] [min] [max]
     373           1 :         if(MDL::cananimate())
     374             :         {
     375           0 :             this->modelcommand(setanim, "anim", "siiff"); //<fmt>anim [anim] [frame] [range] [speed] [priority]
     376             :         }
     377           1 :     }
     378             : };

Generated by: LCOV version 1.14