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