1 /* Copyright (C) 2021 Wildfire Games.
2 * This file is part of 0 A.D.
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.
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.
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/>.
19 * Defines a raw 3d model.
22 #ifndef INCLUDED_MODELDEF
23 #define INCLUDED_MODELDEF
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"
32 #include "renderer/VertexArray.h"
36 #include <unordered_map>
40 class CSkeletonAnimDef
;
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.
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
52 * @see CModel::m_BoneMatrices
56 /// Name of the prop point
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.
67 * Rotation of the prop model that will be attached at this point. Also specified as part of @ref m_Transform.
70 CQuaternion m_Rotation
;
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
79 CMatrix3D m_Transform
;
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.
88 ///////////////////////////////////////////////////////////////////////////////
89 // SVertexBlend: structure containing the necessary data for blending vertices
90 // with multiple bones
94 // index of the influencing bone, or 0xff if none
96 // weight of the influence; all weights sum to 1
99 bool operator==(const SVertexBlend
& o
) const
101 return !memcmp(m_Bone
, o
.m_Bone
, sizeof(m_Bone
)) && !memcmp(m_Weight
, o
.m_Weight
, sizeof(m_Weight
));
105 ///////////////////////////////////////////////////////////////////////////////
106 // SModelVertex: structure containing per-vertex data
114 SVertexBlend m_Blend
;
118 ///////////////////////////////////////////////////////////////////////////////
119 // SModelFace: structure containing per-face data
122 // indices of the 3 vertices on this face
127 ////////////////////////////////////////////////////////////////////////////////////////
129 class CModelDefRPrivate
132 CModelDefRPrivate() { }
133 virtual ~CModelDefRPrivate() { }
137 ////////////////////////////////////////////////////////////////////////////////////////
138 // CModelDef: a raw 3D model; describes the vertices, faces, skinning and skeletal
139 // information of a model
142 NONCOPYABLE(CModelDef
);
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 };
155 // model I/O functions
157 static void Save(const VfsPath
& filename
,const CModelDef
* mdef
);
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
166 static CModelDef
* Load(const VfsPath
& filename
, const VfsPath
& name
);
169 // accessor: get vertex data
170 size_t GetNumVertices() const { return m_NumVertices
; }
171 SModelVertex
* GetVertices() const { return m_pVertices
; }
173 // accessor: get number of UV sets
174 size_t GetNumUVsPerVertex() const { return m_NumUVsPerVertex
; }
176 const std::vector
<CVector2D
>& GetUVCoordinates() const { return m_UVCoordinates
; }
178 // accessor: get face data
179 size_t GetNumFaces() const { return m_NumFaces
; }
180 SModelFace
* GetFaces() const { return m_pFaces
; }
182 // accessor: get bone data
183 size_t GetNumBones() const { return m_NumBones
; }
184 CBoneState
* GetBones() const { return m_Bones
; }
185 CMatrix3D
* GetInverseBindBoneMatrices() { return m_InverseBindBoneMatrices
; }
187 // accessor: get blend data
188 size_t GetNumBlends() const { return m_NumBlends
; }
189 SVertexBlend
* GetBlends() const { return m_pBlends
; }
190 size_t* GetBlendIndices() const { return m_pBlendIndices
; }
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;
197 * @param anim may be null
199 void GetMaxBounds(CSkeletonAnimDef
* anim
, bool loop
, CBoundingBoxAligned
& result
);
202 * Transform the given vertex's position from the bind pose into the new pose.
204 * @return new world-space vertex coordinates
206 static CVector3D
SkinPoint(const SModelVertex
& vtx
,
207 const CMatrix3D newPoseMatrices
[]);
210 * Transform the given vertex's normal from the bind pose into the new pose.
212 * @return new world-space vertex normal
214 static CVector3D
SkinNormal(const SModelVertex
& vtx
,
215 const CMatrix3D newPoseMatrices
[]);
218 * Transform vertices' positions and normals.
219 * (This is equivalent to looping over SkinPoint and SkinNormal,
220 * but slightly more efficient.)
222 static void(*SkinPointsAndNormals
)(
224 const VertexArrayIterator
<CVector3D
>& Position
,
225 const VertexArrayIterator
<CVector3D
>& Normal
,
226 const SModelVertex
* vertices
,
227 const size_t* blendIndices
,
228 const CMatrix3D newPoseMatrices
[]);
231 * Blend bone matrices together to fill bone palette.
233 void BlendBoneMatrices(CMatrix3D boneMatrices
[]);
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.
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.
246 * postconditions : data is bound to the lifetime of this CModelDef
249 void SetRenderData(const void* key
, CModelDefRPrivate
* data
);
251 // accessor: render data
252 CModelDefRPrivate
* GetRenderData(const void* key
) const;
254 // accessor: get model name (for debugging)
255 const VfsPath
& GetName() const { return m_Name
; }
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
265 SModelFace
* m_pFaces
;
266 // bone data - default model pose
269 CMatrix3D
* m_InverseBindBoneMatrices
;
272 SVertexBlend
*m_pBlends
;
273 size_t* m_pBlendIndices
;
275 std::vector
<SPropPoint
> m_PropPoints
;
278 VfsPath m_Name
; // filename
280 // Maximal bounding box of this mesh for a given animation.
281 std::unordered_map
<u32
, CBoundingBoxAligned
> m_MaxBoundsPerAnimDef
;
283 // renderdata shared by models of the same modeldef,
285 typedef std::map
<const void*, CModelDefRPrivate
*> RenderDataMap
;
286 RenderDataMap m_RenderData
;
290 * Detects CPU caps and activates the best possible codepath.
292 extern void ModelDefActivateFastImpl();