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