1 #include "3dc.h"
2 #include "inline.h"
3
4 /*
5 externs for commonly used global variables and arrays
6 */
7
8 extern MORPHDISPLAY MorphDisplay;
9 extern int NormalFrameTime;
10
11 /*
12 Global Variables
13 */
14
15 /*
16 Update Morphing Animation Control Block
17 */
18
UpdateMorphing(MORPHCTRL * mcptr)19 void UpdateMorphing(MORPHCTRL *mcptr)
20 {
21 MORPHHEADER *mhdr = mcptr->ObMorphHeader;
22 int UpdateRate;
23
24
25 /*textprint("UpdateMorphing\n");*/
26
27
28 if(mcptr->ObMorphFlags & mph_flag_play) {
29
30 /* How fast? */
31
32 if(mcptr->ObMorphSpeed == ONE_FIXED) {
33
34 UpdateRate = NormalFrameTime;
35
36 }
37
38 else {
39
40 UpdateRate = MUL_FIXED(NormalFrameTime, mcptr->ObMorphSpeed);
41
42 }
43
44
45 /* Update the current frame */
46
47 if(mcptr->ObMorphFlags & mph_flag_reverse) {
48
49 mcptr->ObMorphCurrFrame -= UpdateRate;
50
51 if(mcptr->ObMorphCurrFrame < 0) {
52
53 if(mcptr->ObMorphFlags & mph_flag_noloop) {
54
55 mcptr->ObMorphCurrFrame = 0;
56
57 /* The sequence has finished and we are at the start */
58
59 mcptr->ObMorphFlags |= (mph_flag_finished | mph_flag_start);
60
61 }
62
63 else {
64
65 mcptr->ObMorphCurrFrame += mhdr->mph_maxframes;
66
67 /* The sequence has looped and we are back at the end */
68
69 mcptr->ObMorphFlags |= (mph_flag_looped | mph_flag_end);
70
71 }
72
73 }
74
75 }
76
77 else {
78
79 mcptr->ObMorphCurrFrame += UpdateRate;
80
81 if(mcptr->ObMorphCurrFrame >= mhdr->mph_maxframes) {
82
83 if(mcptr->ObMorphFlags & mph_flag_noloop) {
84
85 /* The sequence has finished and we are at the end */
86
87 mcptr->ObMorphFlags |= (mph_flag_finished | mph_flag_end);
88
89 mcptr->ObMorphCurrFrame = mhdr->mph_maxframes - 1;
90
91 }
92
93 else {
94
95 mcptr->ObMorphCurrFrame -= mhdr->mph_maxframes;
96
97 /* The sequence has looped and we are back at the start */
98
99 mcptr->ObMorphFlags |= (mph_flag_looped | mph_flag_start);
100
101 }
102
103 }
104
105 }
106
107 }
108
109 }
110
111
112
113 /*
114
115 Update the Morphing Animation for this object
116
117 */
118
UpdateMorphingDptr(DISPLAYBLOCK * dptr)119 void UpdateMorphingDptr(DISPLAYBLOCK *dptr)
120 {
121 SHAPEHEADER *sptr1;
122 SHAPEHEADER *sptr2;
123
124 /* Update object radius and extents */
125
126 GetMorphDisplay(&MorphDisplay, dptr);
127
128 sptr1 = MorphDisplay.md_sptr1;
129 sptr2 = MorphDisplay.md_sptr2;
130
131 #if 0
132 textprint("sptr1->shaperadius = %d\n", sptr1->shaperadius);
133 textprint("sptr2->shaperadius = %d\n", sptr2->shaperadius);
134 #endif
135
136
137 /* Radius */
138
139 if(sptr1->shaperadius == sptr2->shaperadius) {
140
141 dptr->ObRadius = sptr1->shaperadius;
142
143 }
144
145 else {
146
147 dptr->ObRadius = WideMul2NarrowDiv(sptr1->shaperadius,
148 MorphDisplay.md_one_minus_lerp,
149 sptr2->shaperadius,
150 MorphDisplay.md_lerp, ONE_FIXED);
151
152 }
153
154
155 /* X Extent */
156
157 if(sptr1->shapemaxx == sptr2->shapemaxx) {
158
159 dptr->ObMaxX = sptr1->shapemaxx;
160
161 }
162
163 else {
164
165 dptr->ObMaxX = WideMul2NarrowDiv(sptr1->shapemaxx,
166 MorphDisplay.md_one_minus_lerp,
167 sptr2->shapemaxx,
168 MorphDisplay.md_lerp, ONE_FIXED);
169
170 }
171
172 if(sptr1->shapeminx == sptr2->shapeminx) {
173
174 dptr->ObMinX = sptr1->shapeminx;
175
176 }
177
178 else {
179
180 dptr->ObMinX = WideMul2NarrowDiv(sptr1->shapeminx,
181 MorphDisplay.md_one_minus_lerp,
182 sptr2->shapeminx,
183 MorphDisplay.md_lerp, ONE_FIXED);
184
185 }
186
187
188 /* Y Extent */
189
190 if(sptr1->shapemaxy == sptr2->shapemaxy) {
191
192 dptr->ObMaxY = sptr1->shapemaxy;
193
194 }
195
196 else {
197
198 dptr->ObMaxY = WideMul2NarrowDiv(sptr1->shapemaxy,
199 MorphDisplay.md_one_minus_lerp,
200 sptr2->shapemaxy,
201 MorphDisplay.md_lerp, ONE_FIXED);
202
203 }
204
205 if(sptr1->shapeminy == sptr2->shapeminy) {
206
207 dptr->ObMinY = sptr1->shapeminy;
208
209 }
210
211 else {
212
213 dptr->ObMinY = WideMul2NarrowDiv(sptr1->shapeminy,
214 MorphDisplay.md_one_minus_lerp,
215 sptr2->shapeminy,
216 MorphDisplay.md_lerp, ONE_FIXED);
217
218 }
219
220
221 /* Z Extent */
222
223 if(sptr1->shapemaxz == sptr2->shapemaxz) {
224
225 dptr->ObMaxZ = sptr1->shapemaxz;
226
227 }
228
229 else {
230
231 dptr->ObMaxZ = WideMul2NarrowDiv(sptr1->shapemaxz,
232 MorphDisplay.md_one_minus_lerp,
233 sptr2->shapemaxz,
234 MorphDisplay.md_lerp, ONE_FIXED);
235
236 }
237
238 if(sptr1->shapeminz == sptr2->shapeminz) {
239
240 dptr->ObMinZ = sptr1->shapeminz;
241
242 }
243
244 else {
245
246 dptr->ObMinZ = WideMul2NarrowDiv(sptr1->shapeminz,
247 MorphDisplay.md_one_minus_lerp,
248 sptr2->shapeminz,
249 MorphDisplay.md_lerp, ONE_FIXED);
250
251 }
252
253 #if 0
254 textprint("dptr->ObRadius = %d\n", dptr->ObRadius);
255 #endif
256
257 }
258
259
260
261 /*
262
263 Using the current frame, calculate the lerp values and find out which two
264 shapes to interpolate between.
265
266 Write this information back to a MORPHDISPLAY structure.
267
268 */
269
GetMorphDisplay(MORPHDISPLAY * md,DISPLAYBLOCK * dptr)270 void GetMorphDisplay(MORPHDISPLAY *md, DISPLAYBLOCK *dptr)
271 {
272 MORPHFRAME *mdata;
273 MORPHCTRL *mc = dptr->ObMorphCtrl;
274 MORPHHEADER *mhdr = mc->ObMorphHeader;
275
276
277 md->md_lerp = mc->ObMorphCurrFrame & 0xffff;
278 md->md_one_minus_lerp = ONE_FIXED - md->md_lerp;
279
280 mdata = mhdr->mph_frames;
281 mdata = &mdata[mc->ObMorphCurrFrame >> 16];
282
283 md->md_shape1 = mdata->mf_shape1;
284 md->md_shape2 = mdata->mf_shape2;
285
286 md->md_sptr1 = GetShapeData(md->md_shape1);
287 md->md_sptr2 = GetShapeData(md->md_shape2);
288 }
289
290
CopyMorphCtrl(MORPHCTRL * src,MORPHCTRL * dst)291 void CopyMorphCtrl(MORPHCTRL *src, MORPHCTRL *dst)
292 {
293 dst->ObMorphCurrFrame = src->ObMorphCurrFrame;
294 dst->ObMorphFlags = src->ObMorphFlags;
295 dst->ObMorphSpeed = src->ObMorphSpeed;
296 dst->ObMorphHeader = src->ObMorphHeader;
297 }
298