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