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