1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
2 // This file is part of the "Irrlicht Engine".
3 // For conditions of distribution and use, see copyright notice in irrlicht.h
4 
5 #ifndef __I_SKIN_MESH_BUFFER_H_INCLUDED__
6 #define __I_SKIN_MESH_BUFFER_H_INCLUDED__
7 
8 #include "IMeshBuffer.h"
9 #include "S3DVertex.h"
10 
11 
12 namespace irr
13 {
14 namespace scene
15 {
16 
17 
18 //! A mesh buffer able to choose between S3DVertex2TCoords, S3DVertex and S3DVertexTangents at runtime
19 struct SSkinMeshBuffer : public IMeshBuffer
20 {
21 	//! Default constructor
22 	SSkinMeshBuffer(video::E_VERTEX_TYPE vt=video::EVT_STANDARD) :
23 		ChangedID_Vertex(1), ChangedID_Index(1), VertexType(vt),
24 		MappingHint_Vertex(EHM_NEVER), MappingHint_Index(EHM_NEVER),
25 		BoundingBoxNeedsRecalculated(true)
26 	{
27 		#ifdef _DEBUG
28 		setDebugName("SSkinMeshBuffer");
29 		#endif
30 	}
31 
32 	//! Get Material of this buffer.
getMaterialSSkinMeshBuffer33 	virtual const video::SMaterial& getMaterial() const
34 	{
35 		return Material;
36 	}
37 
38 	//! Get Material of this buffer.
getMaterialSSkinMeshBuffer39 	virtual video::SMaterial& getMaterial()
40 	{
41 		return Material;
42 	}
43 
44 	//! Get standard vertex at given index
getVertexSSkinMeshBuffer45 	virtual video::S3DVertex *getVertex(u32 index)
46 	{
47 		switch (VertexType)
48 		{
49 			case video::EVT_2TCOORDS:
50 				return (video::S3DVertex*)&Vertices_2TCoords[index];
51 			case video::EVT_TANGENTS:
52 				return (video::S3DVertex*)&Vertices_Tangents[index];
53 			default:
54 				return &Vertices_Standard[index];
55 		}
56 	}
57 
58 	//! Get pointer to vertex array
getVerticesSSkinMeshBuffer59 	virtual const void* getVertices() const
60 	{
61 		switch (VertexType)
62 		{
63 			case video::EVT_2TCOORDS:
64 				return Vertices_2TCoords.const_pointer();
65 			case video::EVT_TANGENTS:
66 				return Vertices_Tangents.const_pointer();
67 			default:
68 				return Vertices_Standard.const_pointer();
69 		}
70 	}
71 
72 	//! Get pointer to vertex array
getVerticesSSkinMeshBuffer73 	virtual void* getVertices()
74 	{
75 		switch (VertexType)
76 		{
77 			case video::EVT_2TCOORDS:
78 				return Vertices_2TCoords.pointer();
79 			case video::EVT_TANGENTS:
80 				return Vertices_Tangents.pointer();
81 			default:
82 				return Vertices_Standard.pointer();
83 		}
84 	}
85 
86 	//! Get vertex count
getVertexCountSSkinMeshBuffer87 	virtual u32 getVertexCount() const
88 	{
89 		switch (VertexType)
90 		{
91 			case video::EVT_2TCOORDS:
92 				return Vertices_2TCoords.size();
93 			case video::EVT_TANGENTS:
94 				return Vertices_Tangents.size();
95 			default:
96 				return Vertices_Standard.size();
97 		}
98 	}
99 
100 	//! Get type of index data which is stored in this meshbuffer.
101 	/** \return Index type of this buffer. */
getIndexTypeSSkinMeshBuffer102 	virtual video::E_INDEX_TYPE getIndexType() const
103 	{
104 		return video::EIT_16BIT;
105 	}
106 
107 	//! Get pointer to index array
getIndicesSSkinMeshBuffer108 	virtual const u16* getIndices() const
109 	{
110 		return Indices.const_pointer();
111 	}
112 
113 	//! Get pointer to index array
getIndicesSSkinMeshBuffer114 	virtual u16* getIndices()
115 	{
116 		return Indices.pointer();
117 	}
118 
119 	//! Get index count
getIndexCountSSkinMeshBuffer120 	virtual u32 getIndexCount() const
121 	{
122 		return Indices.size();
123 	}
124 
125 	//! Get bounding box
getBoundingBoxSSkinMeshBuffer126 	virtual const core::aabbox3d<f32>& getBoundingBox() const
127 	{
128 		return BoundingBox;
129 	}
130 
131 	//! Set bounding box
setBoundingBoxSSkinMeshBuffer132 	virtual void setBoundingBox( const core::aabbox3df& box)
133 	{
134 		BoundingBox = box;
135 	}
136 
137 	//! Recalculate bounding box
recalculateBoundingBoxSSkinMeshBuffer138 	virtual void recalculateBoundingBox()
139 	{
140 		if(!BoundingBoxNeedsRecalculated)
141 			return;
142 
143 		BoundingBoxNeedsRecalculated = false;
144 
145 		switch (VertexType)
146 		{
147 			case video::EVT_STANDARD:
148 			{
149 				if (Vertices_Standard.empty())
150 					BoundingBox.reset(0,0,0);
151 				else
152 				{
153 					BoundingBox.reset(Vertices_Standard[0].Pos);
154 					for (u32 i=1; i<Vertices_Standard.size(); ++i)
155 						BoundingBox.addInternalPoint(Vertices_Standard[i].Pos);
156 				}
157 				break;
158 			}
159 			case video::EVT_2TCOORDS:
160 			{
161 				if (Vertices_2TCoords.empty())
162 					BoundingBox.reset(0,0,0);
163 				else
164 				{
165 					BoundingBox.reset(Vertices_2TCoords[0].Pos);
166 					for (u32 i=1; i<Vertices_2TCoords.size(); ++i)
167 						BoundingBox.addInternalPoint(Vertices_2TCoords[i].Pos);
168 				}
169 				break;
170 			}
171 			case video::EVT_TANGENTS:
172 			{
173 				if (Vertices_Tangents.empty())
174 					BoundingBox.reset(0,0,0);
175 				else
176 				{
177 					BoundingBox.reset(Vertices_Tangents[0].Pos);
178 					for (u32 i=1; i<Vertices_Tangents.size(); ++i)
179 						BoundingBox.addInternalPoint(Vertices_Tangents[i].Pos);
180 				}
181 				break;
182 			}
183 		}
184 	}
185 
186 	//! Get vertex type
getVertexTypeSSkinMeshBuffer187 	virtual video::E_VERTEX_TYPE getVertexType() const
188 	{
189 		return VertexType;
190 	}
191 
192 	//! Convert to 2tcoords vertex type
convertTo2TCoordsSSkinMeshBuffer193 	virtual void convertTo2TCoords()
194 	{
195 		if (VertexType==video::EVT_STANDARD)
196 		{
197 			for(u32 n=0;n<Vertices_Standard.size();++n)
198 			{
199 				video::S3DVertex2TCoords Vertex;
200 				Vertex.Color=Vertices_Standard[n].Color;
201 				Vertex.Pos=Vertices_Standard[n].Pos;
202 				Vertex.Normal=Vertices_Standard[n].Normal;
203 				Vertex.TCoords=Vertices_Standard[n].TCoords;
204 				Vertices_2TCoords.push_back(Vertex);
205 			}
206 			Vertices_Standard.clear();
207 			VertexType=video::EVT_2TCOORDS;
208 		}
209 	}
210 
211 	//! Convert to tangents vertex type
convertToTangentsSSkinMeshBuffer212 	virtual void convertToTangents()
213 	{
214 		if (VertexType==video::EVT_STANDARD)
215 		{
216 			for(u32 n=0;n<Vertices_Standard.size();++n)
217 			{
218 				video::S3DVertexTangents Vertex;
219 				Vertex.Color=Vertices_Standard[n].Color;
220 				Vertex.Pos=Vertices_Standard[n].Pos;
221 				Vertex.Normal=Vertices_Standard[n].Normal;
222 				Vertex.TCoords=Vertices_Standard[n].TCoords;
223 				Vertices_Tangents.push_back(Vertex);
224 			}
225 			Vertices_Standard.clear();
226 			VertexType=video::EVT_TANGENTS;
227 		}
228 		else if (VertexType==video::EVT_2TCOORDS)
229 		{
230 			for(u32 n=0;n<Vertices_2TCoords.size();++n)
231 			{
232 				video::S3DVertexTangents Vertex;
233 				Vertex.Color=Vertices_2TCoords[n].Color;
234 				Vertex.Pos=Vertices_2TCoords[n].Pos;
235 				Vertex.Normal=Vertices_2TCoords[n].Normal;
236 				Vertex.TCoords=Vertices_2TCoords[n].TCoords;
237 				Vertices_Tangents.push_back(Vertex);
238 			}
239 			Vertices_2TCoords.clear();
240 			VertexType=video::EVT_TANGENTS;
241 		}
242 	}
243 
244 	//! returns position of vertex i
getPositionSSkinMeshBuffer245 	virtual const core::vector3df& getPosition(u32 i) const
246 	{
247 		switch (VertexType)
248 		{
249 			case video::EVT_2TCOORDS:
250 				return Vertices_2TCoords[i].Pos;
251 			case video::EVT_TANGENTS:
252 				return Vertices_Tangents[i].Pos;
253 			default:
254 				return Vertices_Standard[i].Pos;
255 		}
256 	}
257 
258 	//! returns position of vertex i
getPositionSSkinMeshBuffer259 	virtual core::vector3df& getPosition(u32 i)
260 	{
261 		switch (VertexType)
262 		{
263 			case video::EVT_2TCOORDS:
264 				return Vertices_2TCoords[i].Pos;
265 			case video::EVT_TANGENTS:
266 				return Vertices_Tangents[i].Pos;
267 			default:
268 				return Vertices_Standard[i].Pos;
269 		}
270 	}
271 
272 	//! returns normal of vertex i
getNormalSSkinMeshBuffer273 	virtual const core::vector3df& getNormal(u32 i) const
274 	{
275 		switch (VertexType)
276 		{
277 			case video::EVT_2TCOORDS:
278 				return Vertices_2TCoords[i].Normal;
279 			case video::EVT_TANGENTS:
280 				return Vertices_Tangents[i].Normal;
281 			default:
282 				return Vertices_Standard[i].Normal;
283 		}
284 	}
285 
286 	//! returns normal of vertex i
getNormalSSkinMeshBuffer287 	virtual core::vector3df& getNormal(u32 i)
288 	{
289 		switch (VertexType)
290 		{
291 			case video::EVT_2TCOORDS:
292 				return Vertices_2TCoords[i].Normal;
293 			case video::EVT_TANGENTS:
294 				return Vertices_Tangents[i].Normal;
295 			default:
296 				return Vertices_Standard[i].Normal;
297 		}
298 	}
299 
300 	//! returns texture coords of vertex i
getTCoordsSSkinMeshBuffer301 	virtual const core::vector2df& getTCoords(u32 i) const
302 	{
303 		switch (VertexType)
304 		{
305 			case video::EVT_2TCOORDS:
306 				return Vertices_2TCoords[i].TCoords;
307 			case video::EVT_TANGENTS:
308 				return Vertices_Tangents[i].TCoords;
309 			default:
310 				return Vertices_Standard[i].TCoords;
311 		}
312 	}
313 
314 	//! returns texture coords of vertex i
getTCoordsSSkinMeshBuffer315 	virtual core::vector2df& getTCoords(u32 i)
316 	{
317 		switch (VertexType)
318 		{
319 			case video::EVT_2TCOORDS:
320 				return Vertices_2TCoords[i].TCoords;
321 			case video::EVT_TANGENTS:
322 				return Vertices_Tangents[i].TCoords;
323 			default:
324 				return Vertices_Standard[i].TCoords;
325 		}
326 	}
327 
328 	//! append the vertices and indices to the current buffer
appendSSkinMeshBuffer329 	virtual void append(const void* const vertices, u32 numVertices, const u16* const indices, u32 numIndices) {}
330 
331 	//! append the meshbuffer to the current buffer
appendSSkinMeshBuffer332 	virtual void append(const IMeshBuffer* const other) {}
333 
334 	//! get the current hardware mapping hint for vertex buffers
getHardwareMappingHint_VertexSSkinMeshBuffer335 	virtual E_HARDWARE_MAPPING getHardwareMappingHint_Vertex() const
336 	{
337 		return MappingHint_Vertex;
338 	}
339 
340 	//! get the current hardware mapping hint for index buffers
getHardwareMappingHint_IndexSSkinMeshBuffer341 	virtual E_HARDWARE_MAPPING getHardwareMappingHint_Index() const
342 	{
343 		return MappingHint_Index;
344 	}
345 
346 	//! set the hardware mapping hint, for driver
347 	virtual void setHardwareMappingHint( E_HARDWARE_MAPPING NewMappingHint, E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX )
348 	{
349 		if (Buffer==EBT_VERTEX)
350 			MappingHint_Vertex=NewMappingHint;
351 		else if (Buffer==EBT_INDEX)
352 			MappingHint_Index=NewMappingHint;
353 		else if (Buffer==EBT_VERTEX_AND_INDEX)
354 		{
355 			MappingHint_Vertex=NewMappingHint;
356 			MappingHint_Index=NewMappingHint;
357 		}
358 	}
359 
360 	//! flags the mesh as changed, reloads hardware buffers
361 	virtual void setDirty(E_BUFFER_TYPE Buffer=EBT_VERTEX_AND_INDEX)
362 	{
363 		if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_VERTEX)
364 			++ChangedID_Vertex;
365 		if (Buffer==EBT_VERTEX_AND_INDEX || Buffer==EBT_INDEX)
366 			++ChangedID_Index;
367 	}
368 
getChangedID_VertexSSkinMeshBuffer369 	virtual u32 getChangedID_Vertex() const {return ChangedID_Vertex;}
370 
getChangedID_IndexSSkinMeshBuffer371 	virtual u32 getChangedID_Index() const {return ChangedID_Index;}
372 
373 	//! Call this after changing the positions of any vertex.
boundingBoxNeedsRecalculatedSSkinMeshBuffer374 	void boundingBoxNeedsRecalculated(void) { BoundingBoxNeedsRecalculated = true; }
375 
376 	core::array<video::S3DVertexTangents> Vertices_Tangents;
377 	core::array<video::S3DVertex2TCoords> Vertices_2TCoords;
378 	core::array<video::S3DVertex> Vertices_Standard;
379 	core::array<u16> Indices;
380 
381 	u32 ChangedID_Vertex;
382 	u32 ChangedID_Index;
383 
384 	//ISkinnedMesh::SJoint *AttachedJoint;
385 	core::matrix4 Transformation;
386 
387 	video::SMaterial Material;
388 	video::E_VERTEX_TYPE VertexType;
389 
390 	core::aabbox3d<f32> BoundingBox;
391 
392 	// hardware mapping hint
393 	E_HARDWARE_MAPPING MappingHint_Vertex:3;
394 	E_HARDWARE_MAPPING MappingHint_Index:3;
395 
396 	bool BoundingBoxNeedsRecalculated:1;
397 };
398 
399 
400 } // end namespace scene
401 } // end namespace irr
402 
403 #endif
404 
405