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