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*>(¶meter);
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