2011-11-10 00:11:28 +01:00
|
|
|
/* Copyright (C) 2011 Wildfire Games.
|
2009-04-18 19:00:33 +02:00
|
|
|
* This file is part of 0 A.D.
|
|
|
|
*
|
|
|
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* 0 A.D. is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2009-04-18 19:51:05 +02:00
|
|
|
/*
|
|
|
|
* Defines a raw 3d model.
|
2007-05-07 18:33:24 +02:00
|
|
|
*/
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2007-05-07 18:33:24 +02:00
|
|
|
#ifndef INCLUDED_MODELDEF
|
|
|
|
#define INCLUDED_MODELDEF
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "ps/CStr.h"
|
2020-11-21 12:20:29 +01:00
|
|
|
#include "maths/Matrix3D.h"
|
2012-07-24 00:49:46 +02:00
|
|
|
#include "maths/Vector2D.h"
|
2006-06-02 04:10:27 +02:00
|
|
|
#include "maths/Vector3D.h"
|
2006-12-15 17:09:30 +01:00
|
|
|
#include "maths/Quaternion.h"
|
2008-01-07 21:03:19 +01:00
|
|
|
#include "lib/file/vfs/vfs_path.h"
|
2010-09-24 18:54:20 +02:00
|
|
|
#include "renderer/VertexArray.h"
|
2005-10-25 04:00:09 +02:00
|
|
|
#include <map>
|
2011-07-13 01:48:05 +02:00
|
|
|
#include <cstring>
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2006-12-15 17:09:30 +01:00
|
|
|
class CBoneState;
|
2004-11-08 23:02:01 +01:00
|
|
|
|
2011-11-25 07:36:13 +01:00
|
|
|
/**
|
|
|
|
* Describes the position of a prop point within its parent model. A prop point is the location within a parent model
|
|
|
|
* where the prop's origin will be attached.
|
2016-11-23 12:18:37 +01:00
|
|
|
*
|
2011-11-25 07:36:13 +01:00
|
|
|
* A prop point is specified by its transformation matrix (or separately by its position and rotation), which
|
2016-11-23 12:18:37 +01:00
|
|
|
* can be relative to either the parent model's origin, or one of the parent's bones. If the parent model is boned,
|
|
|
|
* then the @ref m_BoneIndex field may specify a bone to which the transformation matrix is relative (see
|
|
|
|
* @ref CModel::m_BoneMatrices). Otherwise, the transformation matrix is assumed to be relative to the parent model's
|
2011-11-25 07:36:13 +01:00
|
|
|
* origin.
|
2016-11-23 12:18:37 +01:00
|
|
|
*
|
2011-11-25 07:36:13 +01:00
|
|
|
* @see CModel::m_BoneMatrices
|
|
|
|
*/
|
2004-05-30 02:46:58 +02:00
|
|
|
struct SPropPoint
|
|
|
|
{
|
2011-11-25 07:36:13 +01:00
|
|
|
/// Name of the prop point
|
2004-05-30 02:46:58 +02:00
|
|
|
CStr m_Name;
|
2011-11-25 07:36:13 +01:00
|
|
|
|
|
|
|
/**
|
2016-11-23 12:18:37 +01:00
|
|
|
* Position of the point within the parent model, relative to either the parent model's origin or one of the parent
|
2011-11-25 07:36:13 +01:00
|
|
|
* model's bones if applicable. Also specified as part of @ref m_Transform.
|
|
|
|
* @see m_Transform
|
|
|
|
*/
|
2004-05-30 02:46:58 +02:00
|
|
|
CVector3D m_Position;
|
2011-11-25 07:36:13 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Rotation of the prop model that will be attached at this point. Also specified as part of @ref m_Transform.
|
|
|
|
* @see m_Transform
|
|
|
|
*/
|
2004-05-30 02:46:58 +02:00
|
|
|
CQuaternion m_Rotation;
|
2011-11-25 07:36:13 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Object to parent space transformation. Combines both @ref m_Position and @ref m_Rotation in a single
|
|
|
|
* transformation matrix. This transformation is relative to either the parent model's origin, or one of its
|
|
|
|
* bones, depending on whether it is skeletal. If relative to a bone, then the bone in the parent model to
|
|
|
|
* which this transformation is relative may be found by m_BoneIndex.
|
|
|
|
* @see m_Position, m_Rotation
|
|
|
|
*/
|
2004-05-30 02:46:58 +02:00
|
|
|
CMatrix3D m_Transform;
|
2011-11-25 07:36:13 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Index of parent bone to which this prop point is relative, if any. The value 0xFF specifies that either the parent
|
|
|
|
* model is unboned, or that this prop point is relative to the parent model's origin rather than one if its bones.
|
|
|
|
*/
|
2004-05-30 02:46:58 +02:00
|
|
|
u8 m_BoneIndex;
|
|
|
|
};
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2016-11-23 12:18:37 +01:00
|
|
|
// SVertexBlend: structure containing the necessary data for blending vertices
|
|
|
|
// with multiple bones
|
2004-05-29 22:56:24 +02:00
|
|
|
struct SVertexBlend
|
|
|
|
{
|
|
|
|
enum { SIZE = 4 };
|
|
|
|
// index of the influencing bone, or 0xff if none
|
|
|
|
u8 m_Bone[SIZE];
|
|
|
|
// weight of the influence; all weights sum to 1
|
|
|
|
float m_Weight[SIZE];
|
2011-07-13 01:48:05 +02:00
|
|
|
|
|
|
|
bool operator==(const SVertexBlend& o) const
|
|
|
|
{
|
|
|
|
return !memcmp(m_Bone, o.m_Bone, sizeof(m_Bone)) && !memcmp(m_Weight, o.m_Weight, sizeof(m_Weight));
|
|
|
|
}
|
2004-05-29 22:56:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// SModelVertex: structure containing per-vertex data
|
|
|
|
struct SModelVertex
|
|
|
|
{
|
|
|
|
// vertex position
|
|
|
|
CVector3D m_Coords;
|
|
|
|
// vertex normal
|
|
|
|
CVector3D m_Norm;
|
|
|
|
// vertex UVs
|
2012-07-24 00:49:46 +02:00
|
|
|
std::vector<float> m_UVs;
|
2004-05-29 22:56:24 +02:00
|
|
|
// vertex blend data
|
|
|
|
SVertexBlend m_Blend;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// SModelFace: structure containing per-face data
|
|
|
|
struct SModelFace
|
|
|
|
{
|
|
|
|
// indices of the 3 vertices on this face
|
|
|
|
u16 m_Verts[3];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2005-10-02 23:11:11 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
2005-10-25 04:00:09 +02:00
|
|
|
// CModelDefRPrivate
|
|
|
|
class CModelDefRPrivate
|
2005-10-02 23:11:11 +02:00
|
|
|
{
|
|
|
|
public:
|
2005-10-25 04:00:09 +02:00
|
|
|
CModelDefRPrivate() { }
|
|
|
|
virtual ~CModelDefRPrivate() { }
|
2005-10-02 23:11:11 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
2016-11-23 12:18:37 +01:00
|
|
|
// CModelDef: a raw 3D model; describes the vertices, faces, skinning and skeletal
|
2004-05-29 22:56:24 +02:00
|
|
|
// information of a model
|
|
|
|
class CModelDef
|
|
|
|
{
|
2012-04-12 17:43:59 +02:00
|
|
|
NONCOPYABLE(CModelDef);
|
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
public:
|
|
|
|
// current file version given to saved animations
|
2006-12-15 17:09:30 +01:00
|
|
|
enum { FILE_VERSION = 3 };
|
2004-05-29 22:56:24 +02:00
|
|
|
// supported file read version - files with a version less than this will be rejected
|
|
|
|
enum { FILE_READ_VERSION = 1 };
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
CModelDef();
|
2006-12-20 04:22:24 +01:00
|
|
|
~CModelDef();
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// model I/O functions
|
2006-12-20 04:22:24 +01:00
|
|
|
|
2008-01-07 21:03:19 +01:00
|
|
|
static void Save(const VfsPath& filename,const CModelDef* mdef);
|
2006-12-20 04:22:24 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads a PMD file.
|
|
|
|
* @param filename VFS path of .pmd file to load
|
2009-11-03 22:46:35 +01:00
|
|
|
* @param name arbitrary name to give the model for debugging purposes (usually pathname)
|
2006-12-20 04:22:24 +01:00
|
|
|
* @return the model - always non-NULL
|
|
|
|
* @throw PSERROR_File if it can't load the model
|
|
|
|
*/
|
2009-11-03 22:46:35 +01:00
|
|
|
static CModelDef* Load(const VfsPath& filename, const VfsPath& name);
|
2016-11-23 12:18:37 +01:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
public:
|
|
|
|
// accessor: get vertex data
|
2011-07-13 01:48:05 +02:00
|
|
|
size_t GetNumVertices() const { return m_NumVertices; }
|
2004-10-06 20:45:59 +02:00
|
|
|
SModelVertex* GetVertices() const { return m_pVertices; }
|
2016-11-23 12:18:37 +01:00
|
|
|
|
2012-07-24 00:49:46 +02:00
|
|
|
// accessor: get number of UV sets
|
|
|
|
size_t GetNumUVsPerVertex() const { return m_NumUVsPerVertex; }
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// accessor: get face data
|
2011-07-13 01:48:05 +02:00
|
|
|
size_t GetNumFaces() const { return m_NumFaces; }
|
2004-10-06 20:45:59 +02:00
|
|
|
SModelFace* GetFaces() const { return m_pFaces; }
|
2004-05-29 22:56:24 +02:00
|
|
|
|
|
|
|
// accessor: get bone data
|
2011-07-13 01:48:05 +02:00
|
|
|
size_t GetNumBones() const { return m_NumBones; }
|
2004-10-06 20:45:59 +02:00
|
|
|
CBoneState* GetBones() const { return m_Bones; }
|
2012-04-12 17:43:59 +02:00
|
|
|
CMatrix3D* GetInverseBindBoneMatrices() { return m_InverseBindBoneMatrices; }
|
2004-10-06 20:45:59 +02:00
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
// accessor: get blend data
|
|
|
|
size_t GetNumBlends() const { return m_NumBlends; }
|
|
|
|
SVertexBlend* GetBlends() const { return m_pBlends; }
|
|
|
|
size_t* GetBlendIndices() const { return m_pBlendIndices; }
|
|
|
|
|
2004-05-30 02:46:58 +02:00
|
|
|
// find and return pointer to prop point matching given name; return
|
|
|
|
// null if no match (case insensitive search)
|
2010-11-20 21:16:06 +01:00
|
|
|
const SPropPoint* FindPropPoint(const char* name) const;
|
2004-05-29 22:56:24 +02:00
|
|
|
|
2005-10-25 04:00:09 +02:00
|
|
|
/**
|
2006-12-15 17:09:30 +01:00
|
|
|
* Transform the given vertex's position from the bind pose into the new pose.
|
|
|
|
*
|
|
|
|
* @return new world-space vertex coordinates
|
|
|
|
*/
|
|
|
|
static CVector3D SkinPoint(const SModelVertex& vtx,
|
2011-07-13 01:48:05 +02:00
|
|
|
const CMatrix3D newPoseMatrices[]);
|
2006-12-15 17:09:30 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Transform the given vertex's normal from the bind pose into the new pose.
|
|
|
|
*
|
|
|
|
* @return new world-space vertex normal
|
|
|
|
*/
|
|
|
|
static CVector3D SkinNormal(const SModelVertex& vtx,
|
2011-07-13 01:48:05 +02:00
|
|
|
const CMatrix3D newPoseMatrices[]);
|
2006-12-15 17:09:30 +01:00
|
|
|
|
2010-09-24 18:54:20 +02:00
|
|
|
/**
|
|
|
|
* Transform vertices' positions and normals.
|
|
|
|
* (This is equivalent to looping over SkinPoint and SkinNormal,
|
|
|
|
* but slightly more efficient.)
|
|
|
|
*/
|
|
|
|
static void SkinPointsAndNormals(
|
|
|
|
size_t numVertices,
|
|
|
|
const VertexArrayIterator<CVector3D>& Position,
|
|
|
|
const VertexArrayIterator<CVector3D>& Normal,
|
|
|
|
const SModelVertex* vertices,
|
2011-07-13 01:48:05 +02:00
|
|
|
const size_t* blendIndices,
|
|
|
|
const CMatrix3D newPoseMatrices[]);
|
|
|
|
|
2013-10-03 20:22:10 +02:00
|
|
|
#if HAVE_SSE
|
2011-11-10 00:11:28 +01:00
|
|
|
/**
|
|
|
|
* SSE-optimised version of SkinPointsAndNormals.
|
|
|
|
*/
|
|
|
|
static void SkinPointsAndNormals_SSE(
|
|
|
|
size_t numVertices,
|
|
|
|
const VertexArrayIterator<CVector3D>& Position,
|
|
|
|
const VertexArrayIterator<CVector3D>& Normal,
|
|
|
|
const SModelVertex* vertices,
|
|
|
|
const size_t* blendIndices,
|
|
|
|
const CMatrix3D newPoseMatrices[]);
|
|
|
|
#endif
|
|
|
|
|
2011-07-13 01:48:05 +02:00
|
|
|
/**
|
|
|
|
* Blend bone matrices together to fill bone palette.
|
|
|
|
*/
|
|
|
|
void BlendBoneMatrices(CMatrix3D boneMatrices[]);
|
2010-09-24 18:54:20 +02:00
|
|
|
|
2006-12-15 17:09:30 +01:00
|
|
|
/**
|
|
|
|
* Register renderer private data. Use the key to
|
2005-10-25 04:00:09 +02:00
|
|
|
* distinguish between private data used by different render paths.
|
|
|
|
* The private data will be managed by this CModelDef object:
|
|
|
|
* It will be deleted when CModelDef is destructed or when private
|
|
|
|
* data is registered using the same key.
|
|
|
|
*
|
|
|
|
* @param key The opaque key that is used to identify the caller.
|
|
|
|
* The given private data can be retrieved by passing key to GetRenderData.
|
|
|
|
* @param data The private data.
|
|
|
|
*
|
|
|
|
* postconditions : data is bound to the lifetime of this CModelDef
|
|
|
|
* object.
|
|
|
|
*/
|
|
|
|
void SetRenderData(const void* key, CModelDefRPrivate* data);
|
2016-11-23 12:18:37 +01:00
|
|
|
|
2005-10-02 23:11:11 +02:00
|
|
|
// accessor: render data
|
2005-10-25 04:00:09 +02:00
|
|
|
CModelDefRPrivate* GetRenderData(const void* key) const;
|
2005-10-02 23:11:11 +02:00
|
|
|
|
2006-04-14 06:35:36 +02:00
|
|
|
// accessor: get model name (for debugging)
|
2009-11-03 22:46:35 +01:00
|
|
|
const VfsPath& GetName() const { return m_Name; }
|
2006-04-14 06:35:36 +02:00
|
|
|
|
2004-05-29 22:56:24 +02:00
|
|
|
public:
|
|
|
|
// vertex data
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
size_t m_NumVertices;
|
2004-05-29 22:56:24 +02:00
|
|
|
SModelVertex* m_pVertices;
|
2012-07-24 00:49:46 +02:00
|
|
|
size_t m_NumUVsPerVertex; // number of UV pairs per vertex
|
2004-05-29 22:56:24 +02:00
|
|
|
// face data
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
size_t m_NumFaces;
|
2004-05-29 22:56:24 +02:00
|
|
|
SModelFace* m_pFaces;
|
|
|
|
// bone data - default model pose
|
had to remove uint and ulong from lib/types.h due to conflict with other library.
this snowballed into a massive search+destroy of the hodgepodge of
mostly equivalent types we had in use (int, uint, unsigned, unsigned
int, i32, u32, ulong, uintN).
it is more efficient to use 64-bit types in 64-bit mode, so the
preferred default is size_t (for anything remotely resembling a size or
index). tile coordinates are ssize_t to allow more efficient conversion
to/from floating point. flags are int because we almost never need more
than 15 distinct bits, bit test/set is not slower and int is fastest to
type. finally, some data that is pretty much directly passed to OpenGL
is now typed accordingly.
after several hours, the code now requires fewer casts and less
guesswork.
other changes:
- unit and player IDs now have an "invalid id" constant in the
respective class to avoid casting and -1
- fix some endian/64-bit bugs in the map (un)packing. added a
convenience function to write/read a size_t.
- ia32: change CPUID interface to allow passing in ecx (required for
cache topology detection, which I need at work). remove some unneeded
functions from asm, replace with intrinsics where possible.
This was SVN commit r5942.
2008-05-11 20:48:32 +02:00
|
|
|
size_t m_NumBones;
|
2004-05-30 02:46:58 +02:00
|
|
|
CBoneState* m_Bones;
|
2012-04-12 17:43:59 +02:00
|
|
|
CMatrix3D* m_InverseBindBoneMatrices;
|
2011-07-13 01:48:05 +02:00
|
|
|
// blend data
|
|
|
|
size_t m_NumBlends;
|
|
|
|
SVertexBlend *m_pBlends;
|
|
|
|
size_t* m_pBlendIndices;
|
2004-05-30 02:46:58 +02:00
|
|
|
// prop point data
|
2010-11-20 21:16:06 +01:00
|
|
|
std::vector<SPropPoint> m_PropPoints;
|
2004-12-12 20:43:55 +01:00
|
|
|
|
2005-10-25 04:00:09 +02:00
|
|
|
private:
|
2009-11-03 22:46:35 +01:00
|
|
|
VfsPath m_Name; // filename
|
2006-04-14 06:35:36 +02:00
|
|
|
|
2005-10-25 04:00:09 +02:00
|
|
|
// renderdata shared by models of the same modeldef,
|
|
|
|
// by render path
|
|
|
|
typedef std::map<const void*, CModelDefRPrivate*> RenderDataMap;
|
|
|
|
RenderDataMap m_RenderData;
|
2004-05-29 22:56:24 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|
2016-11-23 12:18:37 +01:00
|
|
|
|