1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Model.h
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 32372 $
16  *---------------------------------------------------------------------------*/
17 
18 #ifndef NW_GFX_MODEL_H_
19 #define NW_GFX_MODEL_H_
20 
21 #include <nw/gfx/gfx_TransformNode.h>
22 #include <nw/gfx/res/gfx_ResModel.h>
23 #include <nw/ut/ut_Flag.h>
24 #include <nw/ut/ut_MoveArray.h>
25 #include <nw/gfx/gfx_Material.h>
26 #include <nw/gfx/gfx_MaterialActivator.h>
27 #include <nw/gfx/gfx_SimpleMaterialActivator.h>
28 
29 namespace nw
30 {
31 namespace gfx
32 {
33 
34 class IMaterialActivator;
35 
36 //---------------------------------------------------------------------------
37 //! @brief        シーン上に表示されるオブジェクトを表すためのクラスです。
38 //---------------------------------------------------------------------------
39 class Model : public TransformNode
40 {
41 private:
42     NW_DISALLOW_COPY_AND_ASSIGN(Model);
43 
44 public:
45     NW_UT_RUNTIME_TYPEINFO;
46 
47     //! @brief 描画時に呼ばれるコールバック用スロットの定義です。
48     //!
49     //! @sa PreRenderSignal
50     //! @sa PostRenderSignal
51     typedef ut::Signal3<void, Model*, ResMesh, RenderContext*> RenderSignal;
52 
53     //! @brief 描画時に呼ばれるコールバック用スロットの定義です。
54     typedef RenderSignal::SlotType RenderSlot;
55 
56     //! バッファオプションのビットフラグの定義です。
57     enum BufferOption
58     {
59         //! @details :private
60         FLAG_BUFFER_SHADER_PARAMETER_SHIFT,
61         //! @details :private
62         FLAG_BUFFER_SHADING_PARAMETER_SHIFT,
63         //! @details :private
64         FLAG_BUFFER_MATERIAL_COLOR_SHIFT,
65         //! @details :private
66         FLAG_BUFFER_RASTERIZATION_SHIFT,
67         //! @details :private
68         FLAG_BUFFER_TEXTURE_COORDINATOR_SHIFT,
69         //! @details :private
70         FLAG_BUFFER_TEXTURE_MAPPER_SHIFT,
71         //! @details :private
72         FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER_SHIFT,
73         //! @details :private
74         FLAG_BUFFER_FRAGMENT_LIGHTING_SHIFT,
75         //! @details :private
76         FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE_SHIFT,
77         //! @details :private
78         FLAG_BUFFER_TEXTURE_COMBINER_SHIFT,
79         //! @details :private
80         FLAG_BUFFER_ALPHA_TEST_SHIFT,
81         //! @details :private
82         FLAG_BUFFER_FRAGMENT_OPERATION_SHIFT,
83         //! @details :private
84         FLAG_BUFFER_SCENE_ENVIRONMENT_SHIFT,
85 
86         //! シェーダーパラメータを利用するならば、1になります。
87         FLAG_BUFFER_SHADER_PARAMETER                = 0x1 << FLAG_BUFFER_SHADER_PARAMETER_SHIFT,
88         //! シェーディングパラメータを利用するならば、1になります。
89         FLAG_BUFFER_SHADING_PARAMETER               = 0x1 << FLAG_BUFFER_SHADING_PARAMETER_SHIFT,
90         //! マテリアルカラーを利用するならば、1になります。
91         FLAG_BUFFER_MATERIAL_COLOR                  = 0x1 << FLAG_BUFFER_MATERIAL_COLOR_SHIFT,
92         //! ラスタライゼーションを利用するならば、1になります。
93         FLAG_BUFFER_RASTERIZATION                   = 0x1 << FLAG_BUFFER_RASTERIZATION_SHIFT,
94         //! テクスチャコーディネータを利用するならば、1になります。
95         FLAG_BUFFER_TEXTURE_COORDINATOR             = 0x1 << FLAG_BUFFER_TEXTURE_COORDINATOR_SHIFT,
96         //! テクスチャマッパーを利用するならば、1になります。
97         FLAG_BUFFER_TEXTURE_MAPPER                  = 0x1 << FLAG_BUFFER_TEXTURE_MAPPER_SHIFT,
98         //! 未実装です。
99         FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER       = 0x1 << FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER_SHIFT,
100         //! フラグメントライティングを利用するならば、1になります。
101         FLAG_BUFFER_FRAGMENT_LIGHTING               = 0x1 << FLAG_BUFFER_FRAGMENT_LIGHTING_SHIFT,
102         //! @brief フラグメントライティングテーブルを利用するならば、1になります。
103         FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE         = 0x1 << FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE_SHIFT,
104         //! テクスチャコンバイナを利用するならば、1になります。
105         FLAG_BUFFER_TEXTURE_COMBINER                = 0x1 << FLAG_BUFFER_TEXTURE_COMBINER_SHIFT,
106         //! アルファテストを利用するならば、1になります。
107         FLAG_BUFFER_ALPHA_TEST                      = 0x1 << FLAG_BUFFER_ALPHA_TEST_SHIFT,
108         //! フラグメントオペレーションを利用するならば、1になります。
109         FLAG_BUFFER_FRAGMENT_OPERATION              = 0x1 << FLAG_BUFFER_FRAGMENT_OPERATION_SHIFT,
110         //! シーン環境を利用するならば、1になります。
111         FLAG_BUFFER_SCENE_ENVIRONMENT               = 0x1 << FLAG_BUFFER_SCENE_ENVIRONMENT_SHIFT,
112 
113         FLAG_BUFFER_NOT_USE = 0, //!< バッファオプションを使用しません。
114 
115         //! フラグメントシェーダーを一括指定するためのフラグです。
116         MULTI_FLAG_BUFFER_FRAGMENT_SHADER =
117             FLAG_BUFFER_FRAGMENT_LIGHTING         |
118             FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE   |
119             FLAG_BUFFER_TEXTURE_COMBINER          |
120             FLAG_BUFFER_ALPHA_TEST,
121 
122         //! マテリアルを一括指定するためのフラグです。
123         MULTI_FLAG_BUFFER_MATERIAL =
124             FLAG_BUFFER_SHADER_PARAMETER          |
125             FLAG_BUFFER_SHADING_PARAMETER         |
126             FLAG_BUFFER_MATERIAL_COLOR            |
127             FLAG_BUFFER_RASTERIZATION             |
128             FLAG_BUFFER_TEXTURE_COORDINATOR       |
129             FLAG_BUFFER_TEXTURE_MAPPER            |
130             FLAG_BUFFER_PROCEDURAL_TEXTURE_MAPPER |
131             FLAG_BUFFER_FRAGMENT_LIGHTING         |
132             FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE   |
133             FLAG_BUFFER_TEXTURE_COMBINER          |
134             FLAG_BUFFER_ALPHA_TEST                |
135             FLAG_BUFFER_FRAGMENT_OPERATION        |
136             FLAG_BUFFER_SCENE_ENVIRONMENT,
137 
138         //! マテリアルのうち、アニメーションする要素を一括指定するためのフラグです。
139         MULTI_FLAG_ANIMATABLE_MATERIAL =
140             FLAG_BUFFER_MATERIAL_COLOR      |
141             FLAG_BUFFER_TEXTURE_COORDINATOR |
142             FLAG_BUFFER_TEXTURE_MAPPER      |
143             FLAG_BUFFER_FRAGMENT_OPERATION,
144 
145 
146         //! マテリアルのうち、ライトに関連する要素を一括指定するためのフラグです。
147         MULTI_FLAG_LIGHTING_MATERIAL =
148             FLAG_BUFFER_SHADING_PARAMETER       |
149             FLAG_BUFFER_MATERIAL_COLOR          |
150             FLAG_BUFFER_FRAGMENT_LIGHTING       |
151             FLAG_BUFFER_FRAGMENT_LIGHTING_TABLE |
152             FLAG_BUFFER_SCENE_ENVIRONMENT
153     };
154 
155     //! @brief 設定内容です。
156     struct Description : public TransformNode::Description
157     {
158         bit32 bufferOption;          //!< バッファの生成オプションです。
159         Model* sharedMaterialModel; //!< 共有元のマテリアルを持つモデルです。
160 
161         //! @brief コンストラクタです。
DescriptionDescription162         Description() :
163             bufferOption(0),
164             sharedMaterialModel(NULL)
165         {}
166     };
167 
168     //---------------------------------------------------------------------------
169     //! @brief デフォルトのモデル表示フラグ判定関数オブジェクトです。
170     //---------------------------------------------------------------------------
171     struct IsVisibleModelDefaultFunctor
172     {
IsVisibleIsVisibleModelDefaultFunctor173         bool IsVisible(const nw::gfx::Model* model)
174         {
175             return model->IsVisible() && model->IsEnabledResults(SceneNode::FLAG_IS_VISIBLE);
176         }
177     };
178 
179     //----------------------------------------
180     //! @name 作成/破棄
181     //@{
182 
183     //! @brief        モデルを生成します。
184     //!
185     //! @param[in]    parent 親のノードです。
186     //! @param[in]    resource リソースです。
187     //! @param[in]    description 設定内容です。
188     //! @param[in]    allocator アロケータです。
189     //!
190     //! @return       生成されたモデルです。
191     //!
192     static Model* Create(
193         SceneNode* parent,
194         ResSceneObject resource,
195         const Model::Description& description,
196         os::IAllocator* allocator);
197 
198     //! @brief        生成時に必要なメモリサイズを取得します。
199     //!
200     //! @param[in]    resource リソースです。
201     //! @param[in]    description 設定内容です。
202     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
203     static size_t GetMemorySize(
204         ResModel resModel,
205         Description description,
206         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
207     {
208         os::MemorySizeCalculator size(alignment);
209 
210         GetMemorySizeInternal(&size, resModel, description);
211 
212         return size.GetSizeWithPadding(alignment);
213     }
214 
215 
216     //! @details :private
GetMemorySizeInternal(os::MemorySizeCalculator * pSize,ResModel resModel,Description description)217     static void GetMemorySizeInternal(
218         os::MemorySizeCalculator* pSize,
219         ResModel resModel,
220         Description description)
221     {
222         os::MemorySizeCalculator& size = *pSize;
223 
224         size += sizeof(Model);
225         GetMemorySizeForInitialize(pSize, resModel, description);
226     }
227 
228     //@}
229 
230     //----------------------------------------
231     //! @name シーンツリー
232     //@{
233 
234     //! @brief        ビジターを受け付けます。
235     //!
236     //! @param[in]    visitor ビジターです。
237     //!
238     virtual void Accept(ISceneVisitor* visitor);
239 
240     //@}
241 
242     //----------------------------------------
243     //! @name リソース
244     //@{
245 
246     //! @brief モデルのリソースを取得します。
GetResModel()247     ResModel GetResModel()
248     {
249         // return ResDynamicCast<ResModel>(this->GetResSceneObject());
250         return ResModel(this->GetResSceneObject().ptr());
251     }
252 
253     //! @brief モデルのリソースを取得します。
GetResModel()254     const ResModel GetResModel() const
255     {
256         // return ResDynamicCast<ResModel>(this->GetResSceneObject());
257         return ResModel(this->GetResSceneObject().ptr());
258     }
259 
260     //! @brief メッシュのリソースの配列を取得します。
261     //!
262     //! メッシュのリソースはモデルリソースから取得するのではなく、
263     //! このメソッドを使って取得するようにしてください。
264     //!
265     //! @return メッシュのリソースの配列を取得します。
266     //!
GetResMeshes()267     ResMeshArray GetResMeshes()
268     {
269         if (this->m_MeshBuffers.empty())
270         {
271             ResModel model = this->GetResModel();
272             NW_ASSERT(model.IsValid());
273             return model.GetMeshes();
274         }
275         return this->m_MeshBuffers;
276     }
277 
278     //! @brief インデックスを指定して MeshNodeVisibility のリソースを取得します。
279     //!
280     //! MeshNodeVisibility のリソースはモデルリソースから取得するのではなく、
281     //! このメソッドを使って取得するようにしてください。
282     //!
283     //! @param[in] idx インデックスです。
284     //!
285     //! @return MeshNodeVisibility のリソースを取得します。
286     //!
GetResMeshNodeVisibilities(int idx)287     ResMeshNodeVisibility GetResMeshNodeVisibilities(int idx)
288     {
289         if (this->m_MeshNodeVisibilityBuffers.empty())
290         {
291             ResModel model = this->GetResModel();
292             NW_ASSERT(model.IsValid());
293             return model.GetMeshNodeVisibilities(idx);
294         }
295         return ResMeshNodeVisibility( &this->m_MeshNodeVisibilityBuffers[idx] );
296     }
297 
298     //@}
299 
300     //----------------------------------------
301     //! @name アニメーション
302     //@{
303 
304     //! @brief マテリアルアニメーショングループを取得します。
GetMaterialAnimGroup()305     AnimGroup* GetMaterialAnimGroup() { return m_MaterialAnimGroup; }
306 
307     //! @brief マテリアルアニメーショングループを取得します。
GetMaterialAnimGroup()308     const AnimGroup* GetMaterialAnimGroup() const { return m_MaterialAnimGroup; }
309 
310     //! @brief マテリアルアニメーショングループのアニメーションバインディング中のインデックスを取得します。
GetMaterialAnimBindingIndex()311     int GetMaterialAnimBindingIndex() const { return m_MaterialAnimBindingIndex; }
312 
313     //! @brief マテリアルアニメーションオブジェクトを取得します。
314     const AnimObject* GetMaterialAnimObject(int objectIndex = 0) const
315     {
316         NW_NULL_ASSERT(m_AnimBinding);
317         return m_AnimBinding->GetAnimObject(m_MaterialAnimBindingIndex, objectIndex);
318     }
319 
320     //! @brief マテリアルアニメーションオブジェクトを取得します。
321     AnimObject* GetMaterialAnimObject(int objectIndex = 0)
322     {
323         NW_NULL_ASSERT(m_AnimBinding);
324         return m_AnimBinding->GetAnimObject(m_MaterialAnimBindingIndex, objectIndex);
325     }
326 
327     //! @brief マテリアルアニメーションオブジェクトを設定します。
328     //!
329     //! @param[in] animObject 設定するアニメーションオブジェクトです。NULL を指定するとアニメーションを解除します。
330     void SetMaterialAnimObject(AnimObject* animObject, int objectIndex = 0)
331     {
332         NW_NULL_ASSERT(m_AnimBinding);
333         m_AnimBinding->SetAnimObject(m_MaterialAnimBindingIndex, animObject, objectIndex);
334     }
335 
336     //! @brief ビジビリティアニメーショングループを取得します。
GetVisibilityAnimGroup()337     AnimGroup* GetVisibilityAnimGroup() { return m_VisibilityAnimGroup; }
338 
339     //! @brief ビジビリティアニメーショングループを取得します。
GetVisibilityAnimGroup()340     const AnimGroup* GetVisibilityAnimGroup() const { return m_VisibilityAnimGroup; }
341 
342     //! @brief ビジビリティアニメーショングループのアニメーションバインディング中のインデックスを取得します。
GetVisibilityAnimBindingIndex()343     int GetVisibilityAnimBindingIndex() const { return m_VisibilityAnimBindingIndex; }
344 
345     //! @brief ビジビリティアニメーションオブジェクトを取得します。
346     const AnimObject* GetVisibilityAnimObject(int objectIndex = 0) const
347     {
348         NW_NULL_ASSERT(m_AnimBinding);
349         return m_AnimBinding->GetAnimObject(m_VisibilityAnimBindingIndex, objectIndex);
350     }
351 
352     //! @brief ビジビリティアニメーションオブジェクトを取得します。
353     AnimObject* GetVisibilityAnimObject(int objectIndex = 0)
354     {
355         NW_NULL_ASSERT(m_AnimBinding);
356         return m_AnimBinding->GetAnimObject(m_VisibilityAnimBindingIndex, objectIndex);
357     }
358 
359     //! @brief ビジビリティアニメーションオブジェクトを設定します。
360     //!
361     //! @param[in] animObject 設定するアニメーションオブジェクトです。NULL を指定するとアニメーションを解除します。
362    void SetVisibilityAnimObject(AnimObject* animObject, int objectIndex = 0)
363     {
364         NW_NULL_ASSERT(m_AnimBinding);
365         m_AnimBinding->SetAnimObject(m_VisibilityAnimBindingIndex, animObject, objectIndex);
366     }
367 
368     //@}
369 
370     //----------------------------------------
371     //! @name コールバック
372     //@{
373 
374     //! @brief モデルの描画前に呼び出されるシグナルを取得します。
375     //!
376     //! このシグナルはライブラリからは呼び出されません。
377     //! シグナルを有効にするためには、ユーザーが明示的に呼び出す必要があります。
378     //!
379     //! @sa RenderSignal
PreRenderSignal()380     RenderSignal& PreRenderSignal() { return *m_PreRenderSignal; }
381 
382     //! @brief モデルの描画前に呼び出されるシグナルを取得します。
383     //!
384     //! このシグナルはライブラリからは呼び出されません。
385     //! シグナルを有効にするためには、ユーザーが明示的に呼び出す必要があります。
386     //!
387     //! @sa RenderSignal
PreRenderSignal()388     const RenderSignal& PreRenderSignal() const { return *m_PreRenderSignal; }
389 
390     //! @brief モデルの描画後に呼び出されるシグナルを取得します。
391     //!
392     //! このシグナルはライブラリからは呼び出されません。
393     //! シグナルを有効にするためには、ユーザーが明示的に呼び出す必要があります。
394     //!
395     //! @sa RenderSignal
PostRenderSignal()396     RenderSignal& PostRenderSignal() { return *m_PostRenderSignal; }
397 
398     //! @brief モデルの描画後に呼び出されるシグナルを取得します。
399     //!
400     //! このシグナルはライブラリからは呼び出されません。
401     //! シグナルを有効にするためには、ユーザーが明示的に呼び出す必要があります。
402     //!
403     //! @sa RenderSignal
PostRenderSignal()404     const RenderSignal& PostRenderSignal() const { return *m_PostRenderSignal; }
405 
406 
407     // [非推奨] 互換性のために残してありますが、こちらの定義は用いないでください。
408 
409     //! @details :private
410     typedef gfx::MaterialArray MaterialArray;
411 
412     //@}
413 
414     //----------------------------------------
415     //! @name マテリアル
416     //@{
417 
418     //! @brief マテリアルのリストの範囲を表す型の定義です。
419     typedef std::pair<
420         gfx::MaterialArray::iterator,
421         gfx::MaterialArray::iterator> MaterialRange;
422 
423     //! @brief マテリアルのリストの先頭と末尾を取得します。
GetMaterials()424     MaterialRange GetMaterials()
425     {
426         return std::make_pair(
427             m_Materials.begin(),
428             m_Materials.end());
429     }
430 
431     //! @brief マテリアルの数を取得します。
GetMaterialCount()432     int GetMaterialCount() const { return m_Materials.size(); }
433 
434     //! @brief 指定したインデックス番号のマテリアルを取得します。
GetMaterial(int index)435     Material* GetMaterial(int index)
436     {
437         return m_Materials[index];
438     }
439 
440     //! @brief 指定したインデックス番号のマテリアルを取得します。
GetMaterial(int index)441     const Material* GetMaterial(int index) const
442     {
443         return m_Materials[index];
444     }
445 
446     //! @brief マテリアルアクティベータを取得します。
GetMaterialActivator()447     const IMaterialActivator* GetMaterialActivator() const
448     {
449         return this->m_MaterialActivator.Get();
450     }
451 
452     //! @brief マテリアルアクティベータを取得します。
GetMaterialActivator()453     IMaterialActivator* GetMaterialActivator()
454     {
455         return this->m_MaterialActivator.Get();
456     }
457 
458     //! @brief 所有権の移動を行いマテリアルアクティベータを設定します。
459     //!        モデルクラスが破棄された場合に一緒に破棄されます。
SetMaterialActivator(IMaterialActivator * materialActivator)460     void SetMaterialActivator(IMaterialActivator* materialActivator)
461     {
462         return this->m_MaterialActivator.Reset(materialActivator);
463     }
464 
465     //! @brief 所有権の移動を行わずにマテリアルアクティベータを設定します。
466     //!        ユーザー側でマテリアルアクティベータを管理する場合はこちらで設定してください。
SetSharedMaterialActivator(IMaterialActivator * materialActivator)467     void SetSharedMaterialActivator(IMaterialActivator* materialActivator)
468     {
469         return this->m_MaterialActivator.Reset(materialActivator, false);
470     }
471 
472     //@}
473 
474     //----------------------------------------
475     //! @name バッファオプション
476     //@{
477 
478     //! @brief バッファオプションを確認します。
CheckBufferOption(bit32 bufferOption)479     bool CheckBufferOption(bit32 bufferOption) const
480     {
481         return ut::CheckFlag(this->m_BufferOption, bufferOption);
482     }
483 
484     //! @brief バッファオプションを取得します。
GetBufferOption()485     bit32 GetBufferOption() const
486     {
487         return this->m_BufferOption;
488     }
489 
490     //@}
491 
492     //----------------------------------------
493     //! @name マトリクス
494     //@{
495 
496     //! @brief モデルビューマトリクスを取得します。
ModelViewMatrix()497     math::MTX34& ModelViewMatrix()
498     {
499         return this->m_ModelViewMatrix;
500     }
501 
502     //! @brief モデルビューマトリクスを取得します。
ModelViewMatrix()503     const math::MTX34& ModelViewMatrix() const
504     {
505         return this->m_ModelViewMatrix;
506     }
507 
508     //! @brief 法線マトリクスを取得します。
NormalMatrix()509     math::MTX34& NormalMatrix()
510     {
511         return this->m_NormalMatrix;
512     }
513 
514     //! @brief 法線マトリクスを取得します。
NormalMatrix()515     const math::MTX34& NormalMatrix() const
516     {
517         return this->m_NormalMatrix;
518     }
519 
520     //! @brief モデルビュー行列と法線用行列を更新します。
521     NW_INLINE void UpdateModelViewMatrixAndNormalMatrix(
522         const math::MTX34& viewMatrix, bool isModelCoordinate);
523 
524     //@}
525 
526     //----------------------------------------
527     //! @name レイヤー
528     //@{
529 
530     //! @brief レイヤーIDを取得します。
GetLayerId()531     u8 GetLayerId() const { return m_LayerId; }
532 
533     //! @brief レイヤーIDを設定します。
SetLayerId(u8 layerId)534     void SetLayerId(u8 layerId) { m_LayerId = layerId; }
535 
536      //! @brief メッシュの描画レイヤー値を取得します。
GetRenderLayerId(ResMesh mesh)537     ResMaterial::TranslucencyKind GetRenderLayerId(ResMesh mesh)
538     {
539         NW_ASSERT(mesh.IsValid());
540         Material* material = this->GetMaterial(mesh.GetMaterialIndex());
541 
542         ResMaterial shadingParametersResMaterial = material->GetShadingParameterResMaterial();
543         NW_ASSERT(shadingParametersResMaterial.IsValid());
544 
545         return shadingParametersResMaterial.GetTranslucencyKind();
546     }
547 
548     //@}
549 
550     //----------------------------------------
551     //! @name 描画
552     //@{
553 
554     //! @brief モデルを描画するかどうかのフラグを取得します。
IsVisible()555     bool IsVisible() const { return m_Visible; }
556 
557     //! @brief モデルを描画するかどうかのフラグを設定します。
SetVisible(bool visible)558     void SetVisible(bool visible) { m_Visible = visible; }
559 
560     //! @brief メッシュが描画されるかどうかのフラグを取得します。
561     //!
562     //! メッシュのビジビリティとメッシュノードビジビリティの論理積を返します。
563     //!
564     //! @param[in] mesh 対象のメッシュです。
565     //!
566     //! @return メッシュが描画されるかどうかのフラグを返します。
IsMeshVisible(ResMesh mesh)567     bool IsMeshVisible(ResMesh mesh)
568     {
569         int index = mesh.GetMeshNodeVisibilityIndex();
570         if (index < 0)
571         {
572             return mesh.IsVisible();
573         }
574         else
575         {
576             ResMeshNodeVisibility visibility = this->GetResMeshNodeVisibilities(index);
577             NW_ASSERT(visibility.IsValid());
578             {
579                 return visibility.IsVisible() && mesh.IsVisible();
580             }
581         }
582     }
583 
584     //! @brief 描画ソート用キーのキャッシュを無効化します。
585     //!
586     //! @sa RenderQueue::Reset
587     void InvalidateRenderKeyCache();
588     //@}
589 
590     //----------------------------------------
591     //! @name ユーザーパラメータ
592     //@{
593 
594     //! @brief ユーザーパラメータを取得します。
595     template<typename Type>
GetUserParameter()596     Type GetUserParameter() const
597     {
598         NW_STATIC_ASSERT(sizeof(Type) <= 4);
599         return *reinterpret_cast<const Type*>(&m_UserParameter);
600     }
601 
602     //! @brief ユーザーパラメータを設定します。
603     template<typename Type>
SetUserParameter(Type parameter)604     void SetUserParameter(Type parameter)
605     {
606         NW_STATIC_ASSERT(sizeof(Type) <= 4);
607         m_UserParameter = *reinterpret_cast<u32*>(&parameter);
608     }
609 
610     //@}
611 
612 
613 protected:
614     virtual Result Initialize(os::IAllocator* allocator);
615 
616     //----------------------------------------
617     //! @name コンストラクタ/デストラクタ
618     //@{
619 
620     //! コンストラクタです。
Model(os::IAllocator * allocator,ResTransformNode resource,const Model::Description & description)621     Model(
622         os::IAllocator* allocator,
623         ResTransformNode resource,
624         const Model::Description& description)
625     : TransformNode(
626         allocator,
627         resource,
628         description),
629       m_MaterialAnimGroup(NULL),
630       m_MaterialAnimBindingIndex(0),
631       m_VisibilityAnimGroup(NULL),
632       m_VisibilityAnimBindingIndex(0),
633       m_PreRenderSignal(NULL),
634       m_PostRenderSignal(NULL),
635       m_MeshBuffers(NULL, NULL),
636       m_BufferOption(description.bufferOption),
637       m_ModelViewMatrix(math::MTX34::Identity()),
638       m_NormalMatrix(math::MTX34::Identity()),
639       m_LayerId(0),
640       m_OriginalVisibility(true),
641       m_Visible(true),
642       m_SharingMaterial(description.sharedMaterialModel != NULL),
643       m_Description(description),
644       m_UserParameter(0)
645     {
646         SetVisible(ResStaticCast<ResModel>(resource).IsVisible());
647     }
648 
649     //! デストラクタです。
~Model()650     virtual ~Model()
651     {
652         DestroyResMeshes(&GetAllocator(), m_MeshBuffers);
653         SafeDestroy(this->m_PreRenderSignal);
654         SafeDestroy(this->m_PostRenderSignal);
655 
656         if (!m_SharingMaterial)
657         {
658             SafeDestroyAll(this->m_Materials);
659         }
660 
661         SafeDestroy(this->m_MaterialAnimGroup);
662         SafeDestroy(this->m_VisibilityAnimGroup);
663     }
664 
665     //@}
666 
667     //! @brief   Initialize() の実行に必要なメモリサイズを取得します。
668     //!
669     //! @details :private
GetMemorySizeForInitialize(os::MemorySizeCalculator * pSize,ResModel resModel,Description description)670     static void GetMemorySizeForInitialize(
671         os::MemorySizeCalculator* pSize,
672         ResModel resModel,
673         Description description)
674     {
675         NW_ASSERT(description.isFixedSizeMemory);
676 
677         os::MemorySizeCalculator& size = *pSize;
678 
679         TransformNode::GetMemorySizeForInitialize(pSize, resModel, description);
680 
681         // Model::CreateResMeshes
682         const s32 meshesCount = resModel.GetMeshesCount();
683         const s32 visibilitiesConut = resModel.GetMeshNodeVisibilitiesCount();
684 
685         size += sizeof(ut::Offset) * meshesCount;
686         size += sizeof(ResMeshData) * meshesCount;
687         size += sizeof(bool) * meshesCount;
688 
689         // Model::CreateResMeshNodeVisibilities
690         size += sizeof(ResMeshNodeVisibilityData) * visibilitiesConut;
691         size += sizeof(bool) * visibilitiesConut;
692 
693         // Model::CreateMaterials
694         if (description.sharedMaterialModel != NULL)
695         {
696             const int materialCount = description.sharedMaterialModel->GetMaterialCount();
697             size += sizeof(Material*) * materialCount;
698         }
699         else
700         {
701             const s32 bufferCount = (description.bufferOption == 0x0) ? 0 : 1;
702             const s32 materialCount = resModel.GetMaterialsCount();
703 
704             size += sizeof(Material*) * materialCount;
705 
706             for (int i=0; i < materialCount ; i++)
707             {
708                 Material::GetMemorySizeInternal(
709                     pSize,
710                     resModel.GetMaterials(i),
711                     bufferCount,
712                     description.bufferOption);
713             }
714         }
715 
716         // Model::CreateCallbacks
717         if (description.maxCallbacks == 0)
718         {
719             RenderSignal::GetMemorySizeForInvalidateSignalInternal(pSize);
720             RenderSignal::GetMemorySizeForInvalidateSignalInternal(pSize);
721         }
722         else
723         {
724             RenderSignal::GetMemorySizeForFixedSizedSignalInternal(pSize, description.maxCallbacks);
725             RenderSignal::GetMemorySizeForFixedSizedSignalInternal(pSize, description.maxCallbacks);
726         }
727 
728         // Model::CreateAnimGroups
729         if (description.isAnimationEnabled)
730         {
731             const int animGroupCount = resModel.GetAnimGroupsCount();
732             for (int animGroupIdx = 0; animGroupIdx < animGroupCount; ++animGroupIdx)
733             {
734                 anim::ResAnimGroup resAnimGroup = resModel.GetAnimGroups(animGroupIdx);
735 
736                 if (
737                     resAnimGroup.GetTargetType() == anim::ResGraphicsAnimGroup::TARGET_TYPE_MATERIAL ||
738                     resAnimGroup.GetTargetType() == anim::ResGraphicsAnimGroup::TARGET_TYPE_VISIBILITY)
739                 {
740                     AnimGroup::Builder()
741                         .ResAnimGroup(resAnimGroup)
742                         .UseOriginalValue(true)
743                         .GetMemorySizeInternal(pSize);
744                 }
745             }
746         }
747 
748         // Model::CreateMaterialActivator
749         if (description.sharedMaterialModel == NULL)
750         {
751             if (description.bufferOption == 0 || description.bufferOption == FLAG_BUFFER_SCENE_ENVIRONMENT)
752             {
753                 SimpleMaterialActivator::GetMemorySizeInternal(pSize);
754             }
755             else
756             {
757                 MaterialActivator::GetMemorySizeInternal(pSize);
758             }
759         }
760     }
761 
762 private:
763 
764     //! マテリアルのメンバへの参照を解決します。
765     void BindMaterialAnim(AnimGroup* animGroup);
766 
767     //! ビジビリティのメンバへの参照を解決します。
768     void BindVisibilityAnim(AnimGroup* animGroup);
769 
770     //! メッシュリソースを生成します。
771     Result CreateResMeshes(os::IAllocator* allocator);
772 
773     //! メッシュリソースを破棄します。
774     void DestroyResMeshes(os::IAllocator* allocator, ResMeshArray resMeshes);
775 
776     //! MeshNodeVisibility リソースを生成します。
777     Result CreateResMeshNodeVisibilities(os::IAllocator* allocator);
778 
779     //! リソースからマテリアルを生成します。
780     Result CreateMaterials(os::IAllocator* allocator);
781 
782     //! アニメーショングループを生成します。
783     Result CreateAnimGroups(os::IAllocator* allocator);
784 
785     //! コールバック関数を生成します。
786     Result CreateCallbacks(os::IAllocator* allocator);
787 
788     //! マテリアルのアクティベータを生成します。
789     Result CreateMaterialActivator(os::IAllocator* allocator);
790 
791     //! アニメーションに登録するモデルデータのポインタを取得します。
792     void* GetAnimTargetObject(const anim::ResAnimGroupMember& anim);
793 
794     //! マテリアルアニメーションで書き換えるメンバへのポインタを取得します。
795     void* GetMaterialAnimTargetPtr(Material* material, const anim::ResAnimGroupMember& anim, bool isOriginalValue);
796 
797     //! アニメーション対象のマテリアルのインデックスを取得します。
798     int GetMaterialIndex(const anim::ResAnimGroupMember& anim) const;
799 
800     AnimGroup* m_MaterialAnimGroup;
801     s32 m_MaterialAnimBindingIndex;
802 
803     AnimGroup* m_VisibilityAnimGroup;
804     s32 m_VisibilityAnimBindingIndex;
805 
806     RenderSignal* m_PreRenderSignal;
807     RenderSignal* m_PostRenderSignal;
808 
809     nw::gfx::MaterialArray m_Materials;
810     ResMeshArray m_MeshBuffers;
811     ut::MoveArray<ResMeshNodeVisibilityData> m_MeshNodeVisibilityBuffers;
812     bit32 m_BufferOption;
813     math::MTX34 m_ModelViewMatrix;
814     math::MTX34 m_NormalMatrix;
815     GfxPtr<IMaterialActivator> m_MaterialActivator;
816 
817     // 以下 4 つのメンバはアライメントを揃えるために集めています。
818     u8 m_LayerId;
819     bool m_OriginalVisibility;
820     bool m_Visible;
821     bool m_SharingMaterial;
822 
823     ut::MoveArray<bool> m_MeshOriginalVisibilities;
824     ut::MoveArray<bool> m_MeshNodeOriginalVisibilities;
825 
826     const Model::Description& m_Description;
827 
828     u32 m_UserParameter;
829 };
830 
831 //----------------------------------------
832 NW_INLINE void
UpdateModelViewMatrixAndNormalMatrix(const math::MTX34 & viewMatrix,bool isModelCoordinate)833 Model::UpdateModelViewMatrixAndNormalMatrix(
834     const math::MTX34& viewMatrix,
835     bool isModelCoordinate)
836 {
837 #if 1 // フラグの判定を行うとより多くのCPU時間を消費する傾向にあるので、判定をせずに全て計算を行うほうを有効にしておきます。
838     // 累積スケールが1でない場合は法線マトリクスの向きを補正します。
839     if (isModelCoordinate)
840     {
841         // ViewMatrix * WorldInverseTranspose * ModelNormalVector
842         math::MTX34 worldInvTranspose;
843         math::MTX34InvTranspose(&worldInvTranspose, &this->WorldMatrix());
844         math::MTX34Mult(&this->NormalMatrix(), &viewMatrix, &worldInvTranspose);
845     }
846     else
847     {
848         if (this->WorldTransform().IsEnabledFlags(CalculatedTransform::FLAG_IS_SCALE_ONE))
849         {
850             // ViewMatrix * WorldNormalVector
851             math::MTX34Copy(&this->NormalMatrix(), &viewMatrix);
852         }
853         else
854         {
855             // ViewMatrix * WorldInverseTranspose * WorldInverse * WorldNormalVector
856             math::MTX34 worldInv;
857             math::MTX34 worldTranspose;
858             math::MTX34 worldInvTranspose;
859             math::MTX34Inverse(&worldInv, this->WorldMatrix());
860             math::MTX34Transpose(&worldTranspose, &worldInv);
861             math::MTX34Mult(&worldInvTranspose, &worldInv, &worldTranspose);
862             math::MTX34Mult(&this->NormalMatrix(), &viewMatrix, &worldInvTranspose);
863         }
864     }
865 #else
866     // 累積スケールが1でない場合は法線マトリクスの向きを補正します。
867     if (isModelCoordinate)
868     {
869         if (this->WorldTransform().IsEnabledFlags(CalculatedTransform::FLAG_IS_SCALE_ONE))
870         {
871             // ViewMatrix * WorldMatrix * ModelNormalVector
872             math::MTX34 modelView;
873             math::MTX34Mult(&modelView, &viewMatrix, &this->WorldMatrix());
874             math::MTX34Copy(&this->NormalMatrix(), &modelView);
875         }
876         else if (this->WorldTransform().IsEnabledFlags(CalculatedTransform::FLAG_IS_UNIFORM_SCALE))
877         {
878             // ViewMatrix * InverseScale * WorldMatrix * ModelNormalVector
879             math::MTX34 scaleMtx;
880             math::MTX34 reScaleMtx;
881             f32 scale = 1.0f / this->WorldTransform().Scale().x;
882             scaleMtx.SetupScale(math::VEC3(scale, scale, scale));
883             math::MTX34Mult(&reScaleMtx, &scaleMtx, &this->WorldMatrix());
884             math::MTX34Mult(&this->NormalMatrix(), &viewMatrix, &reScaleMtx);
885         }
886         else
887         {
888             // ViewMatrix * WorldInverseTranspose * ModelNormalVector
889             math::MTX34 worldInvTranspose;
890             math::MTX34InvTranspose(&worldInvTranspose, &this->WorldMatrix());
891             math::MTX34Mult(&this->NormalMatrix(), &viewMatrix, &worldInvTranspose);
892         }
893     }
894     else
895     {
896         if (this->WorldTransform().IsEnabledFlags(CalculatedTransform::FLAG_IS_SCALE_ONE))
897         {
898             // ViewMatrix * WorldNormalVector
899             math::MTX34Copy(&this->NormalMatrix(), &viewMatrix);
900         }
901         else if (this->WorldTransform().IsEnabledFlags(CalculatedTransform::FLAG_IS_UNIFORM_SCALE))
902         {
903             // ViewMatrix * InverseScale * WorldNormalVector
904             math::MTX34 scaleMtx;
905             f32 scale = 1.0f / this->WorldTransform().Scale().x;
906             scaleMtx.SetupScale(math::VEC3(scale, scale, scale));
907             math::MTX34Mult(&this->NormalMatrix(), &scaleMtx, &viewMatrix);
908         }
909         else
910         {
911             // ViewMatrix * WorldInverseTranspose * WorldInverse * WorldNormalVector
912             math::MTX34 worldInv;
913             math::MTX34 worldTranspose;
914             math::MTX34 worldInvTranspose;
915             math::MTX34Inverse(&worldInv, this->WorldMatrix());
916             math::MTX34Transpose(&worldTranspose, &worldInv);
917             math::MTX34Mult(&worldInvTranspose, &worldInv, &worldTranspose);
918             math::MTX34Mult(&this->NormalMatrix(), &viewMatrix, &worldInvTranspose);
919         }
920 #endif
921 }
922 
923 } // namespace gfx
924 } // namespace nw
925 
926 #endif // NW_GFX_MODEL_H_
927