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