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