1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ResMesh.cpp
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: 25269 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "../precompiled.h"
17 
18 #include <nw/gfx/res/gfx_ResMesh.h>
19 #include <nn/gx.h>
20 
21 namespace nw {
22 namespace gfx {
23 namespace res {
24 
25 namespace {
26 
27     enum { BONE_INDEX_SCALE_INDEX = -2 };
28 
29     //---------------------------------------------------------------------------
30     //! @brief        頂点属性のスケール値を表す値のコマンド中でのインデックスを取得します。
31     //!
32     //! @param[in]    usage   設定する頂点属性の Usage 値です。
33     //!
34     //! @return       m_IrScaleCommand 中の値のインデックスです。
35     //---------------------------------------------------------------------------
36     s32
QueryScaleCommandIndex(ResVertexAttribute::VertexAttributeUsage usage)37     QueryScaleCommandIndex(ResVertexAttribute::VertexAttributeUsage usage)
38     {
39         enum { BASE_INDEX = 2 };
40 
41         switch (usage)
42         {
43         case ResVertexAttribute::USAGE_POSITION:            return BASE_INDEX + 4; // attributeScales[0].x
44         case ResVertexAttribute::USAGE_NORMAL:              return BASE_INDEX + 3; // attributeScales[0].y
45         case ResVertexAttribute::USAGE_TANGENT:             return BASE_INDEX + 2; // attributeScales[0].z
46         case ResVertexAttribute::USAGE_COLOR:               return BASE_INDEX + 0; // attributeScales[0].w
47         case ResVertexAttribute::USAGE_TEXTURECOODINATE0:   return BASE_INDEX + 8; // attributeScales[1].x
48         case ResVertexAttribute::USAGE_TEXTURECOODINATE1:   return BASE_INDEX + 7; // attributeScales[1].y
49         case ResVertexAttribute::USAGE_TEXTURECOODINATE2:   return BASE_INDEX + 6; // attributeScales[1].z
50         case ResVertexAttribute::USAGE_BONEWEIGHT:          return BASE_INDEX + 5; // attributeScales[1].w
51         case ResVertexAttribute::USAGE_BONEINDEX:           return BONE_INDEX_SCALE_INDEX;  // attributeScales[2].x
52         case ResVertexAttribute::USAGE_USERATTRIBUTE0: // don't break;
53         case ResVertexAttribute::USAGE_USERATTRIBUTE1: // don't break;
54         case ResVertexAttribute::USAGE_USERATTRIBUTE2: // don't break;
55         default: break;
56         }
57 
58         return -1;
59     }
60 
61     //---------------------------------------------------------------------------
62     //! @brief        セパレートデータシェイプのIrScale
63     //!
64     //! @param[in]    shape
65     //! @param[in]    shaderProgramDesc
66     //---------------------------------------------------------------------------
67     void
ResSeparateDataShape_SetupVertexIrScale(ResMesh mesh,ResSeparateDataShape shape,ResShaderProgramDescription shaderProgramDesc)68     ResSeparateDataShape_SetupVertexIrScale( ResMesh mesh, ResSeparateDataShape shape, ResShaderProgramDescription shaderProgramDesc )
69     {
70         enum { ATTRIBUTE_SCALES_VECTOR_COUNT = 3 };
71 
72         u32* command = &mesh.ref().m_IrScaleCommand[0];
73 
74         mesh.ref().m_Flags &= ~(ResMesh::FLAG_HAS_VERTEX_ALPHA | ResMesh::FLAG_HAS_BONE_WEIGHT_W);
75         std::memset(command, 0, sizeof(mesh.ref().m_IrScaleCommand));
76 
77         command[0] = VERTEX_SHADER_UNIFORM_IRSCALE_INDEX | 0x80000000;
78         command[1] = internal::MakeCommandHeader(PICA_REG_VS_FLOAT_ADDR, 1, false, 0xF);
79         command[3] = internal::MakeCommandHeader(PICA_REG_VS_FLOAT0, 2 * 4, false, 0xF);
80 
81         internal::ResVertexAttributeIterator iter = internal::ResVertexAttributeIterator::Begin( shape );
82 
83         ResVertexAttributeArray::iterator end = shape.GetVertexAttributes().end();
84         for ( ; iter.IsValid(); ++iter)
85         {
86             ResVertexAttribute attribute = *iter;
87 
88             int index = shaderProgramDesc.GetAttributeIndices(attribute.GetUsage());
89 
90             // シェーダーに存在しない属性の場合は何もせずに終了する。
91             if (index < 0)
92             {
93                 continue;
94             }
95 
96             u8 dimension = 0;
97             ResVertexAttribute::VertexAttributeUsage usage = ResVertexAttribute::USAGE_NONE;
98 
99             if (attribute.GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM)
100             {
101                 ResVertexParamAttribute constantVertexAttribute(attribute.ptr());
102 
103                 dimension = constantVertexAttribute.GetDimension();
104 
105                 usage = static_cast<ResVertexAttribute::VertexAttributeUsage>(constantVertexAttribute.GetUsage());
106                 s32 commandIndex = QueryScaleCommandIndex( usage );
107                 if ( commandIndex >= 0 ) { command[ commandIndex ] = ut::Float32::Float32ToBits32(1.0f); }
108             }
109             else
110             {
111                 ResVertexStream vertexStream(attribute.ptr());
112 
113                 dimension = vertexStream.GetDimension();
114 
115                 usage = static_cast<ResVertexAttribute::VertexAttributeUsage>(vertexStream.GetUsage());
116                 f32 scale = vertexStream.GetScale();
117                 s32 commandIndex = QueryScaleCommandIndex( usage );
118                 if ( commandIndex >= 0 ) { command[ commandIndex ] = ut::Float32::Float32ToBits32(scale); }
119                 NW_ASSERT( ! ( (commandIndex == BONE_INDEX_SCALE_INDEX) && (scale != 1.0f)) );
120             }
121 
122             if (dimension == 4)
123             {
124                 if (usage == ResVertexAttribute::USAGE_COLOR)
125                 {
126                     mesh.ref().m_Flags |= ResMesh::FLAG_HAS_VERTEX_ALPHA;
127                 }
128                 else if (usage == ResVertexAttribute::USAGE_BONEWEIGHT)
129                 {
130                     mesh.ref().m_Flags |= ResMesh::FLAG_HAS_BONE_WEIGHT_W;
131                 }
132             }
133         }
134     }
135 }
136 
137 //----------------------------------------
138 Result
Setup(ResModel owner,os::IAllocator * allocator,ResGraphicsFile graphicsFile)139 ResMesh::Setup(ResModel owner, os::IAllocator* allocator, ResGraphicsFile graphicsFile)
140 {
141     NW_UNUSED_VARIABLE(allocator);
142     NW_UNUSED_VARIABLE(graphicsFile);
143 
144     Result result = RESOURCE_RESULT_OK;
145 
146     if ( ref().m_ActivateCommandCache != NULL )
147     {
148         return result;
149     }
150 
151     ResShape    shape      = owner.GetShapes(this->GetShapeIndex());
152     ResMaterial material   = owner.GetMaterials(this->GetMaterialIndex());
153     ResBinaryShader shader = material.GetShader().Dereference();
154     s32 shaderIndex = material.GetShaderProgramDescriptionIndex();
155 
156     // ResModel::Setup で、シェーダの Setup が完了してから実行するので、
157     // 参照先のシェーダが見つからない場合は ASSERT。
158     NW_ASSERT( shader.IsValid() );
159 
160     ResShaderProgramDescription shaderProgramDesc = shader.GetDescriptions( shaderIndex );
161 
162     switch ( shape.GetTypeInfo() )
163     {
164     case ResSeparateDataShape::TYPE_INFO:
165         {
166             ResSeparateDataShape separateShape = ResStaticCast<ResSeparateDataShape>( shape );
167 
168             internal::CommandCacheBuilder builder;
169             internal::CommandCacheBuilder subBuilder;
170             s32 activateCommandSize;
171             s32 deactivateCommandSize;
172 
173             builder.Begin();
174             {
175                 subBuilder.Begin();
176                 internal::SetupVertexAttributeCommand(separateShape, shaderProgramDesc);
177                 subBuilder.End();
178                 activateCommandSize = subBuilder.GetSize();
179 
180                 subBuilder.Begin();
181                 internal::SetupDeactivateVertexAttributeCommand(separateShape, shaderProgramDesc);
182                 subBuilder.End();
183                 deactivateCommandSize = subBuilder.GetSize();
184             }
185             builder.End();
186 
187             ref().m_ActivateCommandCache = builder.AllocAndCopy();
188             ref().m_ActivateCommandCacheSize = activateCommandSize;
189 
190             ref().m_DeactivateCommandCache = nw::ut::AddOffsetToPtr( ref().m_ActivateCommandCache, activateCommandSize );
191             ref().m_DeactivateCommandCacheSize = deactivateCommandSize;
192 
193             builder.Rollback();
194 
195             ResSeparateDataShape_SetupVertexIrScale( *this, separateShape, shaderProgramDesc );
196         }
197         break;
198 
199     case ResParticleShape::TYPE_INFO:
200         {
201             //ResParticleShape particleShape = ResStaticCast<ResParticleShape>( shape );
202             //internal::SetupVertexAttributeCommand(particleShape, shaderProgramDesc);
203         }
204         break;
205     }
206 
207     return result;
208 }
209 
210 
211 //------------------------------------------------------------------------------
212 void
Cleanup()213 ResMesh::Cleanup()
214 {
215     NW_ASSERT( this->IsValid() );
216 
217     if ( ref().m_ActivateCommandCache != NULL )
218     {
219         CommandCacheManager::Free(ref().m_ActivateCommandCache);
220 
221         ref().m_ActivateCommandCache = NULL;
222         ref().m_ActivateCommandCacheSize = 0;
223 
224         if ( ref().m_DeactivateCommandCache != NULL )
225         {
226             ref().m_DeactivateCommandCache = NULL;
227             ref().m_DeactivateCommandCacheSize = 0;
228         }
229     }
230 
231     // Activate == NULL かつ Deactivate != NULL という事はありえない。
232     NW_ASSERT( ref().m_DeactivateCommandCache == NULL );
233 }
234 
235 } /* namespace res */
236 } /* namespace gfx */
237 } /* namespace nw */
238 
239