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