1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     anim_ResAnim.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: $
16  *---------------------------------------------------------------------------*/
17 
18 #include "../precompiled.h"
19 
20 #include <nw/anim/res/anim_ResAnim.h>
21 #include <nw/ut/ut_Color.h>
22 #include <nw/gfx/res/gfx_ResUtil.h>
23 #include <nw/gfx/res/gfx_ResGraphicsFile.h>
24 #include <nw/gfx/gfx_CalculatedTransform.h>
25 #include <nw/ut/ut_ResDictionary.h>
26 
27 namespace nw {
28 namespace anim {
29 namespace res {
30 
31 //----------------------------------------------------------
GetPrimitiveSize() const32 int ResMemberAnim::GetPrimitiveSize() const
33 {
34     // ここを変更した場合、
35     // AnimResult::m_ValueBuf のサイズを同時に修正すること
36 
37     switch (GetPrimitiveType())
38     {
39     case ResMemberAnim::PRIMITIVETYPE_FLOAT:
40         return sizeof(float);
41     case ResMemberAnim::PRIMITIVETYPE_INT:
42         return sizeof(int);
43     case ResMemberAnim::PRIMITIVETYPE_BOOL:
44         return sizeof(bool);
45     case ResMemberAnim::PRIMITIVETYPE_VECTOR2:
46         return sizeof(math::VEC2);
47     case ResMemberAnim::PRIMITIVETYPE_VECTOR3:
48         return sizeof(math::VEC3);
49     case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
50         return sizeof(gfx::CalculatedTransform);
51     case ResMemberAnim::PRIMITIVETYPE_RGBA_COLOR:
52         return sizeof(ut::ResFloatColor);
53     case ResMemberAnim::PRIMITIVETYPE_TEXTURE:
54         return sizeof(ut::Offset);
55     default:
56         NW_ASSERT(false);
57     }
58     return 0;
59 }
60 
61 //----------------------------------------------------------
62 bit32
EvaluateResult(void * dstBuf,bit32 dstFlags,float frame) const63 ResVec2Anim::EvaluateResult(
64     void* dstBuf,
65     bit32 dstFlags,
66     float frame)
67 const
68 {
69     math::VEC2* dst = reinterpret_cast<math::VEC2*>(dstBuf);
70     const bit32 animFlags = GetFlags();
71     if (!(animFlags & ResVec2AnimData::FLAG_X_NOT_EXIST))
72     {
73         dst->x = EvaluateCurveX(frame);
74         dstFlags |= AnimResult::FLAG_VALID_COMPONENT0;
75     }
76     if (!(animFlags & ResVec2AnimData::FLAG_Y_NOT_EXIST))
77     {
78         dst->y = EvaluateCurveY(frame);
79         dstFlags |= AnimResult::FLAG_VALID_COMPONENT1;
80     }
81     return dstFlags;
82 }
83 
84 //----------------------------------------------------------
85 void
ApplyCache(void * target,const void * cacheBuf) const86 ResVec2Anim::ApplyCache(
87     void* target,
88     const void* cacheBuf
89 ) const
90 {
91     math::VEC2* dst = reinterpret_cast<math::VEC2*>(target);
92     const math::VEC2* src = reinterpret_cast<const math::VEC2*>(cacheBuf);
93     const bit32 animFlags = GetFlags();
94     if (!(animFlags & ResVec2AnimData::FLAG_X_NOT_EXIST))
95     {
96         dst->x = src->x;
97     }
98     if (!(animFlags & ResVec2AnimData::FLAG_Y_NOT_EXIST))
99     {
100         dst->y = src->y;
101     }
102 }
103 
104 //----------------------------------------------------------
105 bit32
EvaluateResult(void * dstBuf,bit32 dstFlags,float frame) const106 ResVec3Anim::EvaluateResult(
107     void* dstBuf,
108     bit32 dstFlags,
109     float frame
110 ) const
111 {
112     math::VEC3* dst = reinterpret_cast<math::VEC3*>(dstBuf);
113     const bit32 animFlags = GetFlags();
114     if (!(animFlags & ResVec3AnimData::FLAG_X_NOT_EXIST))
115     {
116         dst->x = EvaluateCurveX(frame);
117         dstFlags |= AnimResult::FLAG_VALID_COMPONENT0;
118     }
119     if (!(animFlags & ResVec3AnimData::FLAG_Y_NOT_EXIST))
120     {
121         dst->y = EvaluateCurveY(frame);
122         dstFlags |= AnimResult::FLAG_VALID_COMPONENT1;
123     }
124     if (!(animFlags & ResVec3AnimData::FLAG_Z_NOT_EXIST))
125     {
126         dst->z = EvaluateCurveZ(frame);
127         dstFlags |= AnimResult::FLAG_VALID_COMPONENT2;
128     }
129     return dstFlags;
130 }
131 
132 //----------------------------------------------------------
133 void
ApplyCache(void * target,const void * cacheBuf) const134 ResVec3Anim::ApplyCache(
135     void* target,
136     const void* cacheBuf
137 ) const
138 {
139     math::VEC3* dst = reinterpret_cast<math::VEC3*>(target);
140     const math::VEC3* src = reinterpret_cast<const math::VEC3*>(cacheBuf);
141     const bit32 animFlags = GetFlags();
142     if (!(animFlags & ResVec3AnimData::FLAG_X_NOT_EXIST))
143     {
144         dst->x = src->x;
145     }
146     if (!(animFlags & ResVec3AnimData::FLAG_Y_NOT_EXIST))
147     {
148         dst->y = src->y;
149     }
150     if (!(animFlags & ResVec3AnimData::FLAG_Z_NOT_EXIST))
151     {
152         dst->z = src->z;
153     }
154 }
155 
156 //----------------------------------------------------------
157 bit32
EvaluateResult(void * dstBuf,bit32 dstFlags,float frame) const158 ResRgbaColorAnim::EvaluateResult(
159     void* dstBuf,
160     bit32 dstFlags,
161     float frame
162 ) const
163 {
164     ut::ResFloatColor* dst = reinterpret_cast<ut::ResFloatColor*>(dstBuf);
165     const bit32 animFlags = GetFlags();
166     if (!(animFlags & ResRgbaColorAnimData::FLAG_R_NOT_EXIST))
167     {
168         dst->r = EvaluateCurveR(frame);
169         dstFlags |= AnimResult::FLAG_VALID_COMPONENT0;
170     }
171     if (!(animFlags & ResRgbaColorAnimData::FLAG_G_NOT_EXIST))
172     {
173         dst->g = EvaluateCurveG(frame);
174         dstFlags |= AnimResult::FLAG_VALID_COMPONENT1;
175     }
176     if (!(animFlags & ResRgbaColorAnimData::FLAG_B_NOT_EXIST))
177     {
178         dst->b = EvaluateCurveB(frame);
179         dstFlags |= AnimResult::FLAG_VALID_COMPONENT2;
180     }
181     if (!(animFlags & ResRgbaColorAnimData::FLAG_A_NOT_EXIST))
182     {
183         dst->a = EvaluateCurveA(frame);
184         dstFlags |= AnimResult::FLAG_VALID_COMPONENT3;
185     }
186     return dstFlags;
187 }
188 
189 //----------------------------------------------------------
190 void
ApplyCache(void * target,const void * cacheBuf) const191 ResRgbaColorAnim::ApplyCache(
192     void* target,
193     const void* cacheBuf
194 ) const
195 {
196     ut::ResFloatColor* dst = reinterpret_cast<ut::ResFloatColor*>(target);
197     const ut::ResFloatColor* src = reinterpret_cast<const ut::ResFloatColor*>(cacheBuf);
198     const bit32 animFlags = GetFlags();
199     if (!(animFlags & ResRgbaColorAnimData::FLAG_R_NOT_EXIST))
200     {
201         dst->r = src->r;
202     }
203     if (!(animFlags & ResRgbaColorAnimData::FLAG_G_NOT_EXIST))
204     {
205         dst->g = src->g;
206     }
207     if (!(animFlags & ResRgbaColorAnimData::FLAG_B_NOT_EXIST))
208     {
209         dst->b = src->b;
210     }
211     if (!(animFlags & ResRgbaColorAnimData::FLAG_A_NOT_EXIST))
212     {
213         dst->a = src->a;
214     }
215 }
216 
217 //----------------------------------------------------------
218 gfx::Result
Setup(os::IAllocator * allocator,gfx::ResGraphicsFile graphicsFile)219 ResTextureAnim::Setup(os::IAllocator* allocator, gfx::ResGraphicsFile graphicsFile)
220 {
221     NW_UNUSED_VARIABLE(allocator);
222 
223     gfx::Result result = gfx::RESOURCE_RESULT_OK;
224 
225     for (int i = 0; i < GetTexturesCount(); ++i)
226     {
227         if (!GetTextures(i).GetTargetTexture().IsValid())
228         {
229             ::std::pair<gfx::ResTexture, bool> target = gfx::GetReferenceTextureTarget(GetTextures(i), graphicsFile);
230 
231             if (!target.second)
232             {
233                 result |= gfx::Result::MASK_FAIL_BIT;
234                 result |= gfx::RESOURCE_RESULT_NOT_FOUND_TEXTURE;
235             }
236         }
237     }
238 
239     return result;
240 }
241 
242 //----------------------------------------------------------
243 void
Cleanup()244 ResTextureAnim::Cleanup()
245 {
246 }
247 
248 //----------------------------------------------------------
249 bit32
EvaluateResult(void * dstBuf,bit32 dstFlags,float frame) const250 ResTextureAnim::EvaluateResult(
251     void* dstBuf,
252     bit32 dstFlags,
253     float frame
254 ) const
255 {
256     ut::Offset* dst = reinterpret_cast<ut::Offset*>(dstBuf);
257     s32 textureIndex = (s32)EvaluateCurve(frame);
258 
259     if (0 <= textureIndex && textureIndex < GetTexturesCount())
260     {
261         dst->set_ptr(GetTextures(textureIndex).ptr());
262         dstFlags |= AnimResult::FLAG_VALID_COMPONENT0;
263     }
264 
265     return dstFlags;
266 }
267 
268 //----------------------------------------------------------
269 void
ApplyCache(void * target,const void * cacheBuf) const270 ResTextureAnim::ApplyCache(
271     void* target,
272     const void* cacheBuf
273 ) const
274 {
275     ut::Offset* dst = reinterpret_cast<ut::Offset*>(target);
276     const ut::Offset* src = reinterpret_cast<const ut::Offset*>(cacheBuf);
277 
278     dst->set_ptr(src->to_ptr());
279 }
280 
281 //----------------------------------------------------------
EvaluateResult(void * dstBuf,bit32 dstFlags,float frame,const void * originalValue) const282 bit32 ResTransformAnim::EvaluateResult(
283     void* dstBuf,
284     bit32 dstFlags,
285     float frame,
286     const void* originalValue
287 ) const
288 {
289     const math::Transform3& originalTransform =
290         *static_cast<const math::Transform3*>(originalValue);
291 
292     const u32 flags = GetFlags();
293     math::Transform3 transform;
294 
295     // TODO: Rotateアニメがない場合は回転行列計算を省略できるかも
296     // 初期化時にOriginalValueで回転行列が生成されているか確認が必要
297     transform.scale.x = (flags & ResTransformAnimData::FLAG_SCALE_X_NOT_EXIST) ?
298         originalTransform.scale.x : EvaluateScaleX(frame);
299     transform.scale.y = (flags & ResTransformAnimData::FLAG_SCALE_Y_NOT_EXIST) ?
300         originalTransform.scale.y : EvaluateScaleY(frame);
301     transform.scale.z = (flags & ResTransformAnimData::FLAG_SCALE_Z_NOT_EXIST) ?
302         originalTransform.scale.z : EvaluateScaleZ(frame);
303 
304     transform.rotate.x = (flags & ResTransformAnimData::FLAG_ROTATE_X_NOT_EXIST) ?
305         originalTransform.rotate.x : EvaluateRotateX(frame);
306     transform.rotate.y = (flags & ResTransformAnimData::FLAG_ROTATE_Y_NOT_EXIST) ?
307         originalTransform.rotate.y : EvaluateRotateY(frame);
308     transform.rotate.z = (flags & ResTransformAnimData::FLAG_ROTATE_Z_NOT_EXIST) ?
309         originalTransform.rotate.z : EvaluateRotateZ(frame);
310 
311     transform.translate.x = (flags & ResTransformAnimData::FLAG_TRANSLATE_X_NOT_EXIST) ?
312         originalTransform.translate.x : EvaluateTranslateX(frame);
313     transform.translate.y = (flags & ResTransformAnimData::FLAG_TRANSLATE_Y_NOT_EXIST) ?
314         originalTransform.translate.y : EvaluateTranslateY(frame);
315     transform.translate.z = (flags & ResTransformAnimData::FLAG_TRANSLATE_Z_NOT_EXIST) ?
316         originalTransform.translate.z : EvaluateTranslateZ(frame);
317 
318     gfx::CalculatedTransform* dst = new (dstBuf) gfx::CalculatedTransform();
319     dst->SetTransform(transform);
320     dst->UpdateScaleFlags();
321     dst->UpdateRotateFlags();
322     dst->UpdateTranslateFlags();
323     dst->UpdateCompositeFlags();
324 
325     // TransformAnimでは、FLAG_VALID_COMPONENT*は使用しない
326     return dstFlags;
327 }
328 
329 //----------------------------------------------------------
ApplyCache(void * target,const void * cacheBuf) const330 void ResTransformAnim::ApplyCache(
331     void* target,
332     const void* cacheBuf
333 ) const
334 {
335     gfx::CalculatedTransform* dst = reinterpret_cast<gfx::CalculatedTransform*>(target);
336     const gfx::CalculatedTransform* src = reinterpret_cast<const gfx::CalculatedTransform*>(cacheBuf);
337 
338     *dst = *src;
339 }
340 
341 //----------------------------------------------------------
342 void
ApplyBakedFlags(gfx::CalculatedTransform * transform,const bit32 flags)343 ResBakedTransformAnim::ApplyBakedFlags(gfx::CalculatedTransform* transform, const bit32 flags)
344 {
345     static const bit32 CLEAR_FLAGS = (0 |
346         gfx::CalculatedTransform::FLAG_IS_IDENTITY |
347         gfx::CalculatedTransform::FLAG_IS_ROTATE_TRANSLATE_ZERO |
348         gfx::CalculatedTransform::FLAG_IS_ROTATE_ZERO |
349         gfx::CalculatedTransform::FLAG_IS_TRANSLATE_ZERO |
350         gfx::CalculatedTransform::FLAG_IS_SCALE_ONE |
351         gfx::CalculatedTransform::FLAG_IS_UNIFORM_SCALE
352     );
353 
354     static const bit32 CLEAR_COMPOSITE_FLAGS = (0 |
355         gfx::CalculatedTransform::FLAG_IS_IDENTITY |
356         gfx::CalculatedTransform::FLAG_IS_ROTATE_TRANSLATE_ZERO
357         );
358 
359     bit32 originalFlags = transform->GetFlags() & ~CLEAR_FLAGS;
360 
361     bit32 f = flags & ~CLEAR_COMPOSITE_FLAGS;
362 
363     if (ut::CheckFlag(flags,
364             gfx::CalculatedTransform::FLAG_IS_ROTATE_ZERO | gfx::CalculatedTransform::FLAG_IS_TRANSLATE_ZERO))
365     {
366         f |= gfx::CalculatedTransform::FLAG_IS_ROTATE_TRANSLATE_ZERO;
367     }
368 
369     if (ut::CheckFlag(flags,
370             gfx::CalculatedTransform::FLAG_IS_ROTATE_TRANSLATE_ZERO | gfx::CalculatedTransform::FLAG_IS_SCALE_ONE))
371     {
372         f |= gfx::CalculatedTransform::FLAG_IS_IDENTITY;
373     }
374 
375     transform->SetFlags(originalFlags | f);
376 }
377 
378 //----------------------------------------------------------
379 gfx::Result
Setup(os::IAllocator * allocator,gfx::ResGraphicsFile graphicsFile)380 ResMemberAnim::Setup(os::IAllocator* allocator, gfx::ResGraphicsFile graphicsFile)
381 {
382     switch ( GetPrimitiveType() )
383     {
384     case ResMemberAnim::PRIMITIVETYPE_TEXTURE:
385         return static_cast<ResTextureAnim&>(*this).Setup(allocator, graphicsFile);
386     }
387 
388     return gfx::RESOURCE_RESULT_OK;
389 }
390 
391 //----------------------------------------------------------
392 void
Cleanup()393 ResMemberAnim::Cleanup()
394 {
395     switch ( GetPrimitiveType() )
396     {
397     case ResMemberAnim::PRIMITIVETYPE_TEXTURE:
398         static_cast<ResTextureAnim&>(*this).Cleanup();
399         break;
400     }
401 }
402 
403 //----------------------------------------------------------
404 bit32
EvaluateResultForType(void * dstBuf,bit32 dstFlags,float frame,const void * originalValue) const405 ResMemberAnim::EvaluateResultForType(
406     void* dstBuf,
407     bit32 dstFlags,
408     float frame,
409     const void* originalValue
410 ) const
411 {
412     const int primType = GetPrimitiveType();
413     switch (primType)
414     {
415     case ResMemberAnim::PRIMITIVETYPE_FLOAT:
416         dstFlags = static_cast<const ResFloatAnim&>(*this)
417             .EvaluateResult(dstBuf, dstFlags, frame);
418         break;
419     case ResMemberAnim::PRIMITIVETYPE_INT:
420         dstFlags = static_cast<const ResIntAnim&>(*this)
421             .EvaluateResult(dstBuf, dstFlags, frame);
422         break;
423     case ResMemberAnim::PRIMITIVETYPE_BOOL:
424         dstFlags = static_cast<const ResBoolAnim&>(*this)
425             .EvaluateResult(dstBuf, dstFlags, frame);
426         break;
427     case ResMemberAnim::PRIMITIVETYPE_VECTOR2:
428         dstFlags = static_cast<const ResVec2Anim&>(*this)
429             .EvaluateResult(dstBuf, dstFlags, frame);
430         break;
431     case ResMemberAnim::PRIMITIVETYPE_VECTOR3:
432         dstFlags = static_cast<const ResVec3Anim&>(*this)
433             .EvaluateResult(dstBuf, dstFlags, frame);
434         break;
435     case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
436         // この型のみOriginalValueが必要
437         dstFlags = static_cast<const ResTransformAnim&>(*this)
438             .EvaluateResult(dstBuf, dstFlags, frame, originalValue);
439         break;
440     case ResMemberAnim::PRIMITIVETYPE_RGBA_COLOR:
441         dstFlags = static_cast<const ResRgbaColorAnim&>(*this)
442             .EvaluateResult(dstBuf, dstFlags, frame);
443         break;
444     case ResMemberAnim::PRIMITIVETYPE_TEXTURE:
445         dstFlags = static_cast<const ResTextureAnim&>(*this)
446             .EvaluateResult(dstBuf, dstFlags, frame);
447         break;
448     default:
449         NW_ASSERT(false);
450         break;
451     }
452     return dstFlags;
453 }
454 
455 //----------------------------------------------------------
456 void
ApplyCacheForType(void * target,const void * cacheBuf) const457 ResMemberAnim::ApplyCacheForType(
458     void* target,
459     const void* cacheBuf
460 ) const
461 {
462     const int primType = GetPrimitiveType();
463     switch (primType)
464     {
465     case ResMemberAnim::PRIMITIVETYPE_FLOAT:
466         static_cast<const ResFloatAnim&>(*this).ApplyCache(target, cacheBuf);
467         break;
468     case ResMemberAnim::PRIMITIVETYPE_INT:
469         static_cast<const ResIntAnim&>(*this).ApplyCache(target, cacheBuf);
470         break;
471     case ResMemberAnim::PRIMITIVETYPE_BOOL:
472         static_cast<const ResBoolAnim&>(*this).ApplyCache(target, cacheBuf);
473         break;
474     case ResMemberAnim::PRIMITIVETYPE_VECTOR2:
475         static_cast<const ResVec2Anim&>(*this).ApplyCache(target, cacheBuf);
476         break;
477     case ResMemberAnim::PRIMITIVETYPE_VECTOR3:
478         static_cast<const ResVec3Anim&>(*this).ApplyCache(target, cacheBuf);
479         break;
480     case ResMemberAnim::PRIMITIVETYPE_TRANSFORM:
481         static_cast<const ResTransformAnim&>(*this).ApplyCache(target, cacheBuf);
482         break;
483     case ResMemberAnim::PRIMITIVETYPE_RGBA_COLOR:
484         static_cast<const ResRgbaColorAnim&>(*this).ApplyCache(target, cacheBuf);
485         break;
486     case ResMemberAnim::PRIMITIVETYPE_TEXTURE:
487         static_cast<const ResTextureAnim&>(*this).ApplyCache(target, cacheBuf);
488         break;
489     default:
490         NW_ASSERT(false);
491         break;
492     }
493 }
494 
495 //----------------------------------------------------------
496 gfx::Result
Setup(os::IAllocator * allocator,gfx::ResGraphicsFile graphicsFile)497 ResAnim::Setup(os::IAllocator* allocator, gfx::ResGraphicsFile graphicsFile)
498 {
499     gfx::Result result = gfx::RESOURCE_RESULT_OK;
500 
501     for(int i=0; i<GetMemberAnimSetCount(); i++)
502     {
503         ResMemberAnim member = GetMemberAnimSet(i);
504         result |= member.Setup(allocator, graphicsFile);
505     }
506 
507     return result;
508 }
509 
510 //----------------------------------------------------------
511 void
Cleanup()512 ResAnim::Cleanup()
513 {
514     for(int i=0; i<GetMemberAnimSetCount(); i++)
515     {
516         ResMemberAnim member = GetMemberAnimSet(i);
517         member.Cleanup();
518     }
519 }
520 
521 //----------------------------------------------------------
522 ResAnim
CreateEmptyResAnim(nw::os::IAllocator * allocator,const char * targetAnimGroupName)523 ResAnim::CreateEmptyResAnim(
524     nw::os::IAllocator* allocator,
525     const char* targetAnimGroupName
526 )
527 {
528     size_t size = sizeof(ResAnimData);
529     size += sizeof(ut::ResDicPatriciaData);
530 
531     u8* memory = reinterpret_cast<u8*>( allocator->Alloc(size) );
532 
533     ResAnimData* data = reinterpret_cast<ResAnimData*>(memory);
534     memory += sizeof(ResAnimData);
535     ut::ResDicPatriciaData* dicData = reinterpret_cast<ut::ResDicPatriciaData*>(memory);
536 
537     data->m_Header.revision = ResAnim::BINARY_REVISION;
538     data->m_Header.signature = ResAnim::SIGNATURE;
539     data->toName.set_ptr("");
540     data->toTargetAnimGroupName.set_ptr(targetAnimGroupName);
541     data->m_LoopMode = ResAnimData::LOOP_MODE_ONETIME;
542     data->m_FrameSize = 1;
543     data->m_MemberAnimSetDicCount = 0;
544     data->toMemberAnimSetDic.set_ptr(dicData);
545     data->m_UserDataDicCount = 0;
546     data->toUserDataDic.set_ptr(dicData);
547 
548     ut::internal::InitializeResDicPatricia(dicData);
549 
550     return ResAnim(data);
551 }
552 
553 //----------------------------------------------------------
554 bool
IsFullBakedAnim() const555 ResAnim::IsFullBakedAnim() const
556 {
557     if (GetMemberAnimSetCount() == 0)
558     {
559         return false;
560     }
561 
562     // PrimitiveTypeが混在することはないので、1つ目だけ判定すればよい
563     return GetMemberAnimSet(0).GetPrimitiveType() == ResMemberAnim::PRIMITIVETYPE_FULL_BAKED;
564 }
565 
566 } // namespace res
567 } // namespace anim
568 } // namespace nw
569