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: 27935 $
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(graphicsFile);
142 
143     Result result = RESOURCE_RESULT_OK;
144 
145     if (allocator == NULL) { allocator == CommandCacheManager::GetAllocator(); }
146 
147     ResShape    shape      = owner.GetShapes(this->GetShapeIndex());
148     ResMaterial material   = owner.GetMaterials(this->GetMaterialIndex());
149     ResBinaryShader shader = material.GetShader().Dereference();
150     s32 shaderIndex = material.GetShaderProgramDescriptionIndex();
151 
152     // ResModel::Setup で、シェーダの Setup が完了してから実行するので、
153     // 参照先のシェーダが見つからない場合は ASSERT。
154     NW_ASSERT( shader.IsValid() );
155 
156     ResShaderProgramDescription shaderProgramDesc = shader.GetDescriptions( shaderIndex );
157 
158     switch ( shape.GetTypeInfo() )
159     {
160     case ResSeparateDataShape::TYPE_INFO:
161         {
162             ResSeparateDataShape separateShape = ResStaticCast<ResSeparateDataShape>( shape );
163 
164             s32 activateCommandSize   = internal::CalcSetupActivateVertexAttributeCommandSize(separateShape, shaderProgramDesc);
165             s32 deactivateCommandSize = internal::CalcSetupDeactivateVertexAttributeCommandSize(separateShape, shaderProgramDesc);
166 
167             void* buffer = allocator->Alloc( activateCommandSize + deactivateCommandSize, 4 );
168 
169             internal::CommandBufferInfo bufferInfo(buffer, activateCommandSize + deactivateCommandSize);
170 
171             internal::SetupVertexAttributeCommand(bufferInfo, separateShape, shaderProgramDesc);
172             NW_ASSERT(bufferInfo.GetCurrentSize() == activateCommandSize);
173 
174             internal::SetupDeactivateVertexAttributeCommand(bufferInfo, separateShape, shaderProgramDesc);
175             NW_ASSERT(bufferInfo.GetCurrentSize() == activateCommandSize + deactivateCommandSize);
176 
177             ref().m_ActivateCommandCache = buffer;
178             ref().m_ActivateCommandCacheSize = activateCommandSize;
179 
180             ref().m_DeactivateCommandCache = nw::ut::AddOffsetToPtr( ref().m_ActivateCommandCache, activateCommandSize );
181             ref().m_DeactivateCommandCacheSize = deactivateCommandSize;
182 
183             ref().m_CommandAllocator = allocator;
184 
185             ResSeparateDataShape_SetupVertexIrScale( *this, separateShape, shaderProgramDesc );
186         }
187         break;
188 
189     case ResParticleShape::TYPE_INFO:
190         {
191             //ResParticleShape particleShape = ResStaticCast<ResParticleShape>( shape );
192             //internal::SetupVertexAttributeCommand(particleShape, shaderProgramDesc);
193         }
194         break;
195     }
196 
197     if (result.IsSuccess())
198     {
199         this->EnableFlags(ResMesh::FLAG_HAS_BEEN_SETUP);
200     }
201 
202     return result;
203 }
204 
205 
206 //------------------------------------------------------------------------------
207 void
Cleanup()208 ResMesh::Cleanup()
209 {
210     this->DisableFlags(ResMesh::FLAG_HAS_BEEN_SETUP);
211 
212     if ( ref().m_ActivateCommandCache != NULL )
213     {
214         ref().m_CommandAllocator->Free(ref().m_ActivateCommandCache);
215 
216         ref().m_ActivateCommandCache = NULL;
217         ref().m_ActivateCommandCacheSize = 0;
218 
219         if ( ref().m_DeactivateCommandCache != NULL )
220         {
221             ref().m_DeactivateCommandCache = NULL;
222             ref().m_DeactivateCommandCacheSize = 0;
223         }
224     }
225 
226     // Activate == NULL かつ Deactivate != NULL という事はありえない。
227     NW_ASSERT( ref().m_DeactivateCommandCache == NULL );
228 }
229 
230 } /* namespace res */
231 } /* namespace gfx */
232 } /* namespace nw */
233 
234