1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ResShape.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law.  They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Revision: 18106 $
14  *---------------------------------------------------------------------------*/
15 
16 #ifndef NW_GFX_RESSHAPE_H_
17 #define NW_GFX_RESSHAPE_H_
18 
19 #include <nw/ut/ut_ResUtil.h>
20 #include <nw/ut/ut_ResDictionary.h>
21 #include <nw/gfx/res/gfx_ResSceneObject.h>
22 #include <nw/gfx/res/gfx_ResVertex.h>
23 #include <nw/math/math_ResTypes.h>
24 #include <nw/gfx/res/gfx_ResTypeInfo.h>
25 #include <nw/ut/ut_ResPrimitive.h>
26 
27 namespace nw {
28 namespace gfx {
29 namespace res {
30 
31 //===================================
32 // モーフィング用クラス
33 //===================================
34 //! @details :private
35 struct ResKeyShapeWeightData
36 {
37     nw::ut::ResS32 m_Index;
38     nw::ut::ResF32 m_Weight;
39 };
40 
41 //--------------------------------------------------------------------------
42 //! @brief 頂点モーフィングに割り当てるキーシェイプのインデックス番号とウェイト値を表すバイナリリソースクラスです。
43 //! @details :private
44 //---------------------------------------------------------------------------
45 class ResKeyShapeWeight : public nw::ut::ResCommon< ResKeyShapeWeightData >
46 {
47 public:
48     NW_RES_CTOR( ResKeyShapeWeight )
49 
50     NW_RES_FIELD_PRIMITIVE_DECL( s32, Index )  // GetIndex(), SetIndex()
51     NW_RES_FIELD_PRIMITIVE_DECL( f32, Weight ) // GetWeight(), SetWeight()
52 };
53 
54 //! @details :private
55 struct ResMorphShapeData
56 {
57     nw::ut::ResTypeInfo typeInfo;
58     nw::ut::ResS32 m_KeyShapeWeightsTableCount;
59     nw::ut::Offset toKeyShapeWeightsTable;
60 };
61 
62 //--------------------------------------------------------------------------
63 //! @brief  キーシェイプを合成して頂点モーフィングをするための情報を表すバイナリリソースクラスです。
64 //! @details :private
65 //---------------------------------------------------------------------------
66 class ResMorphShape : public nw::ut::ResCommon< ResMorphShapeData >
67 {
68 public:
69     NW_RES_CTOR( ResMorphShape )
70 
71     NW_RES_FIELD_STRUCT_LIST_DECL( ResKeyShapeWeight, KeyShapeWeights )
72 };
73 
74 //! @details :private
75 struct ResSeparateDataMorphShapeData : public ResMorphShapeData
76 {
77     nw::ut::ResS32 m_DeltaVertexAttributesTableCount;
78     nw::ut::Offset toDeltaVertexAttributesTable;
79 };
80 
81 //--------------------------------------------------------------------------
82 //! @brief 複数の属性を組み合わせてモーフィング差分を管理する為バイナリリソースクラスです。
83 //! @details :private
84 //---------------------------------------------------------------------------
85 class ResSeparateDataMorphShape : public ResMorphShape
86 {
87 public:
88     NW_RES_CTOR_INHERIT( ResSeparateDataMorphShape, ResMorphShape )
89 
90     NW_RES_FIELD_CLASS_LIST_DECL( ResVertexAttribute, DeltaVertexAttributes ) // GetDeltaVertexAttributes(int idx), GetDeltaVertexAttributesCount()
91 };
92 
93 //===================================
94 //  プリミティブクラス
95 //===================================
96 //! @details :private
97 struct ResPrimitiveData
98 {
99     nw::ut::ResS32 m_IndexStreamsTableCount;
100     nw::ut::Offset toIndexStreamsTable;
101     nw::ut::ResS32 m_BufferObjectsTableCount;
102     nw::ut::Offset toBufferObjectsTable;
103 };
104 
105 //--------------------------------------------------------------------------
106 //! @brief シェイプを構成する一つのプリミティブを表すバイナリリソースクラスです。
107 //---------------------------------------------------------------------------
108 class ResPrimitive : public nw::ut::ResCommon< ResPrimitiveData >
109 {
110 public:
111     NW_RES_CTOR( ResPrimitive )
112 
113     //---------------------------------------------------------------------------
114     //! @fn           void SetBufferObjects(int idx, u32 value)
115     //! @brief        バッファオブジェクトのリストに要素を設定します。
116     //---------------------------------------------------------------------------
117     //---------------------------------------------------------------------------
118     //! @fn           s32 GetIndexStreamsCount() const
119     //! @brief        頂点インデックスのストリームの要素数を取得します。
120     //---------------------------------------------------------------------------
121     //---------------------------------------------------------------------------
122     //! @fn           ResIndexStream GetIndexStreams(int idx)
123     //! @brief        頂点インデックスのストリームを取得します。
124     //---------------------------------------------------------------------------
125     //---------------------------------------------------------------------------
126     //! @fn           s32 GetBufferObjectsCount() const
127     //! @brief        バッファオブジェクトの要素数を取得します。
128     //---------------------------------------------------------------------------
129     //---------------------------------------------------------------------------
130     //! @fn           u32 GetBufferObjects(int idx) const
131     //! @brief        バッファオブジェクトを取得します。
132     //---------------------------------------------------------------------------
133     NW_RES_FIELD_CLASS_LIST_DECL( ResIndexStream, IndexStreams ) // GetIndexStreams(int idx), GetIndexStreamsCount()
134     NW_RES_FIELD_PRIMITIVE_LIST_DECL( u32, BufferObjects )       // GetBufferObjects(), GetBufferObjects(int idx), GetBufferObjectsCount()
135 
136     //---------------------------------------------------------------------------
137     //! @brief        リソースの初期化処理をおこないます。
138     //---------------------------------------------------------------------------
139     void    Setup();
140 
141     //---------------------------------------------------------------------------
142     //! @brief        リソースの解放準備をおこないます。
143     //---------------------------------------------------------------------------
144     void    Cleanup();
145 };
146 typedef nw::ut::ResArrayClass<ResPrimitive>::type ResPrimitiveArray;
147 
148 
149 //! @details :private
150 struct ResPrimitiveSetData
151 {
152     nw::ut::ResS32 m_BoneIndexTableTableCount;
153     nw::ut::Offset toBoneIndexTableTable;
154     nw::ut::ResS32 m_SkinningMode;
155     nw::ut::ResS32 m_PrimitivesTableCount;
156     nw::ut::Offset toPrimitivesTable;
157 };
158 
159 //--------------------------------------------------------------------------
160 //! @brief 同一のマトリクス群に影響する複数のプリミティブを表すバイナリリソースクラスです。
161 //---------------------------------------------------------------------------
162 class ResPrimitiveSet : public nw::ut::ResCommon< ResPrimitiveSetData >
163 {
164 public:
165     //! @brief  スキニングモードを表します。
166     enum SkinningModeType
167     {
168         SKINNING_MODE_NONE,     //!< スキニング無しの設定です。
169         SKINNING_MODE_RIGID,    //!< リジッドスキニングの設定です。
170         SKINNING_MODE_SMOOTH    //!< スムーススキニングの設定です。
171     };
172 
173     NW_RES_CTOR( ResPrimitiveSet )
174 
175     //---------------------------------------------------------------------------
176     //! @fn           void SetSkinningMode(s32 value)
177     //! @brief        スキニングのモードを設定します。
178     //---------------------------------------------------------------------------
179     //---------------------------------------------------------------------------
180     //! @fn           void SetBoneIndexTable(int idx, s32 value)
181     //! @brief        ボーンインデックスのテーブルのリストに要素を設定します。
182     //---------------------------------------------------------------------------
183     //---------------------------------------------------------------------------
184     //! @fn           s32 GetSkinningMode() const
185     //! @brief        スキニングのモードを取得します。
186     //---------------------------------------------------------------------------
187     //---------------------------------------------------------------------------
188     //! @fn           s32 GetPrimitivesCount() const
189     //! @brief        プリミティブの要素数を取得します。
190     //---------------------------------------------------------------------------
191     //---------------------------------------------------------------------------
192     //! @fn           ResPrimitive GetPrimitives(int idx)
193     //! @brief        プリミティブを取得します。
194     //---------------------------------------------------------------------------
195     //---------------------------------------------------------------------------
196     //! @fn           s32 GetBoneIndexTableCount() const
197     //! @brief        ボーンインデックスのテーブルの要素数を取得します。
198     //---------------------------------------------------------------------------
199     //---------------------------------------------------------------------------
200     //! @fn           s32 GetBoneIndexTable(int idx) const
201     //! @brief        ボーンインデックスのテーブルを取得します。
202     //---------------------------------------------------------------------------
203     NW_RES_FIELD_PRIMITIVE_LIST_DECL( s32, BoneIndexTable )  // GetBoneIndexTable(), GetBoneIndexTable(int idx), GetBoneIndexTableCount()
204     NW_RES_FIELD_PRIMITIVE_DECL( s32, SkinningMode )         // GetSkinningMode(), SetSkinningMode()
205     NW_RES_FIELD_CLASS_LIST_DECL( ResPrimitive, Primitives ) // GetPrimitives(int idx), GetPrimitivesCount()
206 
207     //---------------------------------------------------------------------------
208     //! @brief        リソースの初期化処理をおこないます。
209     //---------------------------------------------------------------------------
210     void    Setup();
211 
212     //---------------------------------------------------------------------------
213     //! @brief        リソースの解放準備をおこないます。
214     //---------------------------------------------------------------------------
215     void    Cleanup();
216 };
217 typedef nw::ut::ResArrayClass<ResPrimitiveSet>::type  ResPrimitiveSetArray;
218 
219 
220 //===================================
221 //  シェイプクラス
222 //===================================
223 //! @details :private
224 struct ResShapeData : public ResSceneObjectData
225 {
226     nw::ut::ResU32 m_Flags;
227     nw::ut::Offset toBoundingVolume;
228     nw::ut::ResVec3 m_PositionOffset;
229     nw::ut::ResS32 m_PrimitiveSetsTableCount;
230     nw::ut::Offset toPrimitiveSetsTable;
231     u32            m_BaseAddress;
232 };
233 
234 //--------------------------------------------------------------------------
235 //! @brief 頂点によって構成される形状を表すバイナリリソースクラスです。
236 //---------------------------------------------------------------------------
237 class ResShape : public ResSceneObject
238 {
239 public:
240     enum { TYPE_INFO = NW_GFX_RES_TYPE_INFO(ResShape) };
241     enum { SIGNATURE = NW_RES_SIGNATURE32('SHOB') };
242 
243     enum Flag
244     {
245         FLAG_HAS_BEEN_SETUP      = 0x1 << 0  //!< 既にセットアップ済みであることを示すフラグ
246     };
247 
NW_RES_CTOR_INHERIT(ResShape,ResSceneObject)248     NW_RES_CTOR_INHERIT( ResShape, ResSceneObject )
249 
250     //---------------------------------------------------------------------------
251     //! @fn           u32 GetFlags() const
252     //! @brief        フラグの値を取得します。
253     //---------------------------------------------------------------------------
254     //---------------------------------------------------------------------------
255     //! @fn           void SetFlags(u32 value)
256     //! @brief        フラグの値を設定します。
257     //---------------------------------------------------------------------------
258     NW_RES_FIELD_PRIMITIVE_DECL( u32, Flags )                      // GetFlags(), SetFlags()
259 
260     //---------------------------------------------------------------------------
261     //! @fn           nw::ut::ResBoundingVolume GetBoundingVolume()
262     //! @brief        指向性境界ボックスを取得します。
263     //---------------------------------------------------------------------------
264     NW_RES_FIELD_CLASS_DECL( nw::ut::ResBoundingVolume, BoundingVolume) // GetBoundingVolume()
265 
266     //---------------------------------------------------------------------------
267     //! @fn           nw::ut::ResOrientedBoundingBox GetOrientedBoundingBox()
268     //! @brief        指向性境界ボックスを取得します。
269     //---------------------------------------------------------------------------
270     nw::ut::ResOrientedBoundingBox GetOrientedBoundingBox()
271     {
272         nw::ut::ResOrientedBoundingBox resOBB( ref().toBoundingVolume.to_ptr() );
273 
274         NW_ASSERT( resOBB.IsValid() || (resOBB.GetTypeInfo() == nw::ut::ResOrientedBoundingBox::TYPE_INFO) );
275         return resOBB;
276     }
277 
GetOrientedBoundingBox()278     const nw::ut::ResOrientedBoundingBox GetOrientedBoundingBox() const
279     {
280         const nw::ut::ResOrientedBoundingBox resOBB( ref().toBoundingVolume.to_ptr() );
281 
282         NW_ASSERT( resOBB.IsValid() || (resOBB.GetTypeInfo() == nw::ut::ResOrientedBoundingBox::TYPE_INFO) );
283         return resOBB;
284     }
285 
286     //---------------------------------------------------------------------------
287     //! @fn           nw::ut::ResOrientedBoundingBoxData & GetOrientedBoundingBoxData()
288     //! @brief        指向性境界ボックスを取得します。
289     //---------------------------------------------------------------------------
GetOrientedBoundingBoxData()290     nw::ut::ResOrientedBoundingBoxData& GetOrientedBoundingBoxData()
291     {
292         return this->GetOrientedBoundingBox().ref();
293     }
294 
GetOrientedBoundingBoxData()295     const nw::ut::ResOrientedBoundingBoxData& GetOrientedBoundingBoxData() const
296     {
297         return this->GetOrientedBoundingBox().ref();
298     }
299 
300     //---------------------------------------------------------------------------
301     //! @fn           const nw::math::VEC3 & GetPositionOffset() const
302     //! @brief        座標情報に加算するオフセット値を取得します。
303     //---------------------------------------------------------------------------
304     //---------------------------------------------------------------------------
305     //! @fn           void SetPositionOffset(f32 x, f32 y, f32 z)
306     //! @brief        座標情報に加算するオフセット値を設定します。
307     //---------------------------------------------------------------------------
NW_RES_FIELD_VECTOR3_DECL(nw::math::VEC3,PositionOffset)308     NW_RES_FIELD_VECTOR3_DECL( nw::math::VEC3, PositionOffset )     // GetPositionOffset()
309 
310     //---------------------------------------------------------------------------
311     //! @fn           s32 GetPrimitiveSetsCount() const
312     //! @brief        プリミティブの集合の要素数を取得します。
313     //---------------------------------------------------------------------------
314     //---------------------------------------------------------------------------
315     //! @fn           ResPrimitiveSet GetPrimitiveSets(int idx)
316     //! @brief        プリミティブの集合を取得します。
317     //---------------------------------------------------------------------------
318     NW_RES_FIELD_CLASS_LIST_DECL( ResPrimitiveSet, PrimitiveSets ) // GetPrimitiveSets(int idx), GetPrimitiveSetsCount()
319 
320     //--------------------------------------------------------------------------
321     //! @brief        ローカルな中心位置を取得します。
322     //!
323     //! @return       ローカルな中心位置の座標です。
324     //---------------------------------------------------------------------------
325     const nw::math::VEC3& GetCenterPosition() const { return this->GetOrientedBoundingBox().GetCenterPosition(); }
326 
327     //--------------------------------------------------------------------------
328     //! @brief        ローカルな中心位置を設定します。
329     //!
330     //! @param[in]    x       中心位置の x 座標です。
331     //! @param[in]    y       中心位置の y 座標です。
332     //! @param[in]    z       中心位置の z 座標です。
333     //---------------------------------------------------------------------------
SetCenterPosition(f32 x,f32 y,f32 z)334     void SetCenterPosition( f32 x, f32 y, f32 z ) { return this->GetOrientedBoundingBox().SetCenterPosition(x, y, z); }
335 
336     //--------------------------------------------------------------------------
337     //! @brief        ローカルな中心位置を設定します。
338     //!
339     //! @param[in]    value   中心位置の座標です。
340     //---------------------------------------------------------------------------
SetCenterPosition(const nw::math::VEC3 & value)341     void SetCenterPosition(const nw::math::VEC3& value) { return this->GetOrientedBoundingBox().SetCenterPosition(value); }
342 
343     //! @brief リソースの初期化をおこないます。
344     Result Setup();
345 
346     //! @brief リソースの後始末をおこないます。
347     void   Cleanup();
348 };
349 typedef nw::ut::ResArrayClass<ResShape>::type  ResShapeArray;
350 
351 
352 //! @details :private
353 struct ResSeparateDataShapeData : public ResShapeData
354 {
355     nw::ut::ResS32 m_VertexAttributesTableCount;
356     nw::ut::Offset toVertexAttributesTable;
357     nw::ut::Offset toMorphShape;
358 };
359 
360 
361 //--------------------------------------------------------------------------
362 //! @brief 複数の属性を組み合わせて形状を現すバイナリリソースクラスです。
363 //---------------------------------------------------------------------------
364 class ResSeparateDataShape : public ResShape
365 {
366 public:
367     enum { TYPE_INFO = NW_GFX_RES_TYPE_INFO(ResSeparateDataShape) };
368     enum { SIGNATURE = NW_RES_SIGNATURE32('SPSH') };
369 
370     NW_RES_CTOR_INHERIT( ResSeparateDataShape, ResShape )
371 
372     //---------------------------------------------------------------------------
373     //! @fn           s32 GetVertexAttributesCount() const
374     //! @brief        頂点属性の要素数を取得します。
375     //---------------------------------------------------------------------------
376     //---------------------------------------------------------------------------
377     //! @fn           ResVertexAttribute GetVertexAttributes(int idx)
378     //! @brief        頂点属性を取得します。
379     //---------------------------------------------------------------------------
380     //---------------------------------------------------------------------------
381     //! @fn           ResSeparateDataMorphShape GetMorphShape()
382     //! @brief        頂点モーフィングの設定を取得します。
383     //---------------------------------------------------------------------------
384     NW_RES_FIELD_CLASS_LIST_DECL( ResVertexAttribute, VertexAttributes ) // GetVertexAttributes(int idx), GetVertexAttributesCount()
385     NW_RES_FIELD_CLASS_DECL( ResSeparateDataMorphShape, MorphShape )     // GetMorphShape()
386 };
387 
388 } // namespace res
389 
390 namespace internal {
391 
392 //--------------------------------------------------------------------------
393 //! @brief ResInterleavedVertexStream に含まれる実データを持たない内部頂点属性も含めて列挙するイテレータです。
394 //!
395 //! @detail nw::gfx::GatherVertexAttributes 関数で取得します。
396 //---------------------------------------------------------------------------
397 class ResVertexAttributeIterator
398 {
399 public:
400     //---------------------------------------------------------------------------
401     //! @brief        シェイプから、ResVertexAttributeIterator を生成します。
402     //!
403     //! @param[in]    shape   シェイプリソースです。
404     //!
405     //! @return       先頭の頂点属性を指すイテレータです。
406     //---------------------------------------------------------------------------
Begin(ResSeparateDataShape shape)407     static ResVertexAttributeIterator Begin(ResSeparateDataShape shape)
408     {
409         return ResVertexAttributeIterator(shape);
410     }
411 
412     //---------------------------------------------------------------------------
413     //! @brief        コピーコンストラクタです。
414     //!
415     //! @param[in]    value   コピー元の値です。
416     //---------------------------------------------------------------------------
ResVertexAttributeIterator(const ResVertexAttributeIterator & value)417     /* implicit */ ResVertexAttributeIterator(const ResVertexAttributeIterator& value)
418      : m_Shape( value.m_Shape ),
419        m_Interleave( value.m_Interleave ),
420        m_IndexOnShape( value.m_IndexOnShape ),
421        m_IndexOnInterleave( value.m_IndexOnInterleave )
422     {
423     }
424 
425     //---------------------------------------------------------------------------
426     //! @brief        イテレータが有効な値を指しているかどうかを取得します。
427     //!
428     //! @return       有効な値であれば true、そうでなければ false を返します。
429     //---------------------------------------------------------------------------
IsValid()430     bool IsValid() const
431     {
432         return (m_IndexOnShape >= 0);
433     }
434 
435     //---------------------------------------------------------------------------
436     //! @brief        ポインタ参照演算子です。
437     //!
438     //! @return       イテレータの指している頂点属性を返します。
439     //---------------------------------------------------------------------------
440     ResVertexAttribute operator*()
441     {
442         if (m_Interleave.IsValid())
443         {
444             return m_Interleave.GetVertexStreams( m_IndexOnInterleave );
445         }
446         else
447         {
448             return m_Shape.GetVertexAttributes( m_IndexOnShape );
449         }
450     }
451 
452     //---------------------------------------------------------------------------
453     //! @brief        ポインタ参照演算子です。
454     //!
455     //! @return       イテレータの指している頂点属性を返します。
456     //---------------------------------------------------------------------------
457     const ResVertexAttribute operator*() const
458     {
459         if (m_Interleave.IsValid())
460         {
461             return m_Interleave.GetVertexStreams( m_IndexOnInterleave );
462         }
463         else
464         {
465             return m_Shape.GetVertexAttributes( m_IndexOnShape );
466         }
467     }
468 
469 
470     //---------------------------------------------------------------------------
471     //! @brief        前置のインクリメント演算子です。
472     //!
473     //! @return       インクリメント後のイテレータを返します。
474     //---------------------------------------------------------------------------
475     ResVertexAttributeIterator& operator++()
476     {
477         if (m_Interleave.IsValid())
478         {
479             ++m_IndexOnInterleave;
480             if (m_Interleave.GetVertexStreamsCount() > m_IndexOnInterleave)
481             {
482                 return *this;
483             }
484 
485             m_Interleave = ResInterleavedVertexStream(NULL);
486             m_IndexOnInterleave = -1;
487         }
488 
489         ++m_IndexOnShape;
490         if (m_Shape.GetVertexAttributesCount() > m_IndexOnShape)
491         {
492             ResVertexAttribute attribute = m_Shape.GetVertexAttributes(m_IndexOnShape);
493 
494             if (attribute.GetFlags() & ResVertexAttribute::FLAG_INTERLEAVE)
495             {
496                 m_Interleave = ResStaticCast<ResInterleavedVertexStream>( attribute );
497                 m_IndexOnInterleave = 0;
498             }
499         }
500         else
501         {
502             m_IndexOnShape = -1;
503         }
504 
505         return *this;
506     }
507 
508     //---------------------------------------------------------------------------
509     //! @brief        後置のインクリメント演算子です。
510     //!
511     //! @return       インクリメント前のイテレータを返します。
512     //---------------------------------------------------------------------------
513     ResVertexAttributeIterator operator++(int)
514     {
515         ResVertexAttributeIterator copy = *this;
516 
517         this->operator++();
518 
519         return copy;
520     }
521 
522 private:
523     ResSeparateDataShape       m_Shape;
524     ResInterleavedVertexStream m_Interleave;
525     s32                        m_IndexOnShape;
526     s32                        m_IndexOnInterleave;
527 
528     //---------------------------------------------------------------------------
529     //! @brief        コンストラクタです。
530     //!
531     //! @param[in]    shape
532     //---------------------------------------------------------------------------
533 
ResVertexAttributeIterator(ResSeparateDataShape shape)534     explicit ResVertexAttributeIterator(ResSeparateDataShape shape)
535      : m_Shape( shape ),
536        m_Interleave( ResInterleavedVertexStream(NULL) ),
537        m_IndexOnShape( 0 ),
538        m_IndexOnInterleave( -1 )
539     {
540         NW_ASSERT( shape.IsValid() );
541 
542         ResVertexAttribute attribute = shape.GetVertexAttributes(0);
543 
544         if (attribute.GetFlags() & ResVertexAttribute::FLAG_INTERLEAVE)
545         {
546             m_Interleave = ResStaticCast<ResInterleavedVertexStream>( attribute );
547             m_IndexOnInterleave = 0;
548         }
549     }
550 };
551 
552 } // namespace internal
553 
554 } // namespace gfx
555 } // namespace nw
556 
557 #endif // NW_GFX_RESSHAPE_H_
558