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