1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_Material.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_MATERIAL_H_
17 #define NW_GFX_MATERIAL_H_
18 
19 #include <nw/gfx/gfx_SceneObject.h>
20 #include <nw/ut/ut_RuntimeTypeInfo.h>
21 #include <nw/ut/ut_MoveArray.h>
22 #include <nw/gfx/gfx_ShaderProgram.h>
23 
24 namespace nw
25 {
26 namespace gfx
27 {
28 
29 class Model;
30 class AnimGroup;
31 
32 //---------------------------------------------------------------------------
33 //! @brief        マテリアルを表すクラスです。
34 //!
35 //! マテリアルに対して、アニメーション後に生成時の状態に戻したい場合、Bufferを使用する必要があります。
36 //---------------------------------------------------------------------------
37 class Material : public SceneObject
38 {
39 private:
40     NW_DISALLOW_COPY_AND_ASSIGN(Material);
41 
42 public:
43     NW_UT_RUNTIME_TYPEINFO;
44 
45     //----------------------------------------
46     //! @name 作成
47     //@{
48 
49     //! @brief        リソースからマテリアルを生成します。
50     //!
51     //! @param[in]    resource リソースです。
52     //! @param[in]    bufferCount 生成するマテリアルバッファの数です。
53     //! @param[in]    parent マテリアルの親となるモデルクラスです。
54     //! @param[in]    allocator アロケータです。
55     //!
56     //! @return       生成されたマテリアルです。
57     //!
58     static Material* Create(
59         ResMaterial resource,
60         s32 bufferCount,
61         Model* parent,
62         os::IAllocator* allocator);
63 
64     //! @brief        生成時に必要なメモリサイズを取得します。
65     //!
66     //! @param[in]    resource リソースです。
67     //! @param[in]    bufferCount 生成するマテリアルバッファの数です。
68     //! @param[in]    parent マテリアルの親となるモデルクラスです。
69     //! @param[in]    alignment 計算に用いるアライメントです。2 のべき乗である必要があります。
70     static size_t GetMemorySize(
71         ResMaterial resource,
72         s32 bufferCount,
73         bit32 bufferOption,
74         size_t alignment = os::IAllocator::DEFAULT_ALIGNMENT)
75     {
76         os::MemorySizeCalculator size(alignment);
77 
78         GetMemorySizeInternal(&size, resource, bufferCount, bufferOption);
79 
80         return size.GetSizeWithPadding(alignment);
81     }
82 
83 
84     //! @details :private
85     static void GetMemorySizeInternal(
86         os::MemorySizeCalculator* pSize,
87         ResMaterial resource,
88         s32 bufferCount,
89         bit32 bufferOption);
90 
91     //@}
92 
93     //----------------------------------------
94     //! @name 取得/設定
95     //@{
96 
97     //! @brief オリジナルリソースを取得します。
GetOriginal()98     ResMaterial GetOriginal()
99     {
100         return ResStaticCast<ResMaterial>(this->GetResSceneObject());
101     }
102 
103     //! @brief オリジナルリソースを取得します。
GetOriginal()104     const ResMaterial GetOriginal() const
105     {
106         return ResStaticCast<ResMaterial>(this->GetResSceneObject());
107     }
108 
109     //! @brief 所有者となるモデルを取得します。
110     //!
111     //! @return マテリアルの所有者のモデルです。
112     //!
GetOwnerModel()113     Model* GetOwnerModel()
114     {
115         return this->m_Owner;
116     }
117 
118     //! @brief 所有者となるモデルを取得します。
119     //!
120     //! @return マテリアルの所有者のモデルです。
121     //!
GetOwnerModel()122     const Model* GetOwnerModel() const
123     {
124         return this->m_Owner;
125     }
126 
127     //! @brief リソースを設定します。
128     //!
129     //! @param[in] description シェーダプログラムの詳細設定です。
130     //!
SetDescription(ResShaderProgramDescription description)131     void SetDescription(ResShaderProgramDescription description) { m_ProgramDescription = description; }
132 
133     //! @brief リソースを取得します。
134     //!
135     //! @return シェーダプログラムの詳細設定です。
136     //!
GetDescription()137     const ResShaderProgramDescription GetDescription() const { return m_ProgramDescription; }
138 
139     //@}
140 
141     //----------------------------------------
142     //! @name バッファオプション関連
143     //@{
144 
145     //! @brief バッファの数を取得します。
GetBufferCount()146     int GetBufferCount() const
147     {
148         return this->m_Buffers.size();
149     }
150 
151     //! @brief バッファを取得します。
GetBuffer()152     ResMaterial GetBuffer()
153     {
154         bool hasBuffer = (0 < m_BufferCount);
155 
156         if (hasBuffer)
157         {
158             return this->m_Buffers[0];
159         }
160         else
161         {
162             return ResMaterial(NULL);
163         }
164     }
165 
166     //! バッファを取得します。
GetBuffer()167     const ResMaterial GetBuffer() const
168     {
169         bool hasBuffer = (0 < m_BufferCount);
170 
171         if (hasBuffer)
172         {
173             return this->m_Buffers[0];
174         }
175         else
176         {
177             return ResMaterial(NULL);
178         }
179     }
180 
181     //! 有効なシェーダーパラメータが取得できるマテリアルを取得します。
GetShaderParameterResMaterial()182     ResMaterial& GetShaderParameterResMaterial() { return m_ShaderParameterResMaterial; }
183 
184     //! 有効なシェーダーパラメータが取得できるマテリアルを取得します。
GetShaderParameterResMaterial()185     const ResMaterial& GetShaderParameterResMaterial() const { return m_ShaderParameterResMaterial; }
186 
187     //! 有効なシェーディングパラメータが取得できるマテリアルを取得します。
GetShadingParameterResMaterial()188     ResMaterial& GetShadingParameterResMaterial() { return m_ShadingParameterResMaterial; }
189 
190     //! 有効なシェーディングパラメータが取得できるマテリアルを取得します。
GetShadingParameterResMaterial()191     const ResMaterial& GetShadingParameterResMaterial() const { return m_ShadingParameterResMaterial; }
192 
193     //! 有効なマテリアルカラーが取得できるマテリアルを取得します。
GetMaterialColorResMaterial()194     ResMaterial& GetMaterialColorResMaterial() { return m_MaterialColorResMaterial; }
195 
196     //! 有効なマテリアルカラーが取得できるマテリアルを取得します。
GetMaterialColorResMaterial()197     const ResMaterial& GetMaterialColorResMaterial() const { return m_MaterialColorResMaterial; }
198 
199     //! 有効なラスタライゼーションが取得できるマテリアルを取得します。
GetRasterizationResMaterial()200     ResMaterial& GetRasterizationResMaterial() { return m_RasterizationResMaterial; }
201 
202     //! 有効なラスタライゼーションが取得できるマテリアルを取得します。
GetRasterizationResMaterial()203     const ResMaterial& GetRasterizationResMaterial() const { return m_RasterizationResMaterial; }
204 
205     //! 有効なテクスチャコーディネータが取得できるマテリアルを取得します。
GetTextureCoordinatorResMaterial()206     ResMaterial& GetTextureCoordinatorResMaterial() { return m_TextureCoordinatorResMaterial; }
207 
208     //! 有効なテクスチャコーディネータが取得できるマテリアルを取得します。
GetTextureCoordinatorResMaterial()209     const ResMaterial& GetTextureCoordinatorResMaterial() const { return m_TextureCoordinatorResMaterial; }
210 
211     //! 有効なテクスチャマッパーが取得できるマテリアルを取得します。
GetTextureMapperResMaterial()212     ResMaterial& GetTextureMapperResMaterial() { return m_TextureMapperResMaterial; }
213 
214     //! 有効なテクスチャマッパーが取得できるマテリアルを取得します。
GetTextureMapperResMaterial()215     const ResMaterial& GetTextureMapperResMaterial() const { return m_TextureMapperResMaterial; }
216 
217     //! 有効なフラグメントライティングが取得できるマテリアルを取得します。
GetFragmentLightingResMaterial()218     ResMaterial& GetFragmentLightingResMaterial() { return m_FragmentLightingResMaterial; }
219 
220     //! 有効なフラグメントライティングが取得できるマテリアルを取得します。
GetFragmentLightingResMaterial()221     const ResMaterial& GetFragmentLightingResMaterial() const { return m_FragmentLightingResMaterial; }
222 
223     //! 有効なフラグメントライティングテーブルが取得できるマテリアルを取得します。
GetFragmentLightingTableResMaterial()224     ResMaterial& GetFragmentLightingTableResMaterial() { return m_FragmentLightingTableResMaterial; }
225 
226     //! 有効なフラグメントライティングテーブルが取得できるマテリアルを取得します。
GetFragmentLightingTableResMaterial()227     const ResMaterial& GetFragmentLightingTableResMaterial() const { return m_FragmentLightingTableResMaterial; }
228 
229     //! 有効なテクスチャコンバイナが取得できるマテリアルを取得します。
GetTextureCombinerResMaterial()230     ResMaterial& GetTextureCombinerResMaterial() { return m_TextureCombinerResMaterial; }
231 
232     //! 有効なテクスチャコンバイナが取得できるマテリアルを取得します。
GetTextureCombinerResMaterial()233     const ResMaterial& GetTextureCombinerResMaterial() const { return m_TextureCombinerResMaterial; }
234 
235     //! 有効なアルファテストが取得できるマテリアルを取得します。
GetAlphaTestResMaterial()236     ResMaterial& GetAlphaTestResMaterial() { return m_AlphaTestResMaterial; }
237 
238     //! 有効なアルファテストが取得できるマテリアルを取得します。
GetAlphaTestResMaterial()239     const ResMaterial& GetAlphaTestResMaterial() const { return m_AlphaTestResMaterial; }
240 
241     //! 有効なフラグメントオペレーションが取得できるマテリアルを取得します。
GetFragmentOperationResMaterial()242     ResMaterial& GetFragmentOperationResMaterial() { return m_FragmentOperationResMaterial; }
243 
244     //! 有効なフラグメントオペレーションが取得できるマテリアルを取得します。
GetFragmentOperationResMaterial()245     const ResMaterial& GetFragmentOperationResMaterial() const { return m_FragmentOperationResMaterial; }
246 
247     //! 有効なシェーディングパラメータが取得できるマテリアルを取得します。
GetSceneEnvironmentResMaterial()248     ResMaterial& GetSceneEnvironmentResMaterial() { return m_SceneEnvironmentResMaterial; }
249 
250     //! 有効なシーン環境の設定が取得できるマテリアルを取得します。
GetSceneEnvironmentResMaterial()251     const ResMaterial& GetSceneEnvironmentResMaterial() const { return m_SceneEnvironmentResMaterial; }
252 
253     //@}
254 
255 protected:
256     //----------------------------------------
257     //! @name コンストラクタ/デストラクタ
258     //@{
259 
260     //! コンストラクタです。
261     Material(
262         os::IAllocator* allocator,
263         ResMaterial resMaterial,
264         s32 bufferCount,
265         Model* parent);
266 
267     //! デストラクタです。
268     virtual ~Material();
269 
270     //@}
271 
272     struct ResMaterialDestroyer : public std::unary_function<ResMaterial, void>
273     {
m_AllocatorResMaterialDestroyer274         ResMaterialDestroyer(os::IAllocator* allocator = 0) : m_Allocator(allocator)
275         {}
operatorResMaterialDestroyer276         result_type operator()(argument_type data)
277         {
278             DestroyResMaterial(m_Allocator, data);
279         }
280 
281         os::IAllocator* m_Allocator;
282     };
283 
284 private:
285 
286     //! @brief メンバのメモリ確保と初期化を行います。
287     Result Initialize(os::IAllocator* allocator);
288 
289     //---------------------------------------------------------------------------
290     //! @brief        バッファを作成します。
291     //!
292     //! @param[in]    allocator アロケータです。
293     //---------------------------------------------------------------------------
294     Result CreateBuffers(os::IAllocator* allocator);
295 
296     //---------------------------------------------------------------------------
297     //! @brief        ResMaterialをコピーします。
298     //!
299     //! @param[in]    allocator        アロケータです。
300     //! @param[in]    bufferOption     生成オプションです。
301     //!
302     //! @return コピーしたマテリアルとコピー結果を表すフラグを返します。
303     //---------------------------------------------------------------------------
304     ::std::pair<ResMaterial, Result> CopyResMaterial(
305         os::IAllocator* allocator,
306         bit32 bufferOption);
307 
308     //---------------------------------------------------------------------------
309     //! @brief        ResMaterial のリソースを破棄します。
310     //!
311     //! @param[in]    allocator        リソース用のメモリを解放するアロケータです。
312     //! @param[in]    resMaterial      解放するリソースです。
313     //---------------------------------------------------------------------------
314     static void DestroyResMaterial(os::IAllocator* allocator, ResMaterial resMaterial);
315 
316     //---------------------------------------------------------------------------
317     //! @brief        ResFragmentShader のリソースを破棄します。
318     //!
319     //! @param[in]    allocator        リソース用のメモリを解放するアロケータです。
320     //! @param[in]    resFragmentShader 解放するリソースです。
321     //---------------------------------------------------------------------------
322     static void DestroyResFragmentShader(
323         os::IAllocator* allocator,
324         ResFragmentShader resFragmentShader);
325 
326     //---------------------------------------------------------------------------
327     //! @brief        ResShaderParameter のリソースを破棄します。
328     //!
329     //! @param[in]    allocator        リソース用のメモリを解放するアロケータです。
330     //! @param[in]    resShaderParameter 解放するリソースです。
331     //---------------------------------------------------------------------------
332     static void DestroyResShaderParameter(
333         os::IAllocator* allocator,
334         ResShaderParameter resShaderParameter);
335 
336     //---------------------------------------------------------------------------
337     //! @brief        リソースからフラグメントライティングテーブルをコピーします。
338     //!
339     //! @param[in]    allocator アロケータです。
340     //! @param[in]    resFragmentLightingTable オリジナルのデータです。
341     //---------------------------------------------------------------------------
342     ::std::pair<ResFragmentLightingTable, Result> CopyResFragmentLightingTable(
343         os::IAllocator* allocator,
344         ResFragmentLightingTable resFragmentLightingTable);
345 
346     //---------------------------------------------------------------------------
347     //! @brief        リソースからライティング参照テーブルをコピーします。
348     //!
349     //! @param[in]    allocator アロケータです。
350     //! @param[in]    resLightingLookupTable オリジナルのデータです。
351     //---------------------------------------------------------------------------
352     ::std::pair<ResLightingLookupTable, Result> CopyResLightingLookupTable(
353         os::IAllocator* allocator,
354         ResLightingLookupTable resLightingLookupTable);
355 
356     //! @brief アニメーション対象のリソースを取得します。
357     //!
358     //! @param objectType 対応するタイプです。
359     //! @return バッファがあればバッファを、無ければオリジナルを返します。
360     //!
GetActiveResource(u32 objectType)361     ResMaterial GetActiveResource(u32 objectType)
362     {
363         return (CanUseBuffer(objectType)) ? GetBuffer() : GetOriginal();
364     }
365 
366     //! @brief アニメーションに登録するモデルデータのポインタを取得します。
367     void* GetAnimTargetObject(const anim::ResAnimGroupMember& anim, const ResMaterial resMaterial);
368 
369     // アニメーションのオブジェクトタイプに対応するバッファーが存在するかどうかを取得します。
370     bool CanUseBuffer(u32 objectType) const;
371 
372     typedef ut::MoveArray<ResMaterial> ResMaterialArray;
373 
374     ResMaterialArray m_Buffers;
375     Model* m_Owner;
376     ResShaderProgramDescription m_ProgramDescription;
377     s32 m_BufferCount;
378 
379     ResMaterial m_ShaderParameterResMaterial;
380     ResMaterial m_ShadingParameterResMaterial;
381     ResMaterial m_MaterialColorResMaterial;
382     ResMaterial m_RasterizationResMaterial;
383     ResMaterial m_TextureCoordinatorResMaterial;
384     ResMaterial m_TextureMapperResMaterial;
385     ResMaterial m_FragmentLightingResMaterial;
386     ResMaterial m_FragmentLightingTableResMaterial;
387     ResMaterial m_TextureCombinerResMaterial;
388     ResMaterial m_AlphaTestResMaterial;
389     ResMaterial m_FragmentOperationResMaterial;
390     ResMaterial m_SceneEnvironmentResMaterial;
391 
392     // TODO: CanUseBufferを非公開にするために暫定で対処しています。
393     friend class Model;
394 };
395 
396 //! @brief マテリアルの Array の定義です。
397 typedef ut::MoveArray<Material*> MaterialArray;
398 
399 } // namespace gfx
400 } // namespace nw
401 
402 #endif // NW_GFX_MATERIAL_H_
403