1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ParticleAnimationOption.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: 25048 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <nw/gfx/res/gfx_ResParticleAnimationOption.h>
19 
20 #include <nw/ut/ut_ResUtil.h>
21 #include <nw/ut/ut_ResDictionary.h>
22 #include <nw/gfx/gfx_ParticleTime.h>
23 
24 namespace nw
25 {
26 namespace gfx
27 {
28 
29 u32
GetHash(u32 key1,u32 key2,u32 key3,u32 key4)30 ResParticleAnimationOption::GetHash(
31     u32 key1,
32     u32 key2,
33     u32 key3,
34     u32 key4
35 )
36 {
37     union
38     {
39         u32 i;
40         u8 b[4];
41     } u;
42 
43     u.i = (key1 * 0x3f81f635u)
44         + (key2 * 0x30a74193u)
45         + (key3 * 0x371097e7u)
46         + (key4 * 0x7b929u)
47         + 0x4bf53u;
48 
49     u.b[2] ^= u.b[3];
50     u.b[1] ^= u.b[2];
51     u.b[0] ^= u.b[1];
52 
53     return u.i;
54 }
55 
56 ParticleTime
EvaluateAnimationFrame(u32 id,ParticleTime birth,ParticleTime life,ParticleTime time,int updaterIndex) const57 ResParticleAnimationOption::EvaluateAnimationFrame(
58     u32 id,
59     ParticleTime birth,
60     ParticleTime life,
61     ParticleTime time,
62     int updaterIndex
63 ) const
64 {
65     if (!this->IsValid())
66     {
67         if (time < birth)
68         {
69             return 0;
70         }
71 
72         if (life <= 0)
73         {
74             return 0;
75         }
76 
77         return time - birth;
78     }
79 
80     switch (this->GetTypeInfo())
81     {
82     case ResParticleFittingAnimationOption::TYPE_INFO:
83         {
84             if (time < birth)
85             {
86                 return 0;
87             }
88 
89             if (life <= 0)
90             {
91                 return 0;
92             }
93 
94 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
95             return (time - birth) / life * this->GetAnimationDuration();
96 #else
97             ParticleTime time_birth = time - birth;
98             return time_birth.Interp(life, (int)this->GetAnimationDuration());
99 #endif
100         }
101 
102     case ResParticleFrameLoopAnimationOption::TYPE_INFO:
103         {
104             const ResParticleFrameLoopAnimationOption resource =
105                 ResDynamicCast<ResParticleFrameLoopAnimationOption>(*this);
106 
107             if (time < birth)
108             {
109                 return 0;
110             }
111 
112             if (resource.GetAnimationDuration() == 0 || resource.GetLoopDuration() == 0)
113             {
114                 return 0;
115             }
116 
117             ParticleTime delta = time - birth;
118 
119             if (resource.GetRandomOffset())
120             {
121                 u32 random = GetHash(
122                     id,
123 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
124                     (u32)birth,
125 #else
126                     birth.GetS32Value(),
127 #endif
128                     updaterIndex,
129                     0x1234);
130 
131 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
132                 delta += (f32)(random % resource.GetLoopDuration());
133 #else
134                 delta += (s32)(random % resource.GetLoopDuration());
135 #endif
136             }
137 
138 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
139             delta = nw::math::FMod(delta, (f32)resource.GetLoopDuration());
140             delta /= resource.GetLoopDuration();
141 
142             return delta * resource.GetAnimationDuration();
143 #else
144             delta.FMod((int)resource.GetLoopDuration());
145             delta.Interp(ParticleTime((int)resource.GetLoopDuration()), resource.GetAnimationDuration());
146 
147             return delta;
148 #endif
149         }
150 
151     case ResParticleRandomAnimationOption::TYPE_INFO:
152         {
153             if (this->GetAnimationDuration() == 0)
154             {
155                 return 0;
156             }
157 
158             u32 random = GetHash(
159                 id,
160 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
161                 (u32)birth,
162 #else
163                 birth.GetS32Value(),
164 #endif
165                 updaterIndex,
166                 0x4321);
167 
168             int offset = (int)(random % (int)(this->GetAnimationDuration() + 1));
169 
170 #ifdef NW_GFX_PARTICLE_COMPAT_1_1
171             return (f32)offset;
172 #else
173             return offset;
174 #endif
175         }
176     }
177 
178     return 0;
179 }
180 
181 } // namespace gfx
182 } // namespace nw
183