LCOV - code coverage report
Current view: top level - source/graphics - ModelDef.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 4 18 22.2 %
Date: 2023-01-19 00:18:29 Functions: 5 21 23.8 %

          Line data    Source code
       1             : /* Copyright (C) 2021 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : /*
      19             :  * Defines a raw 3d model.
      20             :  */
      21             : 
      22             : #ifndef INCLUDED_MODELDEF
      23             : #define INCLUDED_MODELDEF
      24             : 
      25             : #include "maths/BoundingBoxAligned.h"
      26             : #include "maths/Matrix3D.h"
      27             : #include "maths/Quaternion.h"
      28             : #include "maths/Vector2D.h"
      29             : #include "maths/Vector3D.h"
      30             : #include "lib/file/vfs/vfs_path.h"
      31             : #include "ps/CStr.h"
      32             : #include "renderer/VertexArray.h"
      33             : 
      34             : #include <cstring>
      35             : #include <map>
      36             : #include <unordered_map>
      37             : #include <vector>
      38             : 
      39             : class CBoneState;
      40             : class CSkeletonAnimDef;
      41             : 
      42             : /**
      43             :  * Describes the position of a prop point within its parent model. A prop point is the location within a parent model
      44             :  * where the prop's origin will be attached.
      45             :  *
      46             :  * A prop point is specified by its transformation matrix (or separately by its position and rotation), which
      47             :  * can be relative to either the parent model's origin, or one of the parent's bones. If the parent model is boned,
      48             :  * then the @ref m_BoneIndex field may specify a bone to which the transformation matrix is relative (see
      49             :  * @ref CModel::m_BoneMatrices). Otherwise, the transformation matrix is assumed to be relative to the parent model's
      50             :  * origin.
      51             :  *
      52             :  * @see CModel::m_BoneMatrices
      53             :  */
      54           6 : struct SPropPoint
      55             : {
      56             :     /// Name of the prop point
      57             :     CStr m_Name;
      58             : 
      59             :     /**
      60             :      * Position of the point within the parent model, relative to either the parent model's origin or one of the parent
      61             :      * model's bones if applicable. Also specified as part of @ref m_Transform.
      62             :      * @see m_Transform
      63             :      */
      64             :     CVector3D m_Position;
      65             : 
      66             :     /**
      67             :      * Rotation of the prop model that will be attached at this point. Also specified as part of @ref m_Transform.
      68             :      * @see m_Transform
      69             :      */
      70             :     CQuaternion m_Rotation;
      71             : 
      72             :     /**
      73             :      * Object to parent space transformation. Combines both @ref m_Position and @ref m_Rotation in a single
      74             :      * transformation matrix. This transformation is relative to either the parent model's origin, or one of its
      75             :      * bones, depending on whether it is skeletal. If relative to a bone, then the bone in the parent model to
      76             :      * which this transformation is relative may be found by m_BoneIndex.
      77             :      * @see m_Position, m_Rotation
      78             :      */
      79             :     CMatrix3D m_Transform;
      80             : 
      81             :     /**
      82             :      * Index of parent bone to which this prop point is relative, if any. The value 0xFF specifies that either the parent
      83             :      * model is unboned, or that this prop point is relative to the parent model's origin rather than one if its bones.
      84             :      */
      85             :     u8 m_BoneIndex;
      86             : };
      87             : 
      88             : ///////////////////////////////////////////////////////////////////////////////
      89             : // SVertexBlend: structure containing the necessary data for blending vertices
      90             : // with multiple bones
      91             : struct SVertexBlend
      92             : {
      93             :     enum { SIZE = 4 };
      94             :     // index of the influencing bone, or 0xff if none
      95             :     u8 m_Bone[SIZE];
      96             :     // weight of the influence; all weights sum to 1
      97             :     float m_Weight[SIZE];
      98             : 
      99           0 :     bool operator==(const SVertexBlend& o) const
     100             :     {
     101           0 :         return !memcmp(m_Bone, o.m_Bone, sizeof(m_Bone)) && !memcmp(m_Weight, o.m_Weight, sizeof(m_Weight));
     102             :     }
     103             : };
     104             : 
     105             : ///////////////////////////////////////////////////////////////////////////////
     106             : // SModelVertex: structure containing per-vertex data
     107         746 : struct SModelVertex
     108             : {
     109             :     // vertex position
     110             :     CVector3D m_Coords;
     111             :     // vertex normal
     112             :     CVector3D m_Norm;
     113             :     // vertex blend data
     114             :     SVertexBlend m_Blend;
     115             : };
     116             : 
     117             : 
     118             : ///////////////////////////////////////////////////////////////////////////////
     119             : // SModelFace: structure containing per-face data
     120             : struct SModelFace
     121             : {
     122             :     // indices of the 3 vertices on this face
     123             :     u16 m_Verts[3];
     124             : };
     125             : 
     126             : 
     127             : ////////////////////////////////////////////////////////////////////////////////////////
     128             : // CModelDefRPrivate
     129             : class CModelDefRPrivate
     130             : {
     131             : public:
     132           0 :     CModelDefRPrivate() { }
     133           0 :     virtual ~CModelDefRPrivate() { }
     134             : };
     135             : 
     136             : 
     137             : ////////////////////////////////////////////////////////////////////////////////////////
     138             : // CModelDef: a raw 3D model; describes the vertices, faces, skinning and skeletal
     139             : // information of a model
     140             : class CModelDef
     141             : {
     142             :     NONCOPYABLE(CModelDef);
     143             : 
     144             : public:
     145             :     // current file version given to saved animations
     146             :     enum { FILE_VERSION = 3 };
     147             :     // supported file read version - files with a version less than this will be rejected
     148             :     enum { FILE_READ_VERSION = 1 };
     149             : 
     150             : 
     151             : public:
     152             :     CModelDef();
     153             :     ~CModelDef();
     154             : 
     155             :     // model I/O functions
     156             : 
     157             :     static void Save(const VfsPath& filename,const CModelDef* mdef);
     158             : 
     159             :     /**
     160             :      * Loads a PMD file.
     161             :      * @param filename VFS path of .pmd file to load
     162             :      * @param name arbitrary name to give the model for debugging purposes (usually pathname)
     163             :      * @return the model - always non-NULL
     164             :      * @throw PSERROR_File if it can't load the model
     165             :      */
     166             :     static CModelDef* Load(const VfsPath& filename, const VfsPath& name);
     167             : 
     168             : public:
     169             :     // accessor: get vertex data
     170           0 :     size_t GetNumVertices() const { return m_NumVertices; }
     171           0 :     SModelVertex* GetVertices() const { return m_pVertices; }
     172             : 
     173             :     // accessor: get number of UV sets
     174           0 :     size_t GetNumUVsPerVertex() const { return m_NumUVsPerVertex; }
     175             : 
     176           0 :     const std::vector<CVector2D>& GetUVCoordinates() const { return m_UVCoordinates;  }
     177             : 
     178             :     // accessor: get face data
     179           0 :     size_t GetNumFaces() const { return m_NumFaces; }
     180           0 :     SModelFace* GetFaces() const { return m_pFaces; }
     181             : 
     182             :     // accessor: get bone data
     183           0 :     size_t GetNumBones() const { return m_NumBones; }
     184           6 :     CBoneState* GetBones() const { return m_Bones; }
     185           0 :     CMatrix3D* GetInverseBindBoneMatrices() { return m_InverseBindBoneMatrices; }
     186             : 
     187             :     // accessor: get blend data
     188           0 :     size_t GetNumBlends() const { return m_NumBlends; }
     189             :     SVertexBlend* GetBlends() const { return m_pBlends; }
     190           0 :     size_t* GetBlendIndices() const { return m_pBlendIndices; }
     191             : 
     192             :     // find and return pointer to prop point matching given name; return
     193             :     // null if no match (case insensitive search)
     194             :     const SPropPoint* FindPropPoint(const char* name) const;
     195             : 
     196             :     /**
     197             :      * @param anim may be null
     198             :      */
     199             :     void GetMaxBounds(CSkeletonAnimDef* anim, bool loop, CBoundingBoxAligned& result);
     200             : 
     201             :     /**
     202             :      * Transform the given vertex's position from the bind pose into the new pose.
     203             :      *
     204             :      * @return new world-space vertex coordinates
     205             :      */
     206             :     static CVector3D SkinPoint(const SModelVertex& vtx,
     207             :         const CMatrix3D newPoseMatrices[]);
     208             : 
     209             :     /**
     210             :      * Transform the given vertex's normal from the bind pose into the new pose.
     211             :      *
     212             :      * @return new world-space vertex normal
     213             :      */
     214             :     static CVector3D SkinNormal(const SModelVertex& vtx,
     215             :         const CMatrix3D newPoseMatrices[]);
     216             : 
     217             :     /**
     218             :      * Transform vertices' positions and normals.
     219             :      * (This is equivalent to looping over SkinPoint and SkinNormal,
     220             :      * but slightly more efficient.)
     221             :      */
     222             :     static void(*SkinPointsAndNormals)(
     223             :         size_t numVertices,
     224             :         const VertexArrayIterator<CVector3D>& Position,
     225             :         const VertexArrayIterator<CVector3D>& Normal,
     226             :         const SModelVertex* vertices,
     227             :         const size_t* blendIndices,
     228             :         const CMatrix3D newPoseMatrices[]);
     229             : 
     230             :     /**
     231             :      * Blend bone matrices together to fill bone palette.
     232             :      */
     233             :     void BlendBoneMatrices(CMatrix3D boneMatrices[]);
     234             : 
     235             :     /**
     236             :      * Register renderer private data. Use the key to
     237             :      * distinguish between private data used by different render paths.
     238             :      * The private data will be managed by this CModelDef object:
     239             :      * It will be deleted when CModelDef is destructed or when private
     240             :      * data is registered using the same key.
     241             :      *
     242             :      * @param key The opaque key that is used to identify the caller.
     243             :      * The given private data can be retrieved by passing key to GetRenderData.
     244             :      * @param data The private data.
     245             :      *
     246             :      * postconditions : data is bound to the lifetime of this CModelDef
     247             :      * object.
     248             :      */
     249             :     void SetRenderData(const void* key, CModelDefRPrivate* data);
     250             : 
     251             :     // accessor: render data
     252             :     CModelDefRPrivate* GetRenderData(const void* key) const;
     253             : 
     254             :     // accessor: get model name (for debugging)
     255           4 :     const VfsPath& GetName() const { return m_Name; }
     256             : 
     257             : public:
     258             :     // vertex data
     259             :     size_t m_NumVertices;
     260             :     SModelVertex* m_pVertices;
     261             :     std::vector<CVector2D> m_UVCoordinates;
     262             :     size_t m_NumUVsPerVertex; // number of UV pairs per vertex
     263             :     // face data
     264             :     size_t m_NumFaces;
     265             :     SModelFace* m_pFaces;
     266             :     // bone data - default model pose
     267             :     size_t m_NumBones;
     268             :     CBoneState* m_Bones;
     269             :     CMatrix3D* m_InverseBindBoneMatrices;
     270             :     // blend data
     271             :     size_t m_NumBlends;
     272             :     SVertexBlend *m_pBlends;
     273             :     size_t* m_pBlendIndices;
     274             :     // prop point data
     275             :     std::vector<SPropPoint> m_PropPoints;
     276             : 
     277             : private:
     278             :     VfsPath m_Name; // filename
     279             : 
     280             :     // Maximal bounding box of this mesh for a given animation.
     281             :     std::unordered_map<u32, CBoundingBoxAligned> m_MaxBoundsPerAnimDef;
     282             : 
     283             :     // renderdata shared by models of the same modeldef,
     284             :     // by render path
     285             :     typedef std::map<const void*, CModelDefRPrivate*> RenderDataMap;
     286             :     RenderDataMap m_RenderData;
     287             : };
     288             : 
     289             : /**
     290             :  * Detects CPU caps and activates the best possible codepath.
     291             :  */
     292             : extern void ModelDefActivateFastImpl();
     293             : 
     294             : #endif
     295             : 

Generated by: LCOV version 1.13