File: Model.h

package info (click to toggle)
0ad 0.0.23.1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 78,292 kB
  • sloc: cpp: 245,166; ansic: 200,249; python: 13,754; sh: 6,104; perl: 4,620; makefile: 977; xml: 810; java: 533; ruby: 229; erlang: 46; pascal: 30; sql: 21; tcl: 4
file content (307 lines) | stat: -rw-r--r-- 10,391 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
/* Copyright (C) 2016 Wildfire Games.
 * 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/>.
 */

/*
 * Mesh object with texture and skinning information
 */

#ifndef INCLUDED_MODEL
#define INCLUDED_MODEL

#include <vector>

#include "graphics/Texture.h"
#include "graphics/Material.h"
#include "graphics/MeshManager.h"
#include "graphics/ModelAbstract.h"

struct SPropPoint;
class CObjectEntry;
class CSkeletonAnim;
class CSkeletonAnimDef;
class CSkeletonAnimManager;
class CSimulation2;

#define MODELFLAG_CASTSHADOWS		(1<<0)
#define MODELFLAG_NOLOOPANIMATION	(1<<1)
#define MODELFLAG_SILHOUETTE_DISPLAY	(1<<2)
#define MODELFLAG_SILHOUETTE_OCCLUDER	(1<<3)
#define MODELFLAG_IGNORE_LOS		(1<<4)

///////////////////////////////////////////////////////////////////////////////
// CModel: basically, a mesh object - holds the texturing and skinning
// information for a model in game
class CModel : public CModelAbstract
{
	NONCOPYABLE(CModel);

public:
	struct Prop
	{
		Prop() : m_MinHeight(0.f), m_MaxHeight(0.f), m_Point(0), m_Model(0), m_ObjectEntry(0), m_Hidden(false), m_Selectable(true) {}

		float m_MinHeight;
		float m_MaxHeight;

		/**
		 * Location of the prop point within its parent model, relative to either a bone in the parent model or to the
		 * parent model's origin. See the documentation for @ref SPropPoint for more details.
		 * @see SPropPoint
		 */
		const SPropPoint* m_Point;

		/**
		 * Pointer to the model associated with this prop. Note that the transform matrix held by this model is the full object-to-world
		 * space transform, taking into account all parent model positioning (see @ref CModel::ValidatePosition for positioning logic).
		 * @see CModel::ValidatePosition
		 */
		CModelAbstract* m_Model;
		CObjectEntry* m_ObjectEntry;

		bool m_Hidden; ///< Should this prop be temporarily removed from rendering?
		bool m_Selectable; /// < should this prop count in the selection size?
	};

public:
	// constructor
	CModel(CSkeletonAnimManager& skeletonAnimManager, CSimulation2& simulation);
	// destructor
	~CModel();


	/// Dynamic cast
	virtual CModel* ToCModel()
	{
		return this;
	}

	// setup model from given geometry
	bool InitModel(const CModelDefPtr& modeldef);
	// update this model's state; 'time' is the absolute time since the start of the animation, in MS
	void UpdateTo(float time);

	// get the model's geometry data
	const CModelDefPtr& GetModelDef() { return m_pModelDef; }

	// set the model's material
	void SetMaterial(const CMaterial &material);
	// set the model's player ID, recursively through props
	void SetPlayerID(player_id_t id);
	// set the models mod color
	virtual void SetShadingColor(const CColor& color);
	// get the model's material
	CMaterial& GetMaterial() { return m_Material; }

	// set the given animation as the current animation on this model
	bool SetAnimation(CSkeletonAnim* anim, bool once = false);

	// get the currently playing animation, if any
	CSkeletonAnim* GetAnimation() const { return m_Anim; }

	// set the animation state to be the same as from another; both models should
	// be compatible types (same type of skeleton)
	void CopyAnimationFrom(CModel* source);

	// set object flags
	void SetFlags(int flags) { m_Flags=flags; }
	// get object flags
	int GetFlags() const { return m_Flags; }
	// add object flags, recursively through props
	void AddFlagsRec(int flags);
	// remove shadow casting and receiving, recursively through props
	// TODO: replace with more generic shader define + flags setting
	void RemoveShadowsRec();

	// recurse down tree setting dirty bits
	virtual void SetDirtyRec(int dirtyflags) {
		SetDirty(dirtyflags);
		for (size_t i=0;i<m_Props.size();i++) {
			m_Props[i].m_Model->SetDirtyRec(dirtyflags);
		}
	}

	virtual void SetTerrainDirty(ssize_t i0, ssize_t j0, ssize_t i1, ssize_t j1)
	{
		for (size_t i = 0; i < m_Props.size(); ++i)
			m_Props[i].m_Model->SetTerrainDirty(i0, j0, i1, j1);
	}

	virtual void SetEntityVariable(const std::string& name, float value)
	{
		for (size_t i = 0; i < m_Props.size(); ++i)
			m_Props[i].m_Model->SetEntityVariable(name, value);
	}

	// --- WORLD/OBJECT SPACE BOUNDS -----------------------------------------------------------------

	/// Overridden to calculate both the world-space and object-space bounds of this model, and stores the result in
	/// m_Bounds and m_ObjectBounds, respectively.
	virtual void CalcBounds();

	/// Returns the object-space bounds for this model, excluding its children.
	const CBoundingBoxAligned& GetObjectBounds()
	{
		RecalculateBoundsIfNecessary();				// recalculates both object-space and world-space bounds if necessary
		return m_ObjectBounds;
	}

	virtual const CBoundingBoxAligned GetWorldBoundsRec();		// reimplemented here

	/// Auxiliary method; calculates object space bounds of this model, based solely on vertex positions, and stores
	/// the result in m_ObjectBounds. Called by CalcBounds (instead of CalcAnimatedObjectBounds) if it has been determined
	/// that the object-space bounds are static.
	void CalcStaticObjectBounds();

	/// Auxiliary method; calculate object-space bounds encompassing all vertex positions for given animation, and stores
	/// the result in m_ObjectBounds. Called by CalcBounds (instead of CalcStaticBounds) if it has been determined that the
	/// object-space bounds need to take animations into account.
	void CalcAnimatedObjectBounds(CSkeletonAnimDef* anim,CBoundingBoxAligned& result);

	// --- SELECTION BOX/BOUNDS ----------------------------------------------------------------------

	/// Reimplemented here since proper models should participate in selection boxes.
	virtual const CBoundingBoxAligned GetObjectSelectionBoundsRec();

	/**
	 * Set transform of this object.
	 *
	 * @note In order to ensure that all child props are updated properly,
	 * you must call ValidatePosition().
	 */
	virtual void SetTransform(const CMatrix3D& transform);

	/**
	 * Return whether this is a skinned/skeletal model. If it is, Get*BoneMatrices()
	 * will return valid non-NULL arrays.
	 */
	bool IsSkinned() { return (m_BoneMatrices != NULL); }

	// return the models bone matrices; 16-byte aligned for SSE reads
	const CMatrix3D* GetAnimatedBoneMatrices() {
		ENSURE(m_PositionValid);
		return m_BoneMatrices;
	}

	/**
	 * Load raw animation frame animation from given file, and build an
	 * animation specific to this model.
	 * @param pathname animation file to load
	 * @param name animation name (e.g. "idle")
	 * @param ID specific ID of the animation, to sync with props
	 * @param frequency influences the random choices
	 * @param speed animation speed as a factor of the default animation speed
	 * @param actionpos offset of 'action' event, in range [0, 1]
	 * @param actionpos2 offset of 'action2' event, in range [0, 1]
	 * @param sound offset of 'sound' event, in range [0, 1]
	 * @return new animation, or NULL on error
	 */
	CSkeletonAnim* BuildAnimation(const VfsPath& pathname, const CStr& name, const CStr& ID, int frequency, float speed, float actionpos, float actionpos2, float soundpos);

	/**
	 * Add a prop to the model on the given point.
	 */
	void AddProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry, float minHeight = 0.f, float maxHeight = 0.f, bool selectable = true);

	/**
	 * Add a prop to the model on the given point, and treat it as the ammo prop.
	 * The prop will be hidden by default.
	 */
	void AddAmmoProp(const SPropPoint* point, CModelAbstract* model, CObjectEntry* objectentry);

	/**
	 * Show the ammo prop (if any), and hide any other props on that prop point.
	 */
	void ShowAmmoProp();

	/**
	 * Hide the ammo prop (if any), and show any other props on that prop point.
	 */
	void HideAmmoProp();

	/**
	 * Find the first prop used for ammo, by this model or its own props.
	 */
	CModelAbstract* FindFirstAmmoProp();

	// return prop list
	std::vector<Prop>& GetProps() { return m_Props; }
	const std::vector<Prop>& GetProps() const { return m_Props; }

	// return a clone of this model
	virtual CModelAbstract* Clone() const;

	/**
	 * Ensure that both the transformation and the bone
	 * matrices are correct for this model and all its props.
	 */
	virtual void ValidatePosition();

	/**
	 * Mark this model's position and bone matrices,
	 * and all props' positions as invalid.
	 */
	virtual void InvalidatePosition();

private:
	// delete anything allocated by the model
	void ReleaseData();

	// Needed for terrain aligned props
	CSimulation2& m_Simulation;

	// object flags
	int m_Flags;
	// model's material
	CMaterial m_Material;
	// pointer to the model's raw 3d data
	CModelDefPtr m_pModelDef;
	// object space bounds of model - accounts for bounds of all possible animations
	// that can play on a model. Not always up-to-date - currently CalcBounds()
	// updates it when necessary.
	CBoundingBoxAligned m_ObjectBounds;
	// animation currently playing on this model, if any
	CSkeletonAnim* m_Anim;
	// time (in MS) into the current animation
	float m_AnimTime;

	/**
	 * Current state of all bones on this model; null if associated modeldef isn't skeletal.
	 * Props may attach to these bones by means of the SPropPoint::m_BoneIndex field; in this case their
	 * transformation matrix held is relative to the bone transformation (see @ref SPropPoint and
	 * @ref CModel::ValidatePosition).
	 *
	 * @see SPropPoint
	 */
	CMatrix3D* m_BoneMatrices;
	// list of current props on model
	std::vector<Prop> m_Props;

	/**
	 * The prop point to which the ammo prop is attached, or NULL if none
	 */
	const SPropPoint* m_AmmoPropPoint;

	/**
	 * If m_AmmoPropPoint is not NULL, then the index in m_Props of the ammo prop
	 */
	size_t m_AmmoLoadedProp;

	// manager object which can load animations for us
	CSkeletonAnimManager& m_SkeletonAnimManager;
};

#endif