Rev 1 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | #include "spark.h" |
18 | pmbaty | 2 | #include "brender.h" |
1 | pmbaty | 3 | #include "car.h" |
18 | pmbaty | 4 | #include "crush.h" |
1 | pmbaty | 5 | #include "depth.h" |
18 | pmbaty | 6 | #include "displays.h" |
1 | pmbaty | 7 | #include "errors.h" |
18 | pmbaty | 8 | #include "formats.h" |
1 | pmbaty | 9 | #include "globvars.h" |
10 | #include "globvrkm.h" |
||
11 | #include "graphics.h" |
||
12 | #include "harness/hooks.h" |
||
13 | #include "harness/trace.h" |
||
14 | #include "loading.h" |
||
15 | #include "opponent.h" |
||
16 | #include "piping.h" |
||
17 | #include "replay.h" |
||
18 | #include "trig.h" |
||
19 | #include "utility.h" |
||
20 | #include "world.h" |
||
18 | pmbaty | 21 | #include <math.h> |
1 | pmbaty | 22 | #include <stdlib.h> |
23 | |||
24 | int gNext_spark; |
||
25 | int gSpark_flags; |
||
26 | int gNext_shrapnel; |
||
27 | int gShrapnel_flags; |
||
28 | br_model* gShrapnel_model[2]; |
||
29 | int gSmoke_flags; |
||
30 | int gSmoke_num; |
||
31 | int gOffset = 0; |
||
32 | int gColumn_flags; |
||
33 | int gNext_column; |
||
34 | br_pixelmap* gBlack_smoke_shade_table; |
||
35 | br_pixelmap* gDark_smoke_shade_table; |
||
36 | br_pixelmap* gGrey_smoke_shade_table; |
||
37 | int gSmoke_on = 1; |
||
38 | int gNum_splash_types; |
||
39 | int gIt_type; |
||
40 | br_pixelmap* gIt_shade_table; |
||
41 | br_pixelmap** gDust_table = &gShade_list[8]; |
||
42 | br_pixelmap* gFlame_map[20]; |
||
43 | tBRender_smoke* gBR_smoke_pointers[30]; |
||
44 | tSplash gSplash[32]; |
||
45 | br_material* gSplash_material[20]; |
||
46 | tBRender_smoke gBR_smoke_structs[30]; |
||
47 | tSmoke_column gSmoke_column[25]; |
||
48 | br_matrix4 gCameraToScreen; |
||
49 | tSpark gSparks[32]; |
||
50 | br_pixelmap* gShade_list[16]; |
||
51 | int gN_BR_smoke_structs; |
||
52 | tSmoke gSmoke[25]; |
||
53 | tU32 gSplash_flags; |
||
54 | tU32 gNext_splash; |
||
55 | br_model* gLollipop_model; |
||
56 | int gNum_dust_tables; |
||
57 | br_model* gSplash_model; |
||
58 | int gDust_rotate; |
||
59 | br_camera* gSpark_cam; |
||
60 | br_material* gBlack_material; |
||
61 | tShrapnel gShrapnel[15]; |
||
62 | |||
63 | // gSmoke_column has 25 elements but all the code just checks the first 5 elements |
||
64 | #define MAX_SMOKE_COLUMNS 5 |
||
65 | |||
66 | // Bugfix: At higher FPS, flame animation runs too quickly, so introduce a new frame timer |
||
67 | #define FLAME_ANIMATION_FRAME_INTERVAL 40 |
||
68 | |||
69 | // Bugfix: At higher FPS, `CreatePuffOfSmoke` is called too often and causes smoke cirlces to be recycled too quickly so assume around 25fps |
||
70 | #define SMOKE_COLUMN_NEW_PUFF_INTERVAL 30 |
||
71 | |||
72 | // IDA: void __cdecl DrawDot(br_scalar z, tU8 *scr_ptr, tU16 *depth_ptr, tU8 *shade_ptr) |
||
73 | void DrawDot(br_scalar z, tU8* scr_ptr, tU16* depth_ptr, tU8* shade_ptr) { |
||
74 | LOG_TRACE("(%f, %p, %p, %p)", z, scr_ptr, depth_ptr, shade_ptr); |
||
75 | |||
76 | if (*depth_ptr > (1.0 - z) * 32768.0f) { |
||
77 | *depth_ptr = (1.0 - z) * 32768.0f; |
||
78 | *scr_ptr = shade_ptr[*scr_ptr]; |
||
79 | } |
||
80 | } |
||
81 | |||
82 | // IDA: void __usercall SetWorldToScreen(br_pixelmap *pScreen@<EAX>) |
||
83 | void SetWorldToScreen(br_pixelmap* pScreen) { |
||
84 | br_matrix4 mat; |
||
85 | br_matrix4 mat2; |
||
86 | LOG_TRACE("(%p)", pScreen); |
||
87 | |||
88 | BrMatrix4Perspective(&mat, gSpark_cam->field_of_view, gSpark_cam->aspect, -gSpark_cam->hither_z, -gSpark_cam->yon_z); |
||
89 | BrMatrix4Scale(&mat2, pScreen->width / 2, pScreen->height / 2, 1.0f); |
||
90 | BrMatrix4Mul(&gCameraToScreen, &mat, &mat2); |
||
91 | } |
||
92 | |||
93 | // IDA: void __usercall DrawLine3DThroughBRender(br_vector3 *pStart@<EAX>, br_vector3 *pEnd@<EDX>) |
||
94 | void DrawLine3DThroughBRender(br_vector3* pStart, br_vector3* pEnd) { |
||
95 | LOG_TRACE("(%p, %p)", pStart, pEnd); |
||
96 | NOT_IMPLEMENTED(); |
||
97 | } |
||
98 | |||
99 | // IDA: int __usercall DrawLine3D@<EAX>(br_vector3 *start@<EAX>, br_vector3 *end@<EDX>, br_pixelmap *pScreen@<EBX>, br_pixelmap *pDepth_buffer@<ECX>, br_pixelmap *shade_table) |
||
100 | int DrawLine3D(br_vector3* start, br_vector3* end, br_pixelmap* pScreen, br_pixelmap* pDepth_buffer, br_pixelmap* shade_table) { |
||
101 | br_vector3 o; |
||
102 | br_vector3 p; |
||
103 | //br_vector3 tv; // Pierre-Marie Baty -- unused variable |
||
104 | br_vector4 o2; |
||
105 | br_vector4 p2; |
||
106 | br_scalar ts; |
||
107 | LOG_TRACE("(%p, %p, %p, %p, %p)", start, end, pScreen, pDepth_buffer, shade_table); |
||
108 | |||
109 | o = *start; |
||
110 | p = *end; |
||
111 | if (-gSpark_cam->hither_z < o.v[2] || -gSpark_cam->hither_z < p.v[2]) { |
||
112 | if (-gSpark_cam->hither_z < o.v[2] && -gSpark_cam->hither_z < p.v[2]) { |
||
113 | return 0; |
||
114 | } |
||
115 | ts = (p.v[2] + gSpark_cam->hither_z) / (p.v[2] - o.v[2]); |
||
116 | if (-gSpark_cam->hither_z < o.v[2]) { |
||
117 | o.v[0] = p.v[0] - (p.v[0] - o.v[0]) * ts; |
||
118 | o.v[1] = p.v[1] - (p.v[1] - o.v[1]) * ts; |
||
119 | o.v[2] = -gSpark_cam->hither_z; |
||
120 | } |
||
121 | if (-gSpark_cam->hither_z < p.v[2]) { |
||
122 | p.v[0] = p.v[0] - (p.v[0] - o.v[0]) * ts; |
||
123 | p.v[1] = p.v[1] - (p.v[1] - o.v[1]) * ts; |
||
124 | p.v[2] = -gSpark_cam->hither_z; |
||
125 | } |
||
126 | } |
||
127 | BrMatrix4ApplyP(&o2, &o, &gCameraToScreen); |
||
128 | BrMatrix4ApplyP(&p2, &p, &gCameraToScreen); |
||
129 | o.v[0] = o2.v[0] / o2.v[3]; |
||
130 | o.v[1] = o2.v[1] / o2.v[3]; |
||
131 | o.v[2] = o2.v[2] / o2.v[3]; |
||
132 | p.v[0] = p2.v[0] / p2.v[3]; |
||
133 | p.v[1] = p2.v[1] / p2.v[3]; |
||
134 | p.v[2] = p2.v[2] / p2.v[3]; |
||
135 | return DrawLine2D(&o, &p, pScreen, pDepth_buffer, 1.0, shade_table); |
||
136 | } |
||
137 | |||
138 | // IDA: int __usercall DrawLine2D@<EAX>(br_vector3 *o@<EAX>, br_vector3 *p@<EDX>, br_pixelmap *pScreen@<EBX>, br_pixelmap *pDepth_buffer@<ECX>, br_scalar brightness, br_pixelmap *shade_table) |
||
139 | int DrawLine2D(br_vector3* o, br_vector3* p, br_pixelmap* pScreen, br_pixelmap* pDepth_buffer, br_scalar brightness, br_pixelmap* shade_table) { |
||
140 | tU8* scr_ptr; |
||
141 | tU16* depth_ptr; |
||
142 | tU8* shade_ptr; |
||
143 | int x1; |
||
144 | int x2; |
||
145 | int y1; |
||
146 | int y2; |
||
147 | int d; |
||
148 | int dx; |
||
149 | int dy; |
||
150 | int ax; |
||
151 | int sx; |
||
152 | int ay; |
||
153 | int sy; |
||
154 | int x; |
||
155 | int y; |
||
156 | br_scalar zbuff; |
||
157 | br_scalar zbuff_inc; |
||
158 | int darken_count; |
||
159 | int darken_init; |
||
160 | LOG_TRACE("(%p, %p, %p, %p, %f, %p)", o, p, pScreen, pDepth_buffer, brightness, shade_table); |
||
161 | |||
162 | scr_ptr = (tU8*)pScreen->pixels + pScreen->base_x + pScreen->base_y * pScreen->row_bytes; |
||
163 | depth_ptr = (tU16*)pDepth_buffer->pixels; |
||
164 | shade_ptr = (tU8*)shade_table->pixels + shade_table->base_y * shade_table->row_bytes; |
||
165 | x1 = pScreen->width / 2 + o->v[0]; |
||
166 | x2 = pScreen->width / 2 + p->v[0]; |
||
167 | y1 = pScreen->height / 2 - o->v[1]; |
||
168 | y2 = pScreen->height / 2 - p->v[1]; |
||
169 | if (brightness < 0.001 || brightness > 1.0) { |
||
170 | return 0; |
||
171 | } |
||
172 | if (x1 < 0 || x2 < 0) { |
||
173 | if (x1 < 0 && x2 < 0) { |
||
174 | return 0; |
||
175 | } |
||
176 | if (x1 >= 0) { |
||
177 | y2 = y1 - x1 * (y1 - y2) / (x1 - x2); |
||
178 | p->v[2] = o->v[2] - (o->v[2] - p->v[2]) * (float)x1 / (float)(x1 - x2); |
||
179 | x2 = 0; |
||
180 | } else { |
||
181 | y1 = y2 - x2 * (y2 - y1) / (x2 - x1); |
||
182 | o->v[2] = p->v[2] - (p->v[2] - o->v[2]) * (float)x2 / (float)(x2 - x1); |
||
183 | x1 = 0; |
||
184 | } |
||
185 | } |
||
186 | if (pScreen->width <= x1 || pScreen->width <= x2) { |
||
187 | if (pScreen->width <= x1 && pScreen->width <= x2) { |
||
188 | return 0; |
||
189 | } |
||
190 | if (pScreen->width > x1) { |
||
191 | y2 = y1 - (y1 - y2) * (x1 - (pScreen->width - 1)) / (x1 - x2); |
||
192 | p->v[2] = o->v[2] - (o->v[2] - p->v[2]) * (x1 - (float)(pScreen->width - 1)) / (float)(x1 - x2); |
||
193 | x2 = pScreen->width - 1; |
||
194 | } else { |
||
195 | y1 = y2 - (y2 - y1) * (x2 - (pScreen->width - 1)) / (x2 - x1); |
||
196 | o->v[2] = p->v[2] - (p->v[2] - o->v[2]) * (x2 - (float)(pScreen->width - 1)) / (float)(x2 - x1); |
||
197 | x1 = pScreen->width - 1; |
||
198 | } |
||
199 | } |
||
200 | if (y1 < 0 || y2 < 0) { |
||
201 | if (y1 < 0 && y2 < 0) { |
||
202 | return 0; |
||
203 | } |
||
204 | if (y1 >= 0) { |
||
205 | x2 = x1 - y1 * (x1 - x2) / (y1 - y2); |
||
206 | p->v[2] = o->v[2] - (o->v[2] - p->v[2]) * (float)y1 / (float)(y1 - y2); |
||
207 | y2 = 0; |
||
208 | } else { |
||
209 | x1 = x2 - y2 * (x2 - x1) / (y2 - y1); |
||
210 | o->v[2] = p->v[2] - (p->v[2] - o->v[2]) * (float)y2 / (float)(y2 - y1); |
||
211 | y1 = 0; |
||
212 | } |
||
213 | } |
||
214 | if (pScreen->height <= y1 || pScreen->height <= y2) { |
||
215 | if (pScreen->height <= y1 && pScreen->height <= y2) { |
||
216 | return 0; |
||
217 | } |
||
218 | if (pScreen->height > y1) { |
||
219 | x2 = x1 - (x1 - x2) * (y1 - (pScreen->height - 1)) / (y1 - y2); |
||
220 | p->v[2] = o->v[2] - (o->v[2] - p->v[2]) * (float)(y1 - (pScreen->height - 1)) / (float)(y1 - y2); |
||
221 | y2 = pScreen->height - 1; |
||
222 | } else { |
||
223 | x1 = x2 - (x2 - x1) * (y2 - (pScreen->height - 1)) / (y2 - y1); |
||
224 | o->v[2] = p->v[2] - (p->v[2] - o->v[2]) * (float)(y2 - (pScreen->height - 1)) / (float)(y2 - y1); |
||
225 | y1 = pScreen->height - 1; |
||
226 | } |
||
227 | } |
||
228 | zbuff = o->v[2]; |
||
229 | dx = x2 - x1; |
||
230 | dy = y2 - y1; |
||
231 | ax = 2 * abs(dx); |
||
232 | if (x2 - x1 < 0) { |
||
233 | sx = -1; |
||
234 | } else { |
||
235 | sx = 1; |
||
236 | } |
||
237 | ay = 2 * abs(dy); |
||
238 | if (dy < 0) { |
||
239 | sy = -1; |
||
240 | } else { |
||
241 | sy = 1; |
||
242 | } |
||
243 | x = x1; |
||
244 | y = y1; |
||
245 | scr_ptr += x1 + y1 * pScreen->row_bytes; |
||
246 | depth_ptr += x1 + y1 * (pDepth_buffer->row_bytes / 2); |
||
247 | darken_init = (brightness - 0.001) * (float)shade_table->height; |
||
248 | if (ay >= ax) { |
||
249 | d = ax - ay / 2; |
||
250 | darken_init = 500 * ay / darken_init; |
||
251 | darken_count = darken_init; |
||
252 | zbuff_inc = (p->v[2] - o->v[2]) * 2.0 / (float)ay; |
||
253 | while (1) { |
||
254 | DrawDot(zbuff, scr_ptr, depth_ptr, shade_ptr); |
||
255 | if (y == y2) { |
||
256 | break; |
||
257 | } |
||
258 | if (d >= 0) { |
||
259 | scr_ptr += sx; |
||
260 | depth_ptr += sx; |
||
261 | d -= ay; |
||
262 | } |
||
263 | y += sy; |
||
264 | d += ax; |
||
265 | scr_ptr += sy * pScreen->row_bytes; |
||
266 | depth_ptr += sy * (pDepth_buffer->row_bytes / 2); |
||
267 | zbuff = zbuff_inc + zbuff; |
||
268 | darken_count -= 1000; |
||
269 | while (darken_count <= 0) { |
||
270 | darken_count += darken_init; |
||
271 | shade_ptr += shade_table->row_bytes; |
||
272 | } |
||
273 | } |
||
274 | } else { |
||
275 | d = ay - ax / 2; |
||
276 | darken_init = 500 * ax / darken_init; |
||
277 | darken_count = darken_init; |
||
278 | zbuff_inc = (p->v[2] - o->v[2]) * 2.0 / (float)ax; |
||
279 | while (1) { |
||
280 | DrawDot(zbuff, scr_ptr, depth_ptr, shade_ptr); |
||
281 | if (x == x2) { |
||
282 | break; |
||
283 | } |
||
284 | if (d >= 0) { |
||
285 | scr_ptr += sy * pScreen->row_bytes; |
||
286 | depth_ptr += sy * (pDepth_buffer->row_bytes / 2); |
||
287 | d -= ax; |
||
288 | } |
||
289 | x += sx; |
||
290 | scr_ptr += sx; |
||
291 | depth_ptr += sx; |
||
292 | d += ay; |
||
293 | zbuff = zbuff_inc + zbuff; |
||
294 | darken_count -= 1000; |
||
295 | while (darken_count <= 0) { |
||
296 | darken_count += darken_init; |
||
297 | shade_ptr += shade_table->row_bytes; |
||
298 | } |
||
299 | } |
||
300 | } |
||
301 | return 1; |
||
302 | } |
||
303 | |||
304 | // IDA: void __usercall SetLineModelCols(tU8 pCol@<EAX>) |
||
305 | void SetLineModelCols(tU8 pCol) { |
||
306 | LOG_TRACE("(%d)", pCol); |
||
307 | NOT_IMPLEMENTED(); |
||
308 | } |
||
309 | |||
310 | // IDA: void __usercall ReplaySparks(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, tU32 pTime@<ECX>) |
||
311 | void ReplaySparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_actor* pCamera, tU32 pTime) { |
||
312 | int i; |
||
313 | br_vector3 pos; |
||
314 | br_vector3 o; |
||
315 | br_vector3 p; |
||
316 | br_vector3 tv; |
||
317 | br_vector3 new_pos; |
||
318 | LOG_TRACE("(%p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pTime); |
||
319 | |||
320 | for (i = 0; i < COUNT_OF(gSparks); i++) { |
||
321 | if (gSpark_flags & (1 << i)) { |
||
322 | if (gSparks[i].car == NULL) { |
||
323 | BrVector3Copy(&pos, &gSparks[i].pos); |
||
324 | } else { |
||
325 | BrMatrix34ApplyP(&tv, &o, &gSparks[i].car->car_master_actor->t.t.mat); |
||
326 | BrVector3Copy(&o, &tv); |
||
327 | BrMatrix34ApplyP(&pos, &gSparks[i].pos, &gSparks[i].car->car_master_actor->t.t.mat); |
||
328 | } |
||
329 | BrVector3Add(&o, &pos, &gSparks[i].length); |
||
330 | BrVector3Sub(&tv, &pos, (br_vector3*)gCamera_to_world.m[3]); |
||
331 | BrMatrix34TApplyV(&new_pos, &tv, &gCamera_to_world); |
||
332 | BrVector3Sub(&tv, &o, (br_vector3*)gCamera_to_world.m[3]); |
||
333 | BrMatrix34TApplyV(&p, &tv, &gCamera_to_world); |
||
334 | if (gSparks[i].colour) { |
||
335 | DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gFog_shade_table); |
||
336 | } else { |
||
337 | DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gAcid_shade_table); |
||
338 | } |
||
339 | } |
||
340 | } |
||
341 | } |
||
342 | |||
343 | // IDA: void __usercall RenderSparks(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>, tU32 pTime) |
||
344 | void RenderSparks(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world, tU32 pTime) { |
||
345 | int i; |
||
346 | int time; |
||
347 | br_vector3 tv; |
||
348 | br_vector3 o; |
||
349 | br_vector3 p; |
||
350 | br_vector3 pos; |
||
351 | br_vector3 new_pos; |
||
352 | br_scalar ts; |
||
353 | LOG_TRACE("(%p, %p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pCamera_to_world, pTime); |
||
354 | |||
355 | gSpark_cam = pCamera->type_data; |
||
356 | SetWorldToScreen(pRender_screen); |
||
357 | |||
358 | if (!gSpark_flags) { |
||
359 | return; |
||
360 | } |
||
361 | |||
362 | if (gAction_replay_mode) { |
||
363 | ReplaySparks(pRender_screen, pDepth_buffer, pCamera, pTime); |
||
364 | return; |
||
365 | } |
||
366 | StartPipingSession(ePipe_chunk_spark); |
||
367 | for (i = 0; i < COUNT_OF(gSparks); i++) { |
||
368 | if (((1u << i) & gSpark_flags) == 0) { |
||
369 | continue; |
||
370 | } |
||
371 | if (gSparks[i].count <= 0) { |
||
372 | gSparks[i].count = 0; |
||
373 | gSpark_flags &= ~(1u << i); |
||
374 | } |
||
375 | ts = BrVector3Dot(&gSparks[i].normal, &gSparks[i].v); |
||
376 | BrVector3Scale(&tv, &gSparks[i].normal, ts); |
||
377 | BrVector3Sub(&gSparks[i].v, &gSparks[i].v, &tv); |
||
378 | if (gSparks[i].time_sync) { |
||
379 | BrVector3Scale(&o, &gSparks[i].v, gSparks[i].time_sync / 1000.0); |
||
380 | gSparks[i].count = gSparks[i].time_sync + gSparks[i].count - pTime; |
||
381 | gSparks[i].time_sync = 0; |
||
382 | } else { |
||
383 | BrVector3Scale(&o, &gSparks[i].v, pTime / 1000.0); |
||
384 | gSparks[i].count -= pTime; |
||
385 | } |
||
386 | BrVector3Accumulate(&gSparks[i].pos, &o); |
||
387 | time = 1000 - gSparks[i].count; |
||
388 | if (time > 150) { |
||
389 | time = 150; |
||
390 | } |
||
391 | ts = -time / 1000.0; |
||
392 | if (gSparks[i].colour) { |
||
393 | ts = ts / 2.0; |
||
394 | } |
||
395 | BrVector3Scale(&gSparks[i].length, &gSparks[i].v, ts); |
||
396 | ts = pTime * 10.0 / 6900.0; |
||
397 | if (gSparks[i].car) { |
||
398 | BrMatrix34ApplyV(&tv, &gSparks[i].length, &gSparks[i].car->car_master_actor->t.t.mat); |
||
399 | BrVector3Copy(&gSparks[i].length, &tv); |
||
400 | BrMatrix34ApplyP(&pos, &gSparks[i].pos, &gSparks[i].car->car_master_actor->t.t.mat); |
||
401 | o = tv; |
||
402 | gSparks[i].v.v[0] = gSparks[i].v.v[0] - gSparks[i].car->car_master_actor->t.t.mat.m[0][1] * ts; |
||
403 | gSparks[i].v.v[1] = gSparks[i].v.v[1] - gSparks[i].car->car_master_actor->t.t.mat.m[1][1] * ts; |
||
404 | gSparks[i].v.v[2] = gSparks[i].v.v[2] - gSparks[i].car->car_master_actor->t.t.mat.m[2][1] * ts; |
||
405 | } else { |
||
406 | BrVector3Copy(&pos, &gSparks[i].pos); |
||
407 | gSparks[i].v.v[1] = gSparks[i].v.v[1] - ts; |
||
408 | } |
||
409 | AddSparkToPipingSession(i + (gSparks[i].colour << 8), &pos, &gSparks[i].length); |
||
410 | BrVector3Add(&o, &gSparks[i].length, &pos); |
||
411 | BrVector3Sub(&tv, &pos, (br_vector3*)gCamera_to_world.m[3]); |
||
412 | BrMatrix34TApplyV(&new_pos, &tv, &gCamera_to_world); |
||
413 | BrVector3Sub(&tv, &o, (br_vector3*)gCamera_to_world.m[3]); |
||
414 | BrMatrix34TApplyV(&p, &tv, &gCamera_to_world); |
||
415 | BrVector3SetFloat(&tv, FRandomBetween(-0.1f, 0.1f), FRandomBetween(-0.1f, 0.1f), FRandomBetween(-0.1f, 0.1f)); |
||
416 | BrVector3Accumulate(&gSparks[i].v, &tv); |
||
417 | ts = 1.0f - BrVector3Length(&gSparks[i].v) / 1.4f * pTime / 1000.0f; |
||
418 | if (ts < 0.1f) { |
||
419 | ts = 0.1f; |
||
420 | } |
||
421 | BrVector3Scale(&gSparks[i].v, &gSparks[i].v, ts); |
||
422 | if (gSparks[i].colour) { |
||
423 | DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gFog_shade_table); |
||
424 | } else { |
||
425 | DrawLine3D(&p, &new_pos, pRender_screen, pDepth_buffer, gAcid_shade_table); |
||
426 | } |
||
427 | } |
||
428 | EndPipingSession(); |
||
429 | } |
||
430 | |||
431 | // IDA: void __usercall CreateSingleSpark(tCar_spec *pCar@<EAX>, br_vector3 *pPos@<EDX>, br_vector3 *pVel@<EBX>) |
||
432 | void CreateSingleSpark(tCar_spec* pCar, br_vector3* pPos, br_vector3* pVel) { |
||
433 | LOG_TRACE("(%p, %p, %p)", pCar, pPos, pVel); |
||
434 | |||
435 | BrVector3Copy(&gSparks[gNext_spark].pos, pPos); |
||
436 | BrVector3SetFloat(&gSparks[gNext_spark].normal, 0.0f, 0.0f, 0.0f); |
||
437 | BrVector3Copy(&gSparks[gNext_spark].v, pVel); |
||
438 | gSparks[gNext_spark].count = 500; |
||
439 | gSparks[gNext_spark].car = pCar; |
||
440 | gSpark_flags |= 1u << gNext_spark; |
||
441 | gSparks[gNext_spark].time_sync = 1; |
||
442 | gSparks[gNext_spark].colour = 1; |
||
443 | gNext_spark++; |
||
444 | if (gNext_spark >= COUNT_OF(gSparks)) { |
||
445 | gNext_spark = 0; |
||
446 | } |
||
447 | } |
||
448 | |||
449 | // IDA: void __usercall CreateSparks(br_vector3 *pos@<EAX>, br_vector3 *v@<EDX>, br_vector3 *pForce@<EBX>, br_scalar sparkiness, tCar_spec *pCar) |
||
450 | void CreateSparks(br_vector3* pos, br_vector3* v, br_vector3* pForce, br_scalar sparkiness, tCar_spec* pCar) { |
||
451 | br_vector3 norm; |
||
452 | br_vector3 normal; |
||
453 | br_vector3 tv; |
||
454 | br_vector3 tv2; |
||
455 | br_vector3 pos2; |
||
456 | br_scalar ts; |
||
457 | br_scalar ts2; |
||
458 | int num; |
||
459 | int i; |
||
460 | LOG_TRACE("(%p, %p, %p, %f, %p)", pos, v, pForce, sparkiness, pCar); |
||
461 | |||
462 | ts = BrVector3Length(pForce); |
||
463 | BrVector3InvScale(&normal, pForce, ts); |
||
464 | ts2 = BrVector3Dot(pForce, v); |
||
465 | if (ts2 >= 0) { |
||
466 | ts2 = 1.f / (10.f * ts); |
||
467 | } else { |
||
468 | ts2 = 1.f / (10.f * ts) - ts2 / (ts * ts); |
||
469 | } |
||
470 | |||
471 | BrVector3Scale(&norm, pForce, ts2); |
||
472 | BrVector3Accumulate(v, &norm); |
||
473 | num = FRandomBetween(0.f, BrVector3Length(v) / 2.f + 0.7f) * sparkiness; |
||
474 | |||
475 | if (num > 10) { |
||
476 | num = 10; |
||
477 | } |
||
478 | for (i = 0; i < num; i++) { |
||
479 | BrVector3Copy(&gSparks[gNext_spark].pos, pos); |
||
480 | BrVector3Copy(&gSparks[gNext_spark].normal, &normal); |
||
481 | BrVector3Copy(&gSparks[gNext_spark].v, v); |
||
482 | gSparks[gNext_spark].v.v[0] *= FRandomBetween(.5f, .9f); |
||
483 | gSparks[gNext_spark].v.v[1] *= FRandomBetween(.5f, .9f); |
||
484 | gSparks[gNext_spark].v.v[2] *= FRandomBetween(.5f, .9f); |
||
485 | gSparks[gNext_spark].count = 1000; |
||
486 | gSparks[gNext_spark].car = NULL; |
||
487 | gSpark_flags |= 1u << gNext_spark; |
||
488 | gSparks[gNext_spark].time_sync = gMechanics_time_sync; |
||
489 | gSparks[gNext_spark].colour = 0; |
||
490 | gNext_spark++; |
||
491 | if (gNext_spark >= COUNT_OF(gSparks)) { |
||
492 | gNext_spark = 0; |
||
493 | } |
||
494 | } |
||
495 | if ((ts * sparkiness) >= 10.f) { |
||
496 | tv.v[0] = pos->v[0] - pCar->car_master_actor->t.t.translate.t.v[0] / WORLD_SCALE; |
||
497 | tv.v[1] = pos->v[1] - pCar->car_master_actor->t.t.translate.t.v[1] / WORLD_SCALE; |
||
498 | tv.v[2] = pos->v[2] - pCar->car_master_actor->t.t.translate.t.v[2] / WORLD_SCALE; |
||
499 | BrMatrix34TApplyV(&pos2, &tv, &pCar->car_master_actor->t.t.mat); |
||
500 | BrMatrix34TApplyV(&norm, &normal, &pCar->car_master_actor->t.t.mat); |
||
501 | BrVector3Scale(&tv, &norm, .1f); |
||
502 | BrVector3Accumulate(&pos2, &tv); |
||
503 | num = (ts * sparkiness / 10.f) + 3; |
||
504 | if (num > 10) { |
||
505 | num = 10; |
||
506 | } |
||
507 | for (i = 0; i < num; i++) { |
||
508 | BrVector3Copy(&gSparks[gNext_spark].pos, &pos2); |
||
509 | BrVector3Copy(&gSparks[gNext_spark].normal, &norm); |
||
510 | BrVector3SetFloat(&tv, FRandomBetween(-1.f, 1.f), FRandomBetween(-.2f, 1.f), FRandomBetween(-1.f, 1.f)); |
||
511 | ts2 = BrVector3Dot(&norm, &tv); |
||
512 | BrVector3Scale(&tv2, &norm, ts2); |
||
513 | BrVector3Sub(&gSparks[gNext_spark].v, &tv, &tv2); |
||
514 | gSparks[gNext_spark].count = 1000; |
||
515 | gSparks[gNext_spark].car = pCar; |
||
516 | gSpark_flags |= 1u << gNext_spark; |
||
517 | gSparks[gNext_spark].time_sync = gMechanics_time_sync; |
||
518 | gSparks[gNext_spark].colour = 0; |
||
519 | gNext_spark++; |
||
520 | if (gNext_spark >= COUNT_OF(gSparks)) { |
||
521 | gNext_spark = 0; |
||
522 | } |
||
523 | } |
||
524 | CreateShrapnelShower(pos, v, &normal, ts, pCar, pCar); |
||
525 | } |
||
526 | } |
||
527 | |||
528 | // IDA: void __usercall CreateSparkShower(br_vector3 *pos@<EAX>, br_vector3 *v@<EDX>, br_vector3 *pForce@<EBX>, tCar_spec *pCar1@<ECX>, tCar_spec *pCar2) |
||
529 | void CreateSparkShower(br_vector3* pos, br_vector3* v, br_vector3* pForce, tCar_spec* pCar1, tCar_spec* pCar2) { |
||
530 | br_scalar ts; |
||
531 | br_scalar ts2; |
||
532 | int num; |
||
533 | int i; |
||
534 | tCar_spec* c; |
||
535 | br_vector3 tv; |
||
536 | //br_vector3 tv2; // Pierre-Marie Baty -- unused variable |
||
537 | br_vector3 normal; |
||
538 | LOG_TRACE("(%p, %p, %p, %p, %p)", pos, v, pForce, pCar1, pCar2); |
||
539 | |||
540 | ts = BrVector3Length(pForce); |
||
541 | if (pCar1->driver == eDriver_local_human) { |
||
542 | c = pCar1; |
||
543 | } else { |
||
544 | c = pCar2; |
||
545 | } |
||
546 | BrVector3InvScale(&tv, pForce, ts); |
||
547 | if (ts < 10.f) { |
||
548 | return; |
||
549 | } |
||
550 | CreateShrapnelShower(pos, v, &tv, ts, pCar1, pCar2); |
||
551 | ts2 = BrVector3Dot(pForce, v) / (ts * ts); |
||
552 | BrVector3Scale(v, pForce, ts2); |
||
553 | normal.v[0] = pos->v[0] - c->car_master_actor->t.t.translate.t.v[0] / WORLD_SCALE; |
||
554 | normal.v[1] = pos->v[1] - c->car_master_actor->t.t.translate.t.v[1] / WORLD_SCALE; |
||
555 | normal.v[2] = pos->v[2] - c->car_master_actor->t.t.translate.t.v[2] / WORLD_SCALE; |
||
556 | BrMatrix34TApplyV(pos, &normal, &c->car_master_actor->t.t.mat); |
||
557 | BrMatrix34TApplyV(&normal, pForce, &c->car_master_actor->t.t.mat); |
||
558 | num = (ts / 10.f) + 3; |
||
559 | for (i = 0; i < num; i++) { |
||
560 | BrVector3Copy(&gSparks[gNext_spark].pos, pos); |
||
561 | BrVector3SetFloat(&gSparks[gNext_spark].normal, 0.f, 0.f, 0.f); |
||
562 | BrVector3SetFloat(&normal, FRandomBetween(-1.f, 1.f), FRandomBetween(-.2f, 1.f), FRandomBetween(-1.f, 1.f)); |
||
563 | ts2 = BrVector3LengthSquared(&normal) / (ts * ts); |
||
564 | BrVector3Scale(&tv, &normal, ts2); |
||
565 | BrVector3Sub(&gSparks[gNext_spark].v, &normal, &tv); |
||
566 | BrVector3Accumulate(&gSparks[gNext_spark].v, v); |
||
567 | gSparks[gNext_spark].count = 1000; |
||
568 | gSparks[gNext_spark].car = c; |
||
569 | gSpark_flags |= 1u << gNext_spark; |
||
570 | gSparks[gNext_spark].time_sync = gMechanics_time_sync; |
||
571 | gSparks[gNext_spark].colour = 0; |
||
572 | gNext_spark++; |
||
573 | if (gNext_spark >= COUNT_OF(gSparks)) { |
||
574 | gNext_spark = 0; |
||
575 | } |
||
576 | } |
||
577 | } |
||
578 | |||
579 | // IDA: void __usercall AdjustSpark(int pSpark_num@<EAX>, br_vector3 *pos@<EDX>, br_vector3 *length@<EBX>) |
||
580 | void AdjustSpark(int pSpark_num, br_vector3* pos, br_vector3* length) { |
||
581 | br_vector3 tv; |
||
582 | br_matrix34* mat; |
||
583 | int i; |
||
584 | LOG_TRACE("(%d, %p, %p)", pSpark_num, pos, length); |
||
585 | |||
586 | i = pSpark_num & 0xff; |
||
587 | gSpark_flags |= 1u << pSpark_num; |
||
588 | if (gSparks[i].car != NULL) { |
||
589 | mat = &gSparks[i].car->car_master_actor->t.t.mat; |
||
590 | tv.v[0] = pos->v[0] - mat->m[3][0]; |
||
591 | tv.v[1] = pos->v[0] - mat->m[3][1]; |
||
592 | tv.v[2] = pos->v[0] - mat->m[3][2]; |
||
593 | BrMatrix34TApplyV(&gSparks[i].pos, &tv, mat); |
||
594 | } else { |
||
595 | gSparks[i].pos.v[0] = pos->v[0]; |
||
596 | gSparks[i].pos.v[1] = pos->v[1]; |
||
597 | gSparks[i].pos.v[2] = pos->v[2]; |
||
598 | } |
||
599 | gSparks[i].length.v[0] = length->v[0]; |
||
600 | gSparks[i].length.v[1] = length->v[1]; |
||
601 | gSparks[i].length.v[2] = length->v[2]; |
||
602 | gSparks[i].colour = pSpark_num >> 8; |
||
603 | } |
||
604 | |||
605 | // IDA: void __usercall AdjustShrapnel(int pShrapnel_num@<EAX>, br_vector3 *pos@<EDX>, tU16 pAge@<EBX>, br_material *pMaterial@<ECX>) |
||
606 | void AdjustShrapnel(int pShrapnel_num, br_vector3* pos, tU16 pAge, br_material* pMaterial) { |
||
607 | int i; |
||
608 | LOG_TRACE("(%d, %p, %d, %p)", pShrapnel_num, pos, pAge, pMaterial); |
||
609 | |||
610 | i = pShrapnel_num & 0x7fff; |
||
611 | if (!(gShrapnel_flags & (1u << i))) { |
||
612 | BrActorAdd(gNon_track_actor, gShrapnel[i].actor); |
||
613 | } |
||
614 | gShrapnel_flags |= 1u << i; |
||
615 | gShrapnel[i].actor->t.t.translate.t.v[0] = pos->v[0]; |
||
616 | gShrapnel[i].actor->t.t.translate.t.v[1] = pos->v[1]; |
||
617 | gShrapnel[i].actor->t.t.translate.t.v[2] = pos->v[2]; |
||
618 | if (pShrapnel_num & 0x8000) { |
||
619 | gShrapnel[i].age = pAge; |
||
620 | gShrapnel[i].actor->material = pMaterial; |
||
621 | } |
||
622 | } |
||
623 | |||
624 | // IDA: void __cdecl ResetSparks() |
||
625 | void ResetSparks(void) { |
||
626 | LOG_TRACE("()"); |
||
627 | |||
628 | gSpark_flags = 0; |
||
629 | } |
||
630 | |||
631 | // IDA: void __cdecl ResetShrapnel() |
||
632 | void ResetShrapnel(void) { |
||
633 | int i; |
||
634 | LOG_TRACE("()"); |
||
635 | |||
636 | if (gShrapnel_flags == 0) { |
||
637 | return; |
||
638 | } |
||
639 | for (i = 0; i < COUNT_OF(gShrapnel); i++) { |
||
640 | if (gShrapnel_flags & (1u << i)) { |
||
641 | BrActorRemove(gShrapnel[i].actor); |
||
642 | } |
||
643 | } |
||
644 | gShrapnel_flags = 0; |
||
645 | } |
||
646 | |||
647 | // IDA: void __usercall CreateShrapnelShower(br_vector3 *pos@<EAX>, br_vector3 *v@<EDX>, br_vector3 *pNormal@<EBX>, br_scalar pForce, tCar_spec *c1, tCar_spec *c2) |
||
648 | void CreateShrapnelShower(br_vector3* pos, br_vector3* v, br_vector3* pNormal, br_scalar pForce, tCar_spec* c1, tCar_spec* c2) { |
||
649 | br_scalar ts; |
||
650 | br_scalar ts2; |
||
651 | br_scalar rnd; |
||
652 | int num; |
||
653 | int i; |
||
654 | tCar_spec* c; |
||
655 | br_vector3 tv; |
||
656 | br_vector3 tv2; |
||
657 | br_vector3 vel; |
||
658 | LOG_TRACE("(%p, %p, %p, %f, %p, %p)", pos, v, pNormal, pForce, c1, c2); |
||
659 | |||
660 | if (pForce < 10.f) { |
||
661 | return; |
||
662 | } |
||
663 | ts = .3f; |
||
664 | if (v->v[1] < 0.f) { |
||
665 | ts = .3f - v->v[1]; |
||
666 | } |
||
667 | ts2 = pNormal->v[1] * ts; |
||
668 | |||
669 | tv.v[0] = v->v[0] - ts2 * pNormal->v[0]; |
||
670 | tv.v[1] = v->v[1] + ts - pNormal->v[1] * ts2; |
||
671 | tv.v[2] = v->v[2] - pNormal->v[2] * ts2; |
||
672 | |||
673 | num = (pForce / 10.f) * 3; |
||
674 | rnd = ((pForce + 20.f) * 3.f) / 200.f; |
||
675 | for (i = 0; i < num; i++) { |
||
676 | if ((gShrapnel_flags & (1u << gNext_shrapnel)) == 0) { |
||
677 | BrActorAdd(gNon_track_actor, gShrapnel[gNext_shrapnel].actor); |
||
678 | } |
||
679 | gShrapnel_flags |= 1u << gNext_shrapnel; |
||
680 | BrVector3Copy(&gShrapnel[gNext_shrapnel].actor->t.t.translate.t, pos); |
||
681 | BrVector3SetFloat(&vel, FRandomBetween(-rnd, rnd), FRandomBetween(0.3f - tv.v[1], rnd), FRandomBetween(-rnd, rnd)); |
||
682 | ts2 = BrVector3Dot(pNormal, &vel); |
||
683 | BrVector3Scale(&tv2, pNormal, ts2); |
||
684 | BrVector3Sub(&gShrapnel[gNext_shrapnel].v, &vel, &tv2); |
||
685 | BrVector3Accumulate(&gShrapnel[gNext_shrapnel].v, &tv); |
||
686 | gShrapnel[gNext_shrapnel].time_sync = gMechanics_time_sync; |
||
687 | gShrapnel[gNext_shrapnel].age = 0; |
||
688 | if (IRandomBetween(0, 2) != 0) { |
||
689 | c = (IRandomBetween(0, 1) != 0) ? c1 : c2; |
||
690 | gShrapnel[gNext_shrapnel].actor->material = c->shrapnel_material[IRandomBetween(0, c->max_shrapnel_material - 1)]; |
||
691 | } else { |
||
692 | gShrapnel[gNext_shrapnel].actor->material = gBlack_material; |
||
693 | } |
||
694 | gNext_shrapnel++; |
||
695 | if (gNext_shrapnel >= COUNT_OF(gShrapnel)) { |
||
696 | gNext_shrapnel = 0; |
||
697 | } |
||
698 | } |
||
699 | } |
||
700 | |||
701 | // IDA: void __cdecl InitShrapnel() |
||
702 | void InitShrapnel(void) { |
||
703 | int i; |
||
704 | //int j; // Pierre-Marie Baty -- unused variable |
||
705 | LOG_TRACE("()"); |
||
706 | |||
707 | for (i = 0; i < COUNT_OF(gShrapnel); i++) { |
||
708 | gShrapnel[i].actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); |
||
709 | gShrapnel[i].actor->parent = NULL; |
||
710 | gShrapnel[i].actor->model = gShrapnel_model[1]; |
||
711 | gShrapnel[i].actor->render_style = BR_RSTYLE_DEFAULT; |
||
712 | gShrapnel[i].actor->t.type = BR_TRANSFORM_MATRIX34; |
||
713 | gShrapnel[i].actor->material = BrMaterialFind("DEBRIS.MAT"); |
||
714 | gShrapnel[i].age = 0; |
||
715 | gShrapnel[i].shear1 = FRandomBetween(-2.f, 2.f); |
||
716 | gShrapnel[i].shear2 = FRandomBetween(-2.f, 2.f); |
||
717 | BrVector3SetFloat(&gShrapnel[i].axis, |
||
718 | FRandomBetween(-1.f, 1.f), FRandomBetween(-1.f, 1.f), FRandomBetween(-1.f, 1.f)); |
||
719 | BrVector3Normalise(&gShrapnel[i].axis, &gShrapnel[i].axis); |
||
720 | } |
||
721 | } |
||
722 | |||
723 | // IDA: void __cdecl LoadInShrapnel() |
||
724 | void LoadInShrapnel(void) { |
||
725 | LOG_TRACE("()"); |
||
726 | |||
727 | gShrapnel_model[0] = LoadModel("FRAG4.DAT"); |
||
728 | gShrapnel_model[1] = LoadModel("FRAG5.DAT"); |
||
729 | BrModelAdd(gShrapnel_model[0]); |
||
730 | BrModelAdd(gShrapnel_model[1]); |
||
731 | gBlack_material = BrMaterialFind("M14.MAT"); |
||
732 | } |
||
733 | |||
734 | // IDA: void __usercall KillShrapnel(int i@<EAX>) |
||
735 | void KillShrapnel(int i) { |
||
736 | LOG_TRACE("(%d)", i); |
||
737 | |||
738 | BrActorRemove(gShrapnel[i].actor); |
||
739 | gShrapnel_flags &= ~(1u << i); |
||
740 | } |
||
741 | |||
742 | // IDA: void __cdecl DisposeShrapnel() |
||
743 | void DisposeShrapnel(void) { |
||
744 | int i; |
||
745 | LOG_TRACE("()"); |
||
746 | |||
747 | for (i = 0; i < COUNT_OF(gShrapnel); i++) { |
||
748 | if (gShrapnel_flags & (1u << i)) { |
||
749 | BrActorRemove(gShrapnel[i].actor); |
||
750 | } |
||
751 | BrActorFree(gShrapnel[i].actor); |
||
752 | } |
||
753 | gShrapnel_flags = 0; |
||
754 | for (i = 0; i < COUNT_OF(gShrapnel_model); i++) { |
||
755 | BrModelRemove(gShrapnel_model[i]); |
||
756 | BrModelFree(gShrapnel_model[i]); |
||
757 | } |
||
758 | } |
||
759 | |||
760 | // IDA: void __usercall ReplayShrapnel(tU32 pTime@<EAX>) |
||
761 | void ReplayShrapnel(tU32 pTime) { |
||
762 | int i; |
||
763 | br_matrix34* mat; |
||
764 | LOG_TRACE("(%d)", pTime); |
||
765 | |||
766 | for (i = 0; i < COUNT_OF(gShrapnel); i++) { |
||
767 | mat = &gShrapnel[i].actor->t.t.mat; |
||
768 | if (gShrapnel_flags & (1 << i)) { |
||
769 | gShrapnel[i].age += GetReplayRate() * pTime; |
||
770 | DrMatrix34Rotate(mat, gShrapnel[i].age * BrDegreeToAngle(1), &gShrapnel[i].axis); |
||
771 | BrMatrix34PreShearX(mat, gShrapnel[i].shear1, gShrapnel[i].shear2); |
||
772 | } |
||
773 | } |
||
774 | } |
||
775 | |||
776 | // IDA: void __usercall MungeShrapnel(tU32 pTime@<EAX>) |
||
777 | void MungeShrapnel(tU32 pTime) { |
||
778 | br_vector3 disp; |
||
779 | int i; |
||
780 | br_matrix34* mat; |
||
781 | br_scalar ts; |
||
782 | LOG_TRACE("(%d)", pTime); |
||
783 | |||
784 | MungeSmokeColumn(pTime); |
||
785 | MungeSplash(pTime); |
||
786 | |||
787 | if (gAction_replay_mode) { |
||
788 | ReplayShrapnel(pTime); |
||
789 | return; |
||
790 | } |
||
791 | |||
792 | StartPipingSession(ePipe_chunk_shrapnel); |
||
793 | for (i = 0; i < COUNT_OF(gShrapnel); i++) { |
||
794 | mat = &gShrapnel[i].actor->t.t.mat; |
||
795 | if (((1u << i) & gShrapnel_flags) == 0) { |
||
796 | continue; |
||
797 | } |
||
798 | if (gShrapnel[i].age == -1) { |
||
799 | KillShrapnel(i); |
||
800 | } else { |
||
801 | if (gShrapnel[i].time_sync) { |
||
802 | BrVector3Scale(&disp, &gShrapnel[i].v, gShrapnel[i].time_sync / 1000.0f); |
||
803 | gShrapnel[i].time_sync = 0; |
||
804 | } else { |
||
805 | BrVector3Scale(&disp, &gShrapnel[i].v, pTime / 1000.0f); |
||
806 | gShrapnel[i].age += pTime; |
||
807 | } |
||
808 | mat->m[3][0] = mat->m[3][0] + disp.v[0]; |
||
809 | mat->m[3][1] = mat->m[3][1] + disp.v[1]; |
||
810 | mat->m[3][2] = mat->m[3][2] + disp.v[2]; |
||
811 | gShrapnel[i].v.v[1] -= (10 * pTime) * 0.00014492753f; |
||
812 | DrMatrix34Rotate(mat, 182 * gShrapnel[i].age, &gShrapnel[i].axis); |
||
813 | BrMatrix34PreShearX(mat, gShrapnel[i].shear1, gShrapnel[i].shear2); |
||
814 | // bug: should this be using "&gShrapnel[i].v"?? |
||
815 | ts = 1.0 - BrVector3Length(&gSparks[i].v) / 1.4 * pTime / 1000.0; |
||
816 | if (ts < 0.1) { |
||
817 | ts = (br_scalar) 0.1; // Pierre-Marie Baty -- added type cast |
||
818 | } |
||
819 | BrVector3Scale(&gShrapnel[i].v, &gShrapnel[i].v, ts); |
||
820 | AddShrapnelToPipingSession(i + ((gShrapnel[i].age > 1000 || gShrapnel[i].age < pTime) << 15), (br_vector3*)mat->m[3], gShrapnel[i].age - pTime, gShrapnel[i].actor->material); |
||
821 | if (gShrapnel[i].age > 1000) { |
||
822 | gShrapnel[i].age = -1; |
||
823 | } |
||
824 | } |
||
825 | } |
||
826 | EndPipingSession(); |
||
827 | } |
||
828 | |||
829 | // IDA: void __usercall DrMatrix34Rotate(br_matrix34 *mat@<EAX>, br_angle r@<EDX>, br_vector3 *a@<EBX>) |
||
830 | void DrMatrix34Rotate(br_matrix34* mat, br_angle r, br_vector3* a) { |
||
831 | br_scalar t; |
||
832 | br_scalar s; |
||
833 | br_scalar c; |
||
834 | br_scalar txy; |
||
835 | br_scalar txz; |
||
836 | br_scalar tyz; |
||
837 | br_scalar sx; |
||
838 | br_scalar sy; |
||
839 | br_scalar sz; |
||
840 | LOG_TRACE("(%p, %d, %p)", mat, r, a); |
||
841 | |||
842 | s = FastScalarSinAngle(r); |
||
843 | c = FastScalarCosAngle(r); |
||
844 | t = 1.0f - c; |
||
845 | txy = t * a->v[0] * a->v[1]; |
||
846 | txz = t * a->v[0] * a->v[2]; |
||
847 | tyz = t * a->v[1] * a->v[2]; |
||
848 | sx = a->v[0] * s; |
||
849 | sy = a->v[1] * s; |
||
850 | sz = a->v[2] * s; |
||
851 | mat->m[0][0] = a->v[0] * a->v[0] * t + c; |
||
852 | mat->m[0][1] = sz + txy; |
||
853 | mat->m[0][2] = txz - sy; |
||
854 | mat->m[1][0] = txy - sz; |
||
855 | mat->m[1][1] = a->v[1] * a->v[1] * t + c; |
||
856 | mat->m[1][2] = sx + tyz; |
||
857 | mat->m[2][0] = sy + txz; |
||
858 | mat->m[2][1] = tyz - sx; |
||
859 | mat->m[2][2] = a->v[2] * a->v[2] * t + c; |
||
860 | } |
||
861 | |||
862 | // IDA: void __usercall SmokeLine(int l@<EAX>, int x@<EDX>, br_scalar zbuff, int r_squared, tU8 *scr_ptr, tU16 *depth_ptr, tU8 *shade_ptr, br_scalar r_multiplier, br_scalar z_multiplier, br_scalar shade_offset) |
||
863 | void SmokeLine(int l, int x, br_scalar zbuff, int r_squared, tU8* scr_ptr, tU16* depth_ptr, tU8* shade_ptr, br_scalar r_multiplier, br_scalar z_multiplier, br_scalar shade_offset) { |
||
864 | int i; |
||
865 | int offset; /* Added by dethrace. */ |
||
866 | int r_multiplier_int; |
||
867 | int shade_offset_int; |
||
868 | tU16 z; |
||
869 | LOG_TRACE("(%d, %d, %f, %d, %p, %p, %p, %f, %f, %f)", l, x, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
870 | |||
871 | scr_ptr += gOffset; |
||
872 | if (gProgram_state.cockpit_on) { |
||
873 | depth_ptr += gOffset; |
||
874 | } |
||
875 | z = (1.f - zbuff) * 32768.0f; |
||
876 | r_multiplier_int = r_multiplier * 65536.0f; |
||
877 | shade_offset_int = shade_offset * 65536.0f; |
||
878 | |||
879 | for (i = 0; i < l; i++) { |
||
880 | if (*depth_ptr > z) { |
||
881 | offset = ((shade_offset_int - r_squared * r_multiplier_int) >> 8) & 0xffffff00; |
||
882 | #if defined(DETHRACE_FIX_BUGS) |
||
883 | /* Prevent buffer underflows by capping negative offsets. */ |
||
884 | offset = MAX(0, offset); |
||
885 | #endif |
||
886 | *scr_ptr = shade_ptr[*scr_ptr + offset]; |
||
887 | } |
||
888 | r_multiplier = x + r_squared; |
||
889 | scr_ptr++; |
||
890 | x++; |
||
891 | depth_ptr++; |
||
892 | r_squared = x + r_multiplier; |
||
893 | } |
||
894 | } |
||
895 | |||
896 | // IDA: void __usercall SmokeCircle(br_vector3 *o@<EAX>, br_scalar r, br_scalar extra_z, br_scalar strength, br_scalar pAspect, br_pixelmap *pRender_screen, br_pixelmap *pDepth_buffer, br_pixelmap *pShade_table) |
||
897 | void SmokeCircle(br_vector3* o, br_scalar r, br_scalar extra_z, br_scalar strength, br_scalar pAspect, br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_pixelmap* pShade_table) { |
||
898 | tU8* scr_ptr; |
||
899 | tU16* depth_ptr; |
||
900 | tU8* shade_ptr; |
||
901 | tU8* osp; |
||
902 | tU16* odp; |
||
903 | int ox; |
||
904 | int oy; |
||
905 | //int i; // Pierre-Marie Baty -- unused variable |
||
906 | int r_squared; |
||
907 | int max_r_squared; |
||
908 | int l; |
||
909 | int l2; |
||
910 | int x; |
||
911 | int x2; |
||
912 | //int sx; // Pierre-Marie Baty -- unused variable |
||
913 | int y; |
||
914 | int inc; |
||
915 | int y_limit; |
||
916 | int max_x; |
||
917 | int min_x; |
||
918 | br_scalar shade_offset; |
||
919 | br_scalar r_multiplier; |
||
920 | br_scalar ry; |
||
921 | br_scalar z_multiplier; |
||
922 | br_scalar zbuff; |
||
923 | br_scalar aspect_squared; |
||
924 | void (*line)(int, int, br_scalar, int, tU8*, tU16*, tU8*, br_scalar, br_scalar, br_scalar); |
||
925 | LOG_TRACE("(%p, %f, %f, %f, %f, %p, %p, %p)", o, r, extra_z, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table); |
||
926 | |||
927 | line = SmokeLine; |
||
928 | ox = pRender_screen->width / 2 + o->v[0]; |
||
929 | oy = pRender_screen->height / 2 + o->v[1]; |
||
930 | max_r_squared = r * r; |
||
931 | zbuff = o->v[2]; |
||
932 | aspect_squared = pAspect * pAspect; |
||
933 | if (pRender_screen->width / 4 <= r |
||
934 | || pRender_screen->width <= ox - r |
||
935 | || ox + r < 0.0f) { |
||
936 | return; |
||
937 | } |
||
938 | shade_ptr = (tU8*)pShade_table->pixels + pShade_table->row_bytes * (pShade_table->base_y + 1); |
||
939 | shade_offset = strength * 14.99f; |
||
940 | r_multiplier = shade_offset / (double)max_r_squared; |
||
941 | z_multiplier = extra_z / (double)max_r_squared; |
||
942 | max_x = pRender_screen->width - ox - 1; |
||
943 | min_x = -ox; |
||
944 | ry = r / pAspect; |
||
945 | l = pRender_screen->height - oy - 1; |
||
946 | scr_ptr = pRender_screen->pixels; |
||
947 | scr_ptr += pRender_screen->base_x + pRender_screen->base_y * pRender_screen->row_bytes + ox + l * pRender_screen->row_bytes; |
||
948 | depth_ptr = (tU16*)pDepth_buffer->pixels + ox + l * (pDepth_buffer->row_bytes / 2); |
||
949 | osp = scr_ptr; |
||
950 | odp = depth_ptr; |
||
951 | if (pRender_screen->height > oy && oy + ry >= 0.0) { |
||
952 | r_squared = r * r; |
||
953 | inc = -r; |
||
954 | y = 0; |
||
955 | y_limit = ry; |
||
956 | if (oy < 0) { |
||
957 | y = -oy; |
||
958 | r_squared = (y * y) * aspect_squared; |
||
959 | scr_ptr += oy * pRender_screen->row_bytes; |
||
960 | depth_ptr += oy * (pDepth_buffer->row_bytes / 2); |
||
961 | inc = -sqrtf(max_r_squared - r_squared); |
||
962 | r_squared += inc * inc; |
||
963 | } |
||
964 | if (pRender_screen->height < oy + ry) { |
||
965 | y_limit = pRender_screen->height - oy - 1; |
||
966 | } |
||
967 | l = -2 * inc; |
||
968 | scr_ptr += inc; |
||
969 | depth_ptr += inc; |
||
970 | gOffset = 0; |
||
971 | while (1) { |
||
972 | |||
973 | x = inc + gOffset; |
||
974 | if (min_x <= inc + gOffset && l + x - 1 <= max_x) { |
||
975 | line(l, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
976 | } else { |
||
977 | if (max_x < x || l + x < min_x) { |
||
978 | break; |
||
979 | } |
||
980 | x2 = l; |
||
981 | if (l + x - 1 - max_x > 0) { |
||
982 | x2 = max_x - (x - 1); |
||
983 | } |
||
984 | if (min_x - x <= 0) { |
||
985 | line(x2, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
986 | } else { |
||
987 | line(x2 - (min_x - x), min_x - x + inc, zbuff, y * y + (min_x - x + inc) * (min_x - x + inc), &scr_ptr[min_x - x], &depth_ptr[min_x - x], shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
988 | } |
||
989 | } |
||
990 | if (y_limit <= y) { |
||
991 | break; |
||
992 | } |
||
993 | y++; |
||
994 | scr_ptr -= pRender_screen->row_bytes; |
||
995 | depth_ptr -= pDepth_buffer->row_bytes / 2; |
||
996 | for (r_squared += (2 * y - 1) * aspect_squared; max_r_squared < r_squared && inc < 0; r_squared += 2 * inc - 1) { |
||
997 | inc++; |
||
998 | scr_ptr++; |
||
999 | depth_ptr++; |
||
1000 | l -= 2; |
||
1001 | } |
||
1002 | gOffset += IRandomBetween(-1, 1); |
||
1003 | if (gOffset > r / 5.f) { |
||
1004 | gOffset = r / 5.f; |
||
1005 | } |
||
1006 | if (gOffset < -(r / 5.f)) { |
||
1007 | gOffset = -(r / 5.f); |
||
1008 | } |
||
1009 | } |
||
1010 | } |
||
1011 | if (pAspect < 1.0) { |
||
1012 | aspect_squared = 9.f; |
||
1013 | ry = r / 3.f; |
||
1014 | } |
||
1015 | if (oy > 0 && oy <= pRender_screen->height + ry - 2.f) { |
||
1016 | r_squared = (r * r); |
||
1017 | inc = -r; |
||
1018 | y = 0; |
||
1019 | scr_ptr = osp; |
||
1020 | depth_ptr = odp; |
||
1021 | y_limit = ry; |
||
1022 | if (pRender_screen->height < oy) { |
||
1023 | l2 = oy - pRender_screen->height; |
||
1024 | y = pRender_screen->height - oy; |
||
1025 | r_squared = y * y * aspect_squared; |
||
1026 | scr_ptr = &osp[l2 * pRender_screen->row_bytes]; |
||
1027 | depth_ptr = &odp[l2 * (pDepth_buffer->row_bytes / 2)]; |
||
1028 | inc = -sqrtf(max_r_squared - r_squared); |
||
1029 | r_squared += inc * inc; |
||
1030 | } |
||
1031 | if (oy - ry < 0.f) { |
||
1032 | y_limit = oy; |
||
1033 | } |
||
1034 | l = -2 * inc; |
||
1035 | scr_ptr += inc; |
||
1036 | depth_ptr += inc; |
||
1037 | gOffset = 0; |
||
1038 | do { |
||
1039 | y--; |
||
1040 | scr_ptr += pRender_screen->row_bytes; |
||
1041 | depth_ptr += pDepth_buffer->row_bytes / 2; |
||
1042 | for (r_squared -= (2 * y - 1) * aspect_squared; max_r_squared < r_squared && inc < 0; r_squared += 2 * inc - 1) { |
||
1043 | inc++; |
||
1044 | scr_ptr++; |
||
1045 | depth_ptr++; |
||
1046 | l -= 2; |
||
1047 | } |
||
1048 | x = inc + gOffset; |
||
1049 | if (min_x <= inc + gOffset && l + x - 1 <= max_x) { |
||
1050 | line(l, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
1051 | } else { |
||
1052 | if (max_x < x || l + x < min_x) { |
||
1053 | return; |
||
1054 | } |
||
1055 | x2 = l; |
||
1056 | if (l + x - 1 - max_x > 0) { |
||
1057 | x2 = max_x - (x - 1); |
||
1058 | } |
||
1059 | if (min_x - x <= 0) { |
||
1060 | line(x2, inc, zbuff, r_squared, scr_ptr, depth_ptr, shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
1061 | } else { |
||
1062 | line(x2 - (min_x - x), min_x - x + inc, zbuff, y * y + (min_x - x + inc) * (min_x - x + inc), &scr_ptr[min_x - x], &depth_ptr[min_x - x], shade_ptr, r_multiplier, z_multiplier, shade_offset); |
||
1063 | } |
||
1064 | } |
||
1065 | gOffset += IRandomBetween(-1, 1); |
||
1066 | if (gOffset > r / 5.0) { |
||
1067 | gOffset = r / 5.0; |
||
1068 | } |
||
1069 | if (gOffset < -(r / 5.0)) { |
||
1070 | gOffset = -r / 5.0; |
||
1071 | } |
||
1072 | } while (-y < y_limit); |
||
1073 | } |
||
1074 | } |
||
1075 | |||
1076 | // IDA: int __cdecl CmpSmokeZ(void *p1, void *p2) |
||
1077 | int CmpSmokeZ(void* p1, void* p2) { |
||
1078 | //tBRender_smoke** a; // Pierre-Marie Baty -- unused variable |
||
1079 | //tBRender_smoke** b; // Pierre-Marie Baty -- unused variable |
||
1080 | LOG_TRACE("(%p, %p)", p1, p2); |
||
1081 | NOT_IMPLEMENTED(); |
||
1082 | } |
||
1083 | |||
1084 | // IDA: void __cdecl RenderRecordedSmokeCircles() |
||
1085 | void RenderRecordedSmokeCircles(void) { |
||
1086 | //int i; // Pierre-Marie Baty -- unused variable |
||
1087 | //tBRender_smoke* smoke; // Pierre-Marie Baty -- unused variable |
||
1088 | //tU8 red; // Pierre-Marie Baty -- unused variable |
||
1089 | //tU8 grn; // Pierre-Marie Baty -- unused variable |
||
1090 | //tU8 blu; // Pierre-Marie Baty -- unused variable |
||
1091 | LOG_TRACE("()"); |
||
1092 | NOT_IMPLEMENTED(); |
||
1093 | } |
||
1094 | |||
1095 | // IDA: void __usercall RecordSmokeCircle(br_vector3 *pCent@<EAX>, br_scalar pR, br_scalar pStrength, br_pixelmap *pShade, br_scalar pAspect) |
||
1096 | void RecordSmokeCircle(br_vector3* pCent, br_scalar pR, br_scalar pStrength, br_pixelmap* pShade, br_scalar pAspect) { |
||
1097 | //tU8 shade_index; // Pierre-Marie Baty -- unused variable |
||
1098 | //br_colour shade_rgb; // Pierre-Marie Baty -- unused variable |
||
1099 | LOG_TRACE("(%p, %f, %f, %p, %f)", pCent, pR, pStrength, pShade, pAspect); |
||
1100 | NOT_IMPLEMENTED(); |
||
1101 | } |
||
1102 | |||
1103 | // IDA: void __usercall SmokeCircle3D(br_vector3 *o@<EAX>, br_scalar r, br_scalar strength, br_scalar pAspect, br_pixelmap *pRender_screen, br_pixelmap *pDepth_buffer, br_pixelmap *pShade_table, br_actor *pCam) |
||
1104 | void SmokeCircle3D(br_vector3* o, br_scalar r, br_scalar strength, br_scalar pAspect, br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_pixelmap* pShade_table, br_actor* pCam) { |
||
1105 | br_vector3 tv; |
||
1106 | br_vector3 p; |
||
1107 | br_vector4 o2; |
||
1108 | br_camera* cam; |
||
1109 | int scaled_r; |
||
1110 | br_scalar extra_z; |
||
1111 | LOG_TRACE("(%p, %f, %f, %f, %p, %p, %p, %p)", o, r, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table, pCam); |
||
1112 | |||
1113 | cam = pCam->type_data; |
||
1114 | srand(o->v[2] * 16777216.0f + o->v[1] * 65536.0f + o->v[0] * 256.0f + r); |
||
1115 | BrVector3Sub(&tv, o, (br_vector3*)gCamera_to_world.m[3]); |
||
1116 | BrMatrix34TApplyV(&p, &tv, &gCamera_to_world); |
||
1117 | |||
1118 | if (-p.v[2] >= cam->hither_z && -p.v[2] <= cam->yon_z) { |
||
1119 | scaled_r = gCameraToScreen.m[0][0] * r / -p.v[2]; |
||
1120 | extra_z = gCameraToScreen.m[3][2] * r / (p.v[2] * p.v[2]); |
||
1121 | BrMatrix4ApplyP(&o2, &p, &gCameraToScreen); |
||
1122 | BrVector3InvScale(&p, &o2, o2.v[3]); |
||
1123 | SmokeCircle(&p, (br_scalar)scaled_r, extra_z, strength, pAspect, pRender_screen, pDepth_buffer, pShade_table); |
||
1124 | } |
||
1125 | } |
||
1126 | |||
1127 | // IDA: void __usercall ReplaySmoke(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>) |
||
1128 | void ReplaySmoke(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_actor* pCamera) { |
||
1129 | br_scalar aspect; |
||
1130 | int i; |
||
1131 | LOG_TRACE("(%p, %p, %p)", pRender_screen, pDepth_buffer, pCamera); |
||
1132 | |||
1133 | for (i = 0; i < COUNT_OF(gSmoke_column); i++) { |
||
1134 | if (gSmoke_flags & (1 << i)) { |
||
1135 | aspect = 1.f + (gSmoke[i].radius - .05f) / .25f * .5f; |
||
1136 | if (gSmoke[i].type & 0x10) { |
||
1137 | SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius / aspect, gSmoke[i].strength, 1.f, |
||
1138 | pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera); |
||
1139 | } else { |
||
1140 | SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength, aspect, |
||
1141 | pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera); |
||
1142 | } |
||
1143 | } |
||
1144 | } |
||
1145 | } |
||
1146 | |||
1147 | // IDA: void __usercall GenerateContinuousSmoke(tCar_spec *pCar@<EAX>, int wheel@<EDX>, tU32 pTime@<EBX>) |
||
1148 | void GenerateContinuousSmoke(tCar_spec* pCar, int wheel, tU32 pTime) { |
||
1149 | br_vector3 pos; |
||
1150 | br_vector3 v; |
||
1151 | br_vector3 vcs; |
||
1152 | br_vector3 tv; |
||
1153 | br_scalar decay_factor; |
||
1154 | br_scalar ts; |
||
1155 | br_scalar alpha; |
||
1156 | br_scalar beta; |
||
1157 | int colour; |
||
1158 | LOG_TRACE("(%p, %d, %d)", pCar, wheel, pTime); |
||
1159 | |||
1160 | if (pCar->dust_time[wheel] > (int) pTime) { // Pierre-Marie Baty -- added type cast |
||
1161 | pCar->dust_time[wheel] -= pTime; |
||
1162 | return; |
||
1163 | } |
||
1164 | pCar->dust_time[wheel] += IRandomBetween(200, 400) - pTime; |
||
1165 | if (pCar->dust_time[wheel] < 0) { |
||
1166 | pCar->dust_time[wheel] = 0; |
||
1167 | } |
||
1168 | BrVector3Cross(&tv, &pCar->omega, &pCar->wpos[wheel]); |
||
1169 | BrVector3Scale(&vcs, &pCar->velocity_car_space, WORLD_SCALE * 1000.0f); |
||
1170 | BrVector3Accumulate(&vcs, &tv); |
||
1171 | ts = BrVector3LengthSquared(&vcs); |
||
1172 | if (ts < 25.0f) { |
||
1173 | return; |
||
1174 | } |
||
1175 | decay_factor = sqrtf(ts) / 25.0f; |
||
1176 | if (decay_factor > 1.0f) { |
||
1177 | decay_factor = 1.0f; |
||
1178 | } |
||
1179 | BrVector3InvScale(&tv, &pCar->wpos[wheel], WORLD_SCALE); |
||
1180 | tv.v[1] -= pCar->oldd[wheel] / WORLD_SCALE; |
||
1181 | |||
1182 | alpha = -1000.0f; |
||
1183 | if (vcs.v[2] > 0.0f) { |
||
1184 | alpha = (pCar->bounds[0].min.v[2] - tv.v[2]) / vcs.v[2]; |
||
1185 | } else if (vcs.v[2] < 0.0f) { |
||
1186 | alpha = (pCar->bounds[0].max.v[2] - tv.v[2]) / vcs.v[2]; |
||
1187 | } |
||
1188 | |||
1189 | beta = -1000.0f; |
||
1190 | if (vcs.v[0] > 0.0f) { |
||
1191 | beta = (pCar->bounds[0].min.v[0] - tv.v[0]) / vcs.v[0]; |
||
1192 | } else if (vcs.v[0] < 0.0f) { |
||
1193 | beta = (pCar->bounds[0].max.v[0] - tv.v[0]) / vcs.v[0]; |
||
1194 | } |
||
1195 | |||
1196 | ts = MAX(alpha, beta); |
||
1197 | BrVector3Scale(&pos, &vcs, ts); |
||
1198 | BrVector3Accumulate(&tv, &pos); |
||
1199 | BrMatrix34ApplyP(&pos, &tv, &pCar->car_master_actor->t.t.mat); |
||
1200 | BrMatrix34ApplyV(&v, &vcs, &pCar->car_master_actor->t.t.mat); |
||
1201 | |||
1202 | colour = gDust_rotate + gCurrent_race.material_modifiers[pCar->material_index[wheel]].smoke_type - 2; |
||
1203 | while (colour >= gNum_dust_tables) { |
||
1204 | colour -= gNum_dust_tables; |
||
1205 | } |
||
1206 | CreatePuffOfSmoke(&pos, &v, decay_factor, decay_factor * 2, colour + 8, pCar); |
||
1207 | } |
||
1208 | |||
1209 | // IDA: void __cdecl DustRotate() |
||
1210 | void DustRotate(void) { |
||
1211 | LOG_TRACE("()"); |
||
18 | pmbaty | 1212 | |
1213 | gDust_rotate += 1; |
||
1214 | if (gDust_rotate >= gNum_dust_tables) { |
||
1215 | gDust_rotate = 0; |
||
1216 | } |
||
1217 | NewTextHeadupSlot(4, 0, 1000, -4, "Dust colour rotated"); |
||
1 | pmbaty | 1218 | } |
1219 | |||
1220 | // IDA: void __usercall RenderSmoke(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>, br_matrix34 *pCamera_to_world@<ECX>, tU32 pTime) |
||
1221 | void RenderSmoke(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_actor* pCamera, br_matrix34* pCamera_to_world, tU32 pTime) { |
||
1222 | int i; |
||
1223 | int j; |
||
1224 | br_vector3 tv; |
||
1225 | br_scalar aspect; |
||
1226 | br_scalar ts; |
||
1227 | tU32 seed; |
||
1228 | tU32 not_lonely; |
||
1229 | LOG_TRACE("(%p, %p, %p, %p, %d)", pRender_screen, pDepth_buffer, pCamera, pCamera_to_world, pTime); |
||
1230 | |||
1231 | not_lonely = 0; |
||
1232 | DrawTheGlow(pRender_screen, pDepth_buffer, pCamera); |
||
1233 | |||
1234 | if (gSmoke_flags != 0) { |
||
1235 | seed = rand(); |
||
1236 | if (gAction_replay_mode) { |
||
1237 | ReplaySmoke(pRender_screen, pDepth_buffer, pCamera); |
||
1238 | srand(seed); |
||
1239 | } else { |
||
1240 | StartPipingSession(ePipe_chunk_smoke); |
||
1241 | for (i = 0; i < COUNT_OF(gSmoke); i++) { |
||
1242 | if ((gSmoke_flags & (1u << i)) != 0) { |
||
1243 | if (gSmoke[i].strength > 0.0) { |
||
1244 | if (gSmoke[i].time_sync) { |
||
1245 | BrVector3Scale(&tv, &gSmoke[i].v, gSmoke[i].time_sync / 1000.0); |
||
1246 | gSmoke[i].time_sync = 0; |
||
1247 | } else { |
||
1248 | BrVector3Scale(&tv, &gSmoke[i].v, pTime / 1000.0); |
||
1249 | } |
||
1250 | BrVector3Accumulate(&gSmoke[i].pos, &tv); |
||
1251 | } else { |
||
1252 | gSmoke_flags &= ~(1u << i); |
||
1253 | } |
||
1254 | } |
||
1255 | } |
||
1256 | for (i = 0; i < COUNT_OF(gSmoke); i++) { |
||
1257 | if ((gSmoke_flags & (1u << i)) != 0) { |
||
1258 | if ((gSmoke[i].type & 0xf) == 7) { |
||
1259 | not_lonely |= 1u << i; |
||
1260 | } else if ((not_lonely & (1u << i)) == 0) { |
||
1261 | for (j = i + 1; j < COUNT_OF(gSmoke); j++) { |
||
1262 | if ((gSmoke_flags & (1u << j)) != 0) { |
||
1263 | BrVector3Sub(&tv, &gSmoke[i].pos, &gSmoke[i].pos); |
||
1264 | ts = BrVector3LengthSquared(&tv); |
||
1265 | if ((gSmoke[i].radius + gSmoke[j].radius) * (gSmoke[i].radius + gSmoke[j].radius) > ts) { |
||
1266 | not_lonely |= (1u << j) | (1u << i); |
||
1267 | break; |
||
1268 | } |
||
1269 | } |
||
1270 | } |
||
1271 | } |
||
1272 | if (((1u << i) & not_lonely) == 0) { |
||
1273 | gSmoke[i].strength = gSmoke[i].strength / 2.0; |
||
1274 | } |
||
1275 | aspect = (gSmoke[i].radius - 0.05f) / 0.25f * 0.5f + 1.0f; |
||
1276 | if ((gSmoke[i].type & 0x10) != 0) { |
||
1277 | SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius / aspect, gSmoke[i].strength, 1.0, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera); |
||
1278 | } else { |
||
1279 | SmokeCircle3D(&gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength, aspect, pRender_screen, pDepth_buffer, gShade_list[gSmoke[i].type & 0xf], pCamera); |
||
1280 | } |
||
1281 | if (gSmoke[i].pipe_me) { |
||
1282 | AddSmokeToPipingSession(i, gSmoke[i].type, &gSmoke[i].pos, gSmoke[i].radius, gSmoke[i].strength); |
||
1283 | } |
||
1284 | gSmoke[i].radius = (double)pTime / 1000.0 * gSmoke[i].strength * 0.5 + gSmoke[i].radius; |
||
1285 | gSmoke[i].strength = gSmoke[i].strength - (double)pTime * gSmoke[i].decay_factor / 1000.0; |
||
1286 | if (gSmoke[i].radius > 0.3f) { |
||
1287 | gSmoke[i].radius = 0.3f; |
||
1288 | } |
||
1289 | if (gSmoke[i].strength > 0.0) { |
||
1290 | ts = 1.0f - (double)pTime * 0.002f; |
||
1291 | if (ts < 0.5f) { |
||
1292 | ts = 0.5f; |
||
1293 | } |
||
1294 | BrVector3Scale(&gSmoke[i].v, &gSmoke[i].v, ts); |
||
1295 | if (fabs(gSmoke[i].v.v[1]) < 0.43478259f && (gSmoke[i].type & 0xFu) < 7) { |
||
1296 | if (gSmoke[i].v.v[1] >= 0.0) { |
||
1297 | gSmoke[i].v.v[1] = 0.43478259f; |
||
1298 | } else { |
||
1299 | gSmoke[i].v.v[1] += 0.43478259f; |
||
1300 | } |
||
1301 | } |
||
1302 | } else { |
||
1303 | gSmoke_flags &= ~(1u << i); |
||
1304 | } |
||
1305 | } |
||
1306 | } |
||
1307 | EndPipingSession(); |
||
1308 | srand(seed); |
||
1309 | } |
||
1310 | } |
||
1311 | } |
||
1312 | |||
1313 | // IDA: void __usercall CreatePuffOfSmoke(br_vector3 *pos@<EAX>, br_vector3 *v@<EDX>, br_scalar strength, br_scalar pDecay_factor, int pType, tCar_spec *pC) |
||
1314 | void CreatePuffOfSmoke(br_vector3* pos, br_vector3* v, br_scalar strength, br_scalar pDecay_factor, int pType, tCar_spec* pC) { |
||
1315 | br_vector3 tv; |
||
1316 | //int pipe_me; // Pierre-Marie Baty -- unused variable |
||
1317 | LOG_TRACE("(%p, %p, %f, %f, %d, %p)", pos, v, strength, pDecay_factor, pType, pC); |
||
1318 | |||
1319 | if (!gSmoke_on) { |
||
1320 | return; |
||
1321 | } |
||
1322 | // if we are too far away from the current car... |
||
1323 | BrVector3Sub(&tv, pos, &gProgram_state.current_car.pos); |
||
1324 | if (BrVector3LengthSquared(&tv) > 625.0) { |
||
1325 | // check the distance from the car we are viewing and if it is too far away also, just return |
||
1326 | BrVector3Sub(&tv, pos, &gCar_to_view->pos); |
||
1327 | if (&gProgram_state.current_car != gCar_to_view && BrVector3LengthSquared(&tv) > 625.0) { |
||
1328 | return; |
||
1329 | } |
||
1330 | } |
||
1331 | |||
1332 | BrVector3InvScale(&gSmoke[gSmoke_num].v, v, WORLD_SCALE); |
||
1333 | gSmoke[gSmoke_num].v.v[1] += (1.0f / WORLD_SCALE); |
||
1334 | BrVector3Copy(&gSmoke[gSmoke_num].pos, pos); |
||
1335 | gSmoke[gSmoke_num].radius = 0.05f; |
||
1336 | if ((pType & 0xF) == 7) { |
||
1337 | gSmoke[gSmoke_num].radius *= 2.0f; |
||
1338 | } else { |
||
1339 | gSmoke[gSmoke_num].pos.v[1] += (br_scalar) 0.04; // Pierre-Marie Baty -- added type cast |
||
1340 | } |
||
1341 | gSmoke[gSmoke_num].pos.v[1] += (br_scalar) 0.04; // Pierre-Marie Baty -- added type cast |
||
1342 | if (strength > 1.0) { |
||
1343 | strength = 1.0; |
||
1344 | } |
||
1345 | gSmoke[gSmoke_num].strength = strength; |
||
1346 | gSmoke_flags |= 1u << gSmoke_num; |
||
1347 | gSmoke[gSmoke_num].time_sync = gMechanics_time_sync; |
||
1348 | gSmoke[gSmoke_num].type = pType; |
||
1349 | gSmoke[gSmoke_num].decay_factor = pDecay_factor; |
||
1350 | gSmoke[gSmoke_num].pipe_me = 1; |
||
1351 | gSmoke_num++; |
||
1352 | if (gSmoke_num >= COUNT_OF(gSmoke)) { |
||
1353 | gSmoke_num = 0; |
||
1354 | } |
||
1355 | } |
||
1356 | |||
1357 | // IDA: void __cdecl ResetSmoke() |
||
1358 | void ResetSmoke(void) { |
||
1359 | LOG_TRACE("()"); |
||
1360 | |||
1361 | gSmoke_flags = 0; |
||
1362 | ; |
||
1363 | } |
||
1364 | |||
1365 | // IDA: void __usercall AdjustSmoke(int pIndex@<EAX>, tU8 pType@<EDX>, br_vector3 *pPos@<EBX>, br_scalar pRadius, br_scalar pStrength) |
||
1366 | void AdjustSmoke(int pIndex, tU8 pType, br_vector3* pPos, br_scalar pRadius, br_scalar pStrength) { |
||
1367 | LOG_TRACE("(%d, %d, %p, %f, %f)", pIndex, pType, pPos, pRadius, pStrength); |
||
1368 | |||
1369 | gSmoke[pIndex].type = pType; |
||
1370 | gSmoke[pIndex].radius = pRadius; |
||
1371 | gSmoke[pIndex].strength = pStrength; |
||
1372 | BrVector3Copy(&gSmoke[pIndex].pos, pPos); |
||
1373 | gSmoke_flags |= 1 << pIndex; |
||
1374 | } |
||
1375 | |||
1376 | // IDA: void __cdecl ActorError() |
||
1377 | void ActorError(void) { |
||
1378 | LOG_TRACE("()"); |
||
1379 | } |
||
1380 | |||
1381 | // IDA: void __usercall AdjustSmokeColumn(int pIndex@<EAX>, tCar_spec *pCar@<EDX>, int pVertex@<EBX>, int pColour@<ECX>) |
||
1382 | void AdjustSmokeColumn(int pIndex, tCar_spec* pCar, int pVertex, int pColour) { |
||
1383 | int i; |
||
1384 | //br_actor* actor; // Pierre-Marie Baty -- unused variable |
||
1385 | LOG_TRACE("(%d, %p, %d, %d)", pIndex, pCar, pVertex, pColour); |
||
1386 | |||
1387 | gColumn_flags ^= 1 << pIndex; |
||
1388 | gSmoke_column[pIndex].car = pCar; |
||
1389 | gSmoke_column[pIndex].vertex_index = pVertex; |
||
1390 | gSmoke_column[pIndex].colour = pColour; |
||
1391 | for (i = 0; i < COUNT_OF(gSmoke_column->frame_count); i++) { |
||
1392 | gSmoke_column[pIndex].frame_count[i] = 100; |
||
1393 | } |
||
1394 | if (pColour == 0) { |
||
1395 | if ((gColumn_flags & (1 << pIndex)) != 0) { |
||
1396 | if (gSmoke_column[pIndex].flame_actor->depth != 0) { |
||
1397 | ActorError(); |
||
1398 | } |
||
1399 | BrActorAdd(gNon_track_actor, gSmoke_column[pIndex].flame_actor); |
||
1400 | } else { |
||
1401 | if (gSmoke_column[pIndex].flame_actor->depth == 0) { |
||
1402 | ActorError(); |
||
1403 | } |
||
1404 | BrActorRemove(gSmoke_column[pIndex].flame_actor); |
||
1405 | } |
||
1406 | } |
||
1407 | } |
||
1408 | |||
1409 | // IDA: void __usercall CreateSmokeColumn(tCar_spec *pCar@<EAX>, int pColour@<EDX>, int pVertex_index@<EBX>, tU32 pLifetime@<ECX>) |
||
1410 | void CreateSmokeColumn(tCar_spec* pCar, int pColour, int pVertex_index, tU32 pLifetime) { |
||
1411 | int i; |
||
1412 | br_actor* actor; |
||
1413 | tSmoke_column* col; |
||
1414 | LOG_TRACE("(%p, %d, %d, %d)", pCar, pColour, pVertex_index, pLifetime); |
||
1415 | |||
1416 | col = &gSmoke_column[gNext_column]; |
||
1417 | if (pCar->last_special_volume != NULL && pCar->last_special_volume->gravity_multiplier < 1.0f) { |
||
1418 | return; |
||
1419 | } |
||
1420 | SmudgeCar(pCar, pVertex_index); |
||
1421 | if (pCar->knackered) { |
||
1422 | SmudgeCar(pCar, pCar->fire_vertex[IRandomBetween(0, 11)]); |
||
1423 | } |
||
1424 | if (!gSmoke_on) { |
||
1425 | return; |
||
1426 | } |
||
1427 | if (((1u << gNext_column) & gColumn_flags) != 0) { |
||
1428 | if (gSmoke_column[gNext_column].car != NULL) { |
||
1429 | gSmoke_column[gNext_column].car->num_smoke_columns--; |
||
1430 | } |
||
1431 | StartPipingSession(ePipe_chunk_smoke_column); |
||
1432 | AddSmokeColumnToPipingSession(gNext_column, gSmoke_column[gNext_column].car, gSmoke_column[gNext_column].vertex_index, gSmoke_column[gNext_column].colour); |
||
1433 | EndPipingSession(); |
||
1434 | if (gSmoke_column[gNext_column].colour == 0) { |
||
1435 | StartPipingSession(ePipe_chunk_flame); |
||
1436 | actor = col->flame_actor->children; |
||
1437 | for (i = 0; i < 3; i++) { |
||
1438 | if (actor->type == BR_ACTOR_MODEL) { |
||
1439 | AddFlameToPipingSession(i + 16 * gNext_column, col->frame_count[i], col->scale_x[i], col->scale_y[i], col->offset_x[i], col->offset_z[i]); |
||
1440 | } |
||
1441 | actor->type = BR_ACTOR_NONE; |
||
1442 | actor = actor->next; |
||
1443 | } |
||
1444 | EndPipingSession(); |
||
1445 | } |
||
1446 | } |
||
1447 | if (pColour == 0 && (((1u << gNext_column) & gColumn_flags) == 0 || gSmoke_column[gNext_column].colour != 0)) { |
||
1448 | BrActorAdd(gNon_track_actor, gSmoke_column[gNext_column].flame_actor); |
||
1449 | } |
||
1450 | if (pColour != 0 && ((1u << gNext_column) & gColumn_flags) != 0 && gSmoke_column[gNext_column].colour == 0) { |
||
1451 | BrActorRemove(gSmoke_column[gNext_column].flame_actor); |
||
1452 | } |
||
1453 | StartPipingSession(ePipe_chunk_smoke_column); |
||
1454 | AddSmokeColumnToPipingSession(gNext_column, pCar, pVertex_index, pColour); |
||
1455 | EndPipingSession(); |
||
1456 | gSmoke_column[gNext_column].car = pCar; |
||
1457 | gSmoke_column[gNext_column].colour = pColour; |
||
1458 | gSmoke_column[gNext_column].lifetime = pLifetime; |
||
1459 | gSmoke_column[gNext_column].time = 0; |
||
1460 | gSmoke_column[gNext_column].smudge_timer = 1000; |
||
1461 | gSmoke_column[gNext_column].vertex_index = pVertex_index; |
||
1462 | gSmoke_column[gNext_column].upright = 1; |
||
1463 | gColumn_flags |= 1u << gNext_column; |
||
1464 | pCar->num_smoke_columns++; |
||
1465 | for (i = 0; i < COUNT_OF(gSmoke_column[gNext_column].frame_count); i++) { |
||
1466 | gSmoke_column[gNext_column].frame_count[i] = 100; |
||
1467 | } |
||
1468 | gNext_column++; |
||
1469 | if (gNext_column >= MAX_SMOKE_COLUMNS) { |
||
1470 | gNext_column = 0; |
||
1471 | } |
||
1472 | } |
||
1473 | |||
1474 | // IDA: void __cdecl GenerateSmokeShades() |
||
1475 | void GenerateSmokeShades(void) { |
||
1476 | static int rb = 0x00; |
||
1477 | static int gb = 0x00; |
||
1478 | static int bb = 0x00; |
||
1479 | static int rd = 0x40; |
||
1480 | static int gd = 0x40; |
||
1481 | static int bd = 0x40; |
||
1482 | static int rg = 0x80; |
||
1483 | static int gg = 0x80; |
||
1484 | static int bg = 0x80; |
||
1485 | LOG_TRACE("()"); |
||
1486 | |||
1487 | gBlack_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rb, gb, bb, .25f, .6f, .9f); |
||
1488 | gDark_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rd, gd, bd, .25f, .6f, .9f); |
||
1489 | gGrey_smoke_shade_table = GenerateShadeTable(16, gRender_palette, rg, gg, bg, .25f, .6f, .9f); |
||
1490 | gIt_shade_table = GenerateDarkenedShadeTable(16, gRender_palette, 0, 255, 254, .25f, .5f, .75f, .6f); |
||
1491 | |||
1492 | gShade_list[0] = gBlack_smoke_shade_table; |
||
1493 | gShade_list[1] = gDark_smoke_shade_table; |
||
1494 | gShade_list[2] = gGrey_smoke_shade_table; |
||
1495 | gShade_list[3] = gFog_shade_table; |
||
1496 | gShade_list[4] = gFog_shade_table; |
||
1497 | gShade_list[7] = gAcid_shade_table; |
||
1498 | } |
||
1499 | |||
1500 | // IDA: void __cdecl GenerateItFoxShadeTable() |
||
1501 | void GenerateItFoxShadeTable(void) { |
||
1502 | LOG_TRACE("()"); |
||
1503 | |||
1504 | if (gIt_shade_table == NULL) { |
||
1505 | gIt_shade_table = GenerateDarkenedShadeTable(16, gRender_palette, 0, 255, 254, .25f, .5f, .75f, .6f); |
||
1506 | } |
||
1507 | } |
||
1508 | |||
1509 | // IDA: void __usercall AdjustFlame(int pIndex@<EAX>, int pFrame_count@<EDX>, br_scalar pScale_x, br_scalar pScale_y, br_scalar pOffset_x, br_scalar pOffset_z) |
||
1510 | void AdjustFlame(int pIndex, int pFrame_count, br_scalar pScale_x, br_scalar pScale_y, br_scalar pOffset_x, br_scalar pOffset_z) { |
||
1511 | int i; |
||
1512 | int j; |
||
1513 | tSmoke_column* col; |
||
1514 | //br_actor* actor; // Pierre-Marie Baty -- unused variable |
||
1515 | LOG_TRACE("(%d, %d, %f, %f, %f, %f)", pIndex, pFrame_count, pScale_x, pScale_y, pOffset_x, pOffset_z); |
||
1516 | |||
1517 | i = pIndex >> 4; |
||
1518 | j = pIndex & 0xf; |
||
1519 | col = &gSmoke_column[i]; |
||
1520 | col->frame_count[j] = pFrame_count; |
||
1521 | col->scale_x[j] = pScale_x; |
||
1522 | col->scale_y[j] = pScale_y; |
||
1523 | col->offset_x[j] = pOffset_x; |
||
1524 | col->offset_z[j] = pOffset_z; |
||
1525 | } |
||
1526 | |||
1527 | // IDA: void __usercall ReplayFlame(tSmoke_column *col@<EAX>, br_actor *actor@<EDX>) |
||
1528 | void ReplayFlame(tSmoke_column* col, br_actor* actor) { |
||
1529 | int i; |
||
1530 | LOG_TRACE("(%p, %p)", col, actor); |
||
1531 | |||
1532 | for (i = 0; i < COUNT_OF(col->frame_count); i++, actor = actor->next) { |
||
1533 | col->frame_count[i] += GetReplayRate(); |
||
1534 | if (col->frame_count[i] < 0 || col->frame_count[i] >= COUNT_OF(gFlame_map)) { |
||
1535 | actor->type = BR_ACTOR_NONE; |
||
1536 | } else { |
||
1537 | actor->type = BR_ACTOR_MODEL; |
||
1538 | actor->material->colour_map = gFlame_map[col->frame_count[i]]; |
||
1539 | BrMaterialUpdate(actor->material, BR_MATU_ALL); |
||
1540 | BrMatrix34Scale(&actor->t.t.mat, |
||
1541 | col->scale_x[i] * gFlame_map[col->frame_count[i]]->width, |
||
1542 | col->scale_y[i] * gFlame_map[col->frame_count[i]]->height, |
||
1543 | 1.f); |
||
1544 | actor->t.t.translate.t.v[0] = col->offset_x[i]; |
||
1545 | actor->t.t.translate.t.v[2] = col->offset_z[i]; |
||
1546 | } |
||
1547 | } |
||
1548 | } |
||
1549 | |||
1550 | // IDA: void __usercall FlameAnimate(int c@<EAX>, br_vector3 *pPos@<EDX>, tU32 pTime@<EBX>) |
||
1551 | void FlameAnimate(int c, br_vector3* pPos, tU32 pTime) { |
||
1552 | tSmoke_column* col; |
||
1553 | br_actor* actor; |
||
1554 | int i; |
||
1555 | LOG_TRACE("(%d, %p, %d)", c, pPos, pTime); |
||
1556 | |||
1557 | col = &gSmoke_column[c]; |
||
1558 | actor = col->flame_actor; |
||
1559 | DRMatrix34RotateY(&actor->t.t.mat, FastScalarArcTan2Angle(gCamera_to_world.m[2][0], gCamera_to_world.m[2][2])); |
||
1560 | actor->t.t.translate.t = *pPos; |
||
1561 | actor = actor->children; |
||
1562 | |||
1563 | if (gAction_replay_mode) { |
||
1564 | ReplayFlame(col, actor); |
||
1565 | return; |
||
1566 | } |
||
1567 | for (i = 0; i < COUNT_OF(col->frame_count); i++) { |
||
1568 | |||
1569 | #ifdef DETHRACE_FIX_BUGS |
||
1570 | col->frame_time[i] += pTime; |
||
1571 | if (col->frame_time[i] > FLAME_ANIMATION_FRAME_INTERVAL) { |
||
1572 | col->frame_time[i] = 0; |
||
1573 | col->frame_count[i]++; |
||
1574 | } |
||
1575 | #else |
||
1576 | col->frame_count[i]++; |
||
1577 | #endif |
||
1578 | |||
1579 | if (col->frame_count[i] >= COUNT_OF(gFlame_map)) { |
||
1580 | StartPipingSession(ePipe_chunk_flame); |
||
1581 | AddFlameToPipingSession(i + 16 * c, col->frame_count[i] + 1, col->scale_x[i], col->scale_y[i], col->offset_x[i], col->offset_z[i]); |
||
1582 | EndPipingSession(); |
||
1583 | col->frame_count[i] = IRandomBetween(-5, -1); |
||
1584 | col->scale_x[i] = (2 * IRandomBetween(0, 1) - 1) * SRandomBetween(1.0f, 1.5f) * 0.003f; |
||
1585 | col->scale_y[i] = SRandomBetween(0.5f, 1.0f) * 0.003f; |
||
1586 | col->offset_x[i] = SRandomPosNeg(0.03f); |
||
1587 | col->offset_z[i] = SRandomBetween(-0.03f, 0.0); |
||
1588 | actor->type = BR_ACTOR_NONE; |
||
1589 | } |
||
1590 | if (col->frame_count[i] == 0) { |
||
1591 | if (BrVector3LengthSquared(&col->car->v) >= 80.0f || col->lifetime <= 30 * pTime) { |
||
1592 | col->frame_count[i] = -5; |
||
1593 | } else { |
||
1594 | actor->type = BR_ACTOR_MODEL; |
||
1595 | StartPipingSession(ePipe_chunk_flame); |
||
1596 | AddFlameToPipingSession(i + 16 * c, col->frame_count[i] - 1, col->scale_x[i], col->scale_y[i], col->offset_x[i], col->offset_z[i]); |
||
1597 | EndPipingSession(); |
||
1598 | } |
||
1599 | } |
||
1600 | if (col->frame_count[i] >= 0) { |
||
1601 | actor->material->colour_map = gFlame_map[col->frame_count[i]]; |
||
1602 | BrMaterialUpdate(actor->material, BR_MATU_ALL); |
||
1603 | BrMatrix34Scale(&actor->t.t.mat, gFlame_map[col->frame_count[i]]->width * col->scale_x[i], gFlame_map[col->frame_count[i]]->height * col->scale_y[i], 1.0); |
||
1604 | actor->t.t.mat.m[3][0] = col->offset_x[i]; |
||
1605 | actor->t.t.mat.m[3][2] = col->offset_z[i]; |
||
1606 | } |
||
1607 | actor = actor->next; |
||
1608 | } |
||
1609 | } |
||
1610 | |||
1611 | // IDA: void __usercall DoSmokeColumn(int i@<EAX>, tU32 pTime@<EDX>, br_vector3 *pRet_car_pos@<EBX>) |
||
1612 | void DoSmokeColumn(int i, tU32 pTime, br_vector3* pRet_car_pos) { |
||
1613 | tCar_spec* c; |
||
1614 | br_actor* actor; |
||
1615 | br_actor* bonny; |
||
1616 | //int group; // Pierre-Marie Baty -- unused variable |
||
1617 | LOG_TRACE("(%d, %d, %p)", i, pTime, pRet_car_pos); |
||
1618 | |||
1619 | c = gSmoke_column[i].car; |
||
1620 | if (c->car_master_actor->t.t.mat.m[1][1] > 0.1f) { |
||
1621 | gSmoke_column[i].upright = 1; |
||
1622 | } |
||
1623 | if (c->car_master_actor->t.t.mat.m[1][1] < -0.1f) { |
||
1624 | gSmoke_column[i].upright = 0; |
||
1625 | } |
||
1626 | actor = c->car_model_actors[c->principal_car_actor].actor; |
||
1627 | bonny = c->car_model_actors[c->car_actor_count - 1].actor; |
||
1628 | |||
18 | pmbaty | 1629 | BrVector3Add(pRet_car_pos, &V11MODEL(actor->model)->groups[0].position[gSmoke_column[i].vertex_index], &actor->t.t.translate.t); |
1 | pmbaty | 1630 | if (gProgram_state.cockpit_on && c->driver == eDriver_local_human) { |
1631 | if (c->driver_z_offset + 0.2f <= pRet_car_pos->v[2]) { |
||
1632 | pRet_car_pos->v[1] -= -0.07f; |
||
1633 | } else { |
||
18 | pmbaty | 1634 | BrMatrix34ApplyP(pRet_car_pos, &V11MODEL(actor->model)->groups[0].position[gSmoke_column[i].vertex_index], &bonny->t.t.mat); |
1 | pmbaty | 1635 | } |
1636 | } |
||
1637 | if (!gSmoke_column[i].upright) { |
||
1638 | pRet_car_pos->v[1] = c->bounds[1].min.v[1] / WORLD_SCALE; |
||
1639 | } |
||
1640 | BrMatrix34ApplyP(&gSmoke_column[i].pos, pRet_car_pos, &c->car_master_actor->t.t.mat); |
||
1641 | gSmoke_column[i].pos.v[1] -= 0.03f; |
||
1642 | } |
||
1643 | |||
1644 | // IDA: void __usercall ReplaySmokeColumn(tU32 pTime@<EAX>) |
||
1645 | void ReplaySmokeColumn(tU32 pTime) { |
||
1646 | int i; |
||
1647 | br_vector3 dummy; |
||
1648 | LOG_TRACE("(%d)", pTime); |
||
1649 | |||
1650 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
1651 | if ((gColumn_flags & (1 << i)) != 0) { |
||
1652 | DoSmokeColumn(i, pTime, &dummy); |
||
1653 | if (gSmoke_column[i].colour == 0) { |
||
1654 | FlameAnimate(i, &gSmoke_column[i].pos, pTime); |
||
1655 | } |
||
1656 | } |
||
1657 | } |
||
1658 | } |
||
1659 | |||
1660 | // IDA: void __usercall MungeSmokeColumn(tU32 pTime@<EAX>) |
||
1661 | void MungeSmokeColumn(tU32 pTime) { |
||
1662 | int i; |
||
1663 | int plane; |
||
1664 | //br_actor* actor; // Pierre-Marie Baty -- unused variable |
||
1665 | //br_actor* bonny; // Pierre-Marie Baty -- unused variable |
||
1666 | br_vector3 car_pos; |
||
1667 | br_vector3 pos; |
||
1668 | br_vector3 v; |
||
1669 | //br_vector3 up; // Pierre-Marie Baty -- unused variable |
||
1670 | //br_vector3 start; // Pierre-Marie Baty -- unused variable |
||
1671 | //br_vector3 end; // Pierre-Marie Baty -- unused variable |
||
1672 | //br_scalar ts; // Pierre-Marie Baty -- unused variable |
||
1673 | br_scalar decay_factor; |
||
1674 | tCar_spec* c; |
||
1675 | LOG_TRACE("(%d)", pTime); |
||
1676 | |||
1677 | if (gColumn_flags == 0) { |
||
1678 | return; |
||
1679 | } |
||
1680 | if (gAction_replay_mode) { |
||
1681 | ReplaySmokeColumn(pTime); |
||
1682 | return; |
||
1683 | } |
||
1684 | |||
1685 | gMechanics_time_sync = 1; |
||
1686 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
1687 | if (((1u << i) & gColumn_flags) == 0) { |
||
1688 | continue; |
||
1689 | } |
||
1690 | if (gSmoke_column[i].lifetime >= pTime) { |
||
1691 | gSmoke_column[i].lifetime -= pTime; |
||
1692 | c = gSmoke_column[i].car; |
||
1693 | DoSmokeColumn(i, pTime, &car_pos); |
||
1694 | if (gSmoke_column[i].colour == 0) { |
||
1695 | FlameAnimate(i, &gSmoke_column[i].pos, pTime); |
||
1696 | if (gSmoke_column[i].smudge_timer >= pTime) { |
||
1697 | gSmoke_column[i].smudge_timer -= pTime; |
||
1698 | } else { |
||
1699 | gSmoke_column[i].smudge_timer += 2000; |
||
1700 | SmudgeCar(gSmoke_column[i].car, gSmoke_column[i].vertex_index); |
||
1701 | if (gSmoke_column[i].car->knackered) { |
||
1702 | plane = IRandomBetween(0, COUNT_OF(gSmoke_column[i].car->fire_vertex) - 1); |
||
1703 | SmudgeCar(gSmoke_column[i].car, gSmoke_column[i].car->fire_vertex[plane]); |
||
1704 | } |
||
1705 | } |
||
1706 | } |
||
1707 | gSmoke_column[i].time += pTime; |
||
1708 | if (gSmoke_column[i].time > 200) { |
||
1709 | #ifdef DETHRACE_FIX_BUGS |
||
1710 | gSmoke_column[i].time -= fmaxf(SMOKE_COLUMN_NEW_PUFF_INTERVAL, pTime); |
||
1711 | #else |
||
1712 | gSmoke_column[i].time -= pTime; |
||
1713 | #endif |
||
1714 | gSmoke_column[i].count++; |
||
1715 | BrVector3Cross(&v, &c->omega, &car_pos); |
||
1716 | BrMatrix34ApplyV(&car_pos, &v, &c->car_master_actor->t.t.mat); |
||
1717 | BrVector3Add(&v, &c->v, &car_pos); |
||
1718 | v.v[1] = v.v[1] + 2.898550724637681f; // 100 / 34.5 ? |
||
1719 | pos.v[0] = SRandomBetween(-0.03f, 0.03f) + gSmoke_column[i].pos.v[0]; |
||
1720 | pos.v[1] = (gSmoke_column[i].colour == 0) * 0.05f + gSmoke_column[i].pos.v[1]; |
||
1721 | pos.v[2] = SRandomBetween(-0.03f, 0.03f) + gSmoke_column[i].pos.v[2]; |
||
1722 | if ((gSmoke_column[i].whiter & 2) == 0 || IRandomBetween(0, 3)) { |
||
1723 | if (gSmoke_column[i].whiter < 1) { |
||
1724 | gSmoke_column[i].whiter = -1; |
||
1725 | } else { |
||
1726 | gSmoke_column[i].whiter = 2; |
||
1727 | } |
||
1728 | } else { |
||
1729 | gSmoke_column[i].whiter &= 1; |
||
1730 | } |
||
1731 | decay_factor = ((gSmoke_column[i].whiter > 0) + 1.0f) / 2.0f; |
||
1732 | if (gSmoke_column[i].lifetime < 4000) { |
||
1733 | decay_factor = gSmoke_column[i].lifetime * decay_factor / 4000.0f; |
||
1734 | } |
||
1735 | CreatePuffOfSmoke(&pos, &v, decay_factor, decay_factor, gSmoke_column[i].colour + 16, c); |
||
1736 | } |
||
1737 | } else { |
||
1738 | if (gSmoke_column[i].car != NULL) { |
||
1739 | StartPipingSession(ePipe_chunk_smoke_column); |
||
1740 | AddSmokeColumnToPipingSession(i, gSmoke_column[i].car, gSmoke_column[i].vertex_index, gSmoke_column[i].colour); |
||
1741 | EndPipingSession(); |
||
1742 | } |
||
1743 | gColumn_flags &= ~(1u << i); |
||
1744 | if (gSmoke_column[i].colour == 0) { |
||
1745 | BrActorRemove(gSmoke_column[i].flame_actor); |
||
1746 | } |
||
1747 | if (gSmoke_column[i].car != NULL) { |
||
1748 | if (gSmoke_column[i].car->num_smoke_columns != 0) { |
||
1749 | gSmoke_column[i].car->num_smoke_columns--; |
||
1750 | } |
||
1751 | } |
||
1752 | } |
||
1753 | } |
||
1754 | } |
||
1755 | |||
1756 | // IDA: void __cdecl DisposeFlame() |
||
1757 | void DisposeFlame(void) { |
||
1758 | int i; |
||
1759 | int j; |
||
1760 | br_actor* actor; |
||
1761 | //br_material* material; // Pierre-Marie Baty -- unused variable |
||
1762 | LOG_TRACE("()"); |
||
1763 | |||
1764 | for (i = 0; i < COUNT_OF(gFlame_map); i++) { |
||
1765 | BrMapRemove(gFlame_map[i]); |
||
1766 | BrPixelmapFree(gFlame_map[i]); |
||
1767 | } |
||
1768 | |||
1769 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
1770 | if ((gColumn_flags & (1u << i)) && (gSmoke_column[i].colour == 0)) { |
||
1771 | BrActorRemove(gSmoke_column[i].flame_actor); |
||
1772 | } |
||
1773 | actor = gSmoke_column[i].flame_actor->children; |
||
1774 | for (j = 0; j < COUNT_OF(gSmoke_column[0].frame_count); j++) { |
||
1775 | BrMaterialRemove(actor->material); |
||
1776 | BrMaterialFree(actor->material); |
||
1777 | actor = actor->next; |
||
1778 | } |
||
1779 | BrActorFree(gSmoke_column[i].flame_actor); |
||
1780 | } |
||
1781 | BrModelRemove(gLollipop_model); |
||
1782 | BrModelFree(gLollipop_model); |
||
1783 | } |
||
1784 | |||
1785 | // IDA: void __cdecl InitFlame() |
||
1786 | void InitFlame(void) { |
||
1787 | int i; |
||
1788 | int j; |
||
1789 | int num; |
||
1790 | char the_path[256]; |
||
1791 | br_actor* actor; |
||
1792 | br_material* material; |
||
1793 | LOG_TRACE("()"); |
||
1794 | |||
1795 | gColumn_flags = 0; |
||
1796 | gLollipop_model = BrModelAllocate("Lollipop", 4, 2); |
||
1797 | PathCat(the_path, gApplication_path, "PIXELMAP"); |
||
1798 | PathCat(the_path, the_path, "FLAMES.PIX"); |
||
1799 | num = DRPixelmapLoadMany(the_path, gFlame_map, COUNT_OF(gFlame_map)); |
||
1800 | if (num != COUNT_OF(gFlame_map)) { |
||
1801 | FatalError(kFatalError_LoadPixelmapFile_S, the_path); |
||
1802 | } |
||
1803 | BrMapAddMany(gFlame_map, COUNT_OF(gFlame_map)); |
||
1804 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
1805 | gSmoke_column[i].flame_actor = BrActorAllocate(BR_ACTOR_NONE, NULL); |
||
1806 | for (j = 0; j < COUNT_OF(gSmoke_column[0].frame_count); j++) { |
||
1807 | actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); |
||
1808 | material = BrMaterialAllocate(NULL); |
||
1809 | BrActorAdd(gSmoke_column[i].flame_actor, actor); |
||
1810 | actor->model = gLollipop_model; |
||
1811 | actor->material = material; |
||
1812 | material->flags &= ~BR_MATF_LIGHT; |
||
1813 | material->flags |= BR_MATF_ALWAYS_VISIBLE; |
||
1814 | material->colour_map = gFlame_map[0]; |
||
1815 | BrMaterialAdd(material); |
||
1816 | gSmoke_column[i].frame_count[j] = 100; |
||
1817 | } |
||
1818 | } |
||
1819 | gLollipop_model->nvertices = 4; |
||
1820 | BrVector3SetFloat(&gLollipop_model->vertices[0].p, -.5f, 0.f, .0f); |
||
1821 | BrVector3SetFloat(&gLollipop_model->vertices[1].p, .5f, 0.f, .0f); |
||
1822 | BrVector3SetFloat(&gLollipop_model->vertices[2].p, .5f, 1.f, .0f); |
||
1823 | BrVector3SetFloat(&gLollipop_model->vertices[3].p, -.5f, 1.f, .0f); |
||
1824 | gLollipop_model->vertices[0].map.v[0] = 0.f; |
||
1825 | gLollipop_model->vertices[0].map.v[1] = 1.f; |
||
1826 | gLollipop_model->vertices[1].map.v[0] = 1.f; |
||
1827 | gLollipop_model->vertices[1].map.v[1] = 1.f; |
||
1828 | gLollipop_model->vertices[2].map.v[0] = 1.f; |
||
1829 | gLollipop_model->vertices[2].map.v[1] = 0.f; |
||
1830 | gLollipop_model->vertices[3].map.v[0] = 0.f; |
||
1831 | gLollipop_model->vertices[3].map.v[1] = 0.f; |
||
1832 | |||
1833 | gLollipop_model->nfaces = 2; |
||
1834 | gLollipop_model->faces[0].vertices[0] = 0; |
||
1835 | gLollipop_model->faces[0].vertices[1] = 1; |
||
1836 | gLollipop_model->faces[0].vertices[2] = 2; |
||
1837 | gLollipop_model->faces[1].vertices[0] = 0; |
||
1838 | gLollipop_model->faces[1].vertices[1] = 2; |
||
1839 | gLollipop_model->faces[1].vertices[2] = 3; |
||
1840 | gLollipop_model->faces[0].smoothing = 1; |
||
1841 | gLollipop_model->faces[1].smoothing = 1; |
||
1842 | BrModelAdd(gLollipop_model); |
||
1843 | } |
||
1844 | |||
1845 | // IDA: void __usercall InitSplash(FILE *pF@<EAX>) |
||
1846 | void InitSplash(FILE* pF) { |
||
1847 | int i; |
||
1848 | int num_files; |
||
1849 | int num; |
||
1850 | br_actor* actor; |
||
1851 | char the_path[256]; |
||
1852 | char s[256]; |
||
1853 | br_pixelmap* splash_maps[20]; |
||
1854 | LOG_TRACE("(%p)", pF); |
||
1855 | |||
1856 | gSplash_flags = 0; |
||
1857 | gSplash_model = BrModelAllocate("Splash", 4, 2); |
||
1858 | if (pF != NULL) { |
||
1859 | num = GetAnInt(pF); |
||
1860 | gNum_splash_types = 0; |
||
1861 | for (i = 0; num > i; ++i) { |
||
1862 | GetAString(pF, s); |
||
1863 | PathCat(the_path, gApplication_path, "PIXELMAP"); |
||
1864 | PathCat(the_path, the_path, s); |
||
1865 | num_files = DRPixelmapLoadMany(the_path, &splash_maps[gNum_splash_types], 20 - gNum_splash_types); |
||
1866 | if (num_files == 0) { |
||
1867 | FatalError(kFatalError_LoadPixelmapFile_S, the_path); |
||
1868 | } |
||
1869 | gNum_splash_types += num_files; |
||
1870 | } |
||
1871 | } else { |
||
1872 | PathCat(the_path, gApplication_path, "PIXELMAP"); |
||
1873 | PathCat(the_path, the_path, "SPLSHBLU.PIX"); |
||
1874 | gNum_splash_types = DRPixelmapLoadMany(the_path, splash_maps, 0x14u); |
||
1875 | } |
||
1876 | BrMapAddMany(splash_maps, gNum_splash_types); |
||
1877 | for (i = 0; i < gNum_splash_types; ++i) { |
||
1878 | gSplash_material[i] = BrMaterialAllocate(0); |
||
1879 | gSplash_material[i]->flags &= ~(BR_MATF_LIGHT | BR_MATF_PRELIT); |
||
1880 | gSplash_material[i]->flags |= BR_MATF_ALWAYS_VISIBLE | BR_MATF_PERSPECTIVE; |
||
1881 | gSplash_material[i]->index_blend = LoadSingleShadeTable(&gTrack_storage_space, "BLEND50.TAB"); |
||
1882 | gSplash_material[i]->colour_map = splash_maps[i]; |
||
1883 | BrMaterialAdd(gSplash_material[i]); |
||
1884 | } |
||
1885 | gSplash_model->nvertices = 4; |
||
1886 | BrVector3SetFloat(&gSplash_model->vertices[0].p, -0.5f, 0.0f, 0.0f); |
||
1887 | BrVector3SetFloat(&gSplash_model->vertices[1].p, 0.5f, 0.0f, 0.0f); |
||
1888 | BrVector3SetFloat(&gSplash_model->vertices[2].p, 0.5f, 1.0f, 0.0f); |
||
1889 | BrVector3SetFloat(&gSplash_model->vertices[3].p, -0.5f, 1.0f, 0.0f); |
||
1890 | gSplash_model->vertices[0].map.v[0] = 0.0f; |
||
1891 | gSplash_model->vertices[0].map.v[1] = 1.0f; |
||
1892 | gSplash_model->vertices[1].map.v[0] = 1.0f; |
||
1893 | gSplash_model->vertices[1].map.v[1] = 1.0f; |
||
1894 | gSplash_model->vertices[2].map.v[0] = 1.0f; |
||
1895 | gSplash_model->vertices[2].map.v[1] = 0.0f; |
||
1896 | gSplash_model->vertices[3].map.v[0] = 0.0f; |
||
1897 | gSplash_model->vertices[3].map.v[1] = 0.0f; |
||
1898 | gSplash_model->nfaces = 2; |
||
1899 | gSplash_model->faces[0].vertices[0] = 0; |
||
1900 | gSplash_model->faces[0].vertices[1] = 1; |
||
1901 | gSplash_model->faces[0].vertices[2] = 2; |
||
1902 | gSplash_model->faces[1].vertices[0] = 0; |
||
1903 | gSplash_model->faces[1].vertices[1] = 2; |
||
1904 | gSplash_model->faces[1].vertices[2] = 3; |
||
1905 | gSplash_model->faces[0].smoothing = 1; |
||
1906 | gSplash_model->faces[1].smoothing = 1; |
||
1907 | BrModelAdd(gSplash_model); |
||
1908 | for (i = 0; i < COUNT_OF(gSplash); i++) { |
||
1909 | gSplash[i].actor = BrActorAllocate(BR_ACTOR_MODEL, NULL); |
||
1910 | actor = gSplash[i].actor; |
||
1911 | actor->model = gSplash_model; |
||
1912 | if (gNum_splash_types != 0) { |
||
1913 | actor->material = gSplash_material[IRandomBetween(0, gNum_splash_types - 1)]; |
||
1914 | } else { |
||
1915 | actor->material = NULL; |
||
1916 | } |
||
1917 | gSplash[i].scale_x = SRandomBetween(0.9f, 1.1f) * (2 * IRandomBetween(0, 1) - 1); |
||
1918 | } |
||
1919 | } |
||
1920 | |||
1921 | // IDA: void __cdecl DisposeSplash() |
||
1922 | void DisposeSplash(void) { |
||
1923 | int i; |
||
1924 | LOG_TRACE("()"); |
||
1925 | |||
1926 | for (i = 0; i < gNum_splash_types; i++) { |
||
1927 | BrMapRemove(gSplash_material[i]->colour_map); |
||
1928 | BrPixelmapFree(gSplash_material[i]->colour_map); |
||
1929 | BrMaterialRemove(gSplash_material[i]); |
||
1930 | BrMaterialFree(gSplash_material[i]); |
||
1931 | } |
||
1932 | for (i = 0; i < COUNT_OF(gSplash); i++) { |
||
1933 | if (gSplash_flags & (1u << i)) { |
||
1934 | BrActorRemove(gSplash[i].actor); |
||
1935 | } |
||
1936 | BrActorFree(gSplash[i].actor); |
||
1937 | } |
||
1938 | BrModelRemove(gSplash_model); |
||
1939 | BrModelFree(gSplash_model); |
||
1940 | } |
||
1941 | |||
1942 | // IDA: void __usercall DrawTheGlow(br_pixelmap *pRender_screen@<EAX>, br_pixelmap *pDepth_buffer@<EDX>, br_actor *pCamera@<EBX>) |
||
1943 | void DrawTheGlow(br_pixelmap* pRender_screen, br_pixelmap* pDepth_buffer, br_actor* pCamera) { |
||
1944 | int i; |
||
1945 | br_scalar strength; |
||
1946 | br_vector3 tv; |
||
1947 | tU32 seed; |
||
1948 | LOG_TRACE("(%p, %p, %p)", pRender_screen, pDepth_buffer, pCamera); |
||
1949 | |||
1950 | if (gColumn_flags) { |
||
1951 | seed = rand(); |
||
1952 | srand(GetTotalTime()); |
||
1953 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
1954 | if (((1u << i) & gColumn_flags) != 0 && gSmoke_column[i].colour <= 1) { |
||
1955 | strength = 0.5f; |
||
1956 | if (gSmoke_column[i].lifetime < 4000) { |
||
1957 | strength = gSmoke_column[i].lifetime * 0.5f / 4000.f; |
||
1958 | } |
||
1959 | BrVector3Set(&tv, gSmoke_column[i].pos.v[0], gSmoke_column[i].pos.v[1] + 0.02f, gSmoke_column[i].pos.v[2]); |
||
1960 | SmokeCircle3D(&tv, 0.07f, strength, SRandomBetween(0.5f, 0.99f), pRender_screen, pDepth_buffer, gAcid_shade_table, pCamera); |
||
1961 | } |
||
1962 | } |
||
1963 | srand(seed); |
||
1964 | } |
||
1965 | } |
||
1966 | |||
1967 | // IDA: void __usercall PipeInstantUnSmudge(tCar_spec *pCar@<EAX>) |
||
1968 | void PipeInstantUnSmudge(tCar_spec* pCar) { |
||
1969 | br_model* model; |
||
1970 | br_model* b_model; |
||
1971 | br_actor* actor; |
||
1972 | br_actor* bonny; |
||
1973 | int j; |
||
1974 | int n; |
||
1975 | int v; |
||
1976 | int group; |
||
1977 | tSmudged_vertex data[1000]; |
||
1978 | LOG_TRACE("(%p)", pCar); |
||
1979 | |||
1980 | if (!gAction_replay_mode) { |
||
1981 | return; |
||
1982 | } |
||
1983 | actor = pCar->car_model_actors[pCar->principal_car_actor].actor; |
||
1984 | model = actor->model; |
||
1985 | bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor; |
||
1986 | n = 0; |
||
1987 | if ((model->flags & BR_MODF_KEEP_ORIGINAL) != 0 || (model->flags & BR_MODF_UPDATEABLE) != 0) { |
||
1988 | StartPipingSession(ePipe_chunk_smudge); |
||
1989 | j = 0; |
||
1990 | for (group = 0; group < V11MODEL(model)->ngroups; group++) { |
||
1991 | for (v = 0; v < V11MODEL(model)->groups[group].nvertices; v++) { |
||
1992 | if ((V11MODEL(model)->groups[group].vertex_colours[v] >> 24) != 0) { |
||
1993 | data[n].vertex_index = j; |
||
1994 | data[n].light_index = 0 -(V11MODEL(model)->groups[group].vertex_colours[v] >> 24); // Pierre-Marie Baty -- prefixed 0 to silence signedness warning |
||
1995 | n += 1; |
||
1996 | V11MODEL(model)->groups[group].vertex_colours[v] = 0; |
||
1997 | if ((model->flags & 0x80) != 0) { |
||
1998 | model->vertices[V11MODEL(model)->groups[group].vertex_user[v]].index = 0; |
||
1999 | } |
||
2000 | if (n >= COUNT_OF(data)) { |
||
2001 | group = V11MODEL(model)->ngroups; |
||
2002 | break; |
||
2003 | } |
||
2004 | } |
||
2005 | j += 1; |
||
2006 | } |
||
2007 | } |
||
2008 | if (n != 0) { |
||
2009 | AddSmudgeToPipingSession(pCar->car_ID, pCar->principal_car_actor, n, data); |
||
2010 | } |
||
2011 | if (bonny != actor) { |
||
2012 | b_model = bonny->model; |
||
2013 | n = 0; |
||
2014 | j = 0; |
||
2015 | for (group = 0; group < V11MODEL(model)->ngroups; group++) { |
||
2016 | for (v = 0; v < V11MODEL(model)->groups[group].nvertices; v++) { |
||
2017 | if ((V11MODEL(model)->groups[group].vertex_colours[v] >> 24) != 0) { |
||
2018 | data[n].vertex_index = j; |
||
2019 | data[n].light_index = -V11MODEL(model)->groups[group].nvertices; |
||
2020 | n += 1; |
||
2021 | V11MODEL(model)->groups[group].vertex_colours[v] = 0; |
||
2022 | if ((b_model->flags & BR_MODF_UPDATEABLE) != 0) { |
||
2023 | b_model->vertices[V11MODEL(model)->groups[group].vertex_user[v]].index = 0; |
||
2024 | } |
||
2025 | if (n >= COUNT_OF(data)) { |
||
2026 | group = V11MODEL(model)->groups[group].nvertices; |
||
2027 | break; |
||
2028 | } |
||
2029 | } |
||
2030 | j += 1; |
||
2031 | } |
||
2032 | } |
||
2033 | if (n != 0) { |
||
2034 | AddSmudgeToPipingSession(pCar->car_ID, pCar->car_actor_count - 1, n, data); |
||
2035 | } |
||
2036 | } |
||
2037 | EndPipingSession(); |
||
2038 | } |
||
2039 | } |
||
2040 | |||
2041 | // IDA: void __usercall SmudgeCar(tCar_spec *pCar@<EAX>, int fire_point@<EDX>) |
||
2042 | void SmudgeCar(tCar_spec* pCar, int fire_point) { |
||
2043 | int v; |
||
2044 | int j; |
||
2045 | int real_vertex_number; |
||
2046 | br_model* model; |
||
2047 | br_model* b_model; |
||
2048 | br_actor* actor; |
||
2049 | br_actor* bonny; |
||
2050 | br_scalar ts; |
||
2051 | br_vector3 tv; |
||
2052 | br_vector3 bonny_pos; |
||
2053 | int group; |
||
2054 | br_vector3 point; |
||
2055 | tSmudged_vertex data[30]; |
||
2056 | int n; |
||
2057 | LOG_TRACE("(%p, %d)", pCar, fire_point); |
||
2058 | |||
2059 | if (gAusterity_mode) { |
||
2060 | return; |
||
2061 | } |
||
2062 | |||
2063 | v = fire_point; |
||
2064 | group = 0; |
||
2065 | actor = pCar->car_model_actors[pCar->principal_car_actor].actor; |
||
2066 | model = actor->model; |
||
2067 | bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor; |
||
2068 | n = 0; |
||
2069 | real_vertex_number = 0; |
||
2070 | if ((model->flags & BR_MODF_KEEP_ORIGINAL) != 0 || (model->flags & BR_MODF_UPDATEABLE) != 0) { |
||
18 | pmbaty | 2071 | point = V11MODEL(model)->groups[group].position[fire_point]; |
1 | pmbaty | 2072 | StartPipingSession(ePipe_chunk_smudge); |
2073 | for (group = 0; group < V11MODEL(model)->ngroups; group++) { |
||
2074 | for (j = 0; j < V11MODEL(model)->groups[group].nvertices; j++) { |
||
18 | pmbaty | 2075 | BrVector3Sub(&tv, &V11MODEL(model)->groups[group].position[j], &point); |
1 | pmbaty | 2076 | ts = (.0144f - BrVector3LengthSquared(&tv) / SRandomBetween(.5f, 1.f)) / .0144f * 127.f; |
2077 | if (ts > 0.f) { |
||
2078 | ts += BR_ALPHA(V11MODEL(model)->groups[group].vertex_colours[j]); |
||
2079 | if (ts > 255.f) { |
||
2080 | ts = 255.f; |
||
2081 | } |
||
2082 | if (BR_ALPHA(V11MODEL(model)->groups[group].vertex_colours[j]) != (int)ts) { |
||
2083 | data[n].vertex_index = real_vertex_number; |
||
2084 | data[n].light_index = (int)ts - BR_ALPHA(V11MODEL(model)->groups[group].vertex_colours[j]); |
||
2085 | V11MODEL(model)->groups[group].vertex_colours[j] = (int)ts << 24; |
||
2086 | if ((model->flags & BR_MODF_UPDATEABLE) != 0) { |
||
2087 | model->vertices[V11MODEL(model)->groups[group].vertex_user[j]].index = (int)ts; |
||
2088 | } |
||
2089 | n++; |
||
2090 | if (n >= COUNT_OF(data)) { |
||
2091 | break; |
||
2092 | } |
||
2093 | } |
||
2094 | } |
||
2095 | real_vertex_number++; |
||
2096 | } |
||
2097 | if (n >= COUNT_OF(data)) { |
||
2098 | break; |
||
2099 | } |
||
2100 | } |
||
2101 | if (n > 0) { |
||
2102 | AddSmudgeToPipingSession(pCar->car_ID, pCar->principal_car_actor, n, data); |
||
18 | pmbaty | 2103 | // FIXME? |
1 | pmbaty | 2104 | // Added by dethrace to update gpu-buffered vertices |
18 | pmbaty | 2105 | // model->flags |= BR_MODF_DETHRACE_FORCE_BUFFER_UPDATE; |
1 | pmbaty | 2106 | } |
2107 | |||
2108 | n = 0; |
||
2109 | real_vertex_number = 0; |
||
2110 | if (actor != bonny) { |
||
2111 | b_model = bonny->model; |
||
2112 | BrVector3Add(&tv, &actor->t.t.translate.t, &point); |
||
2113 | BrVector3Accumulate(&tv, &bonny->t.t.translate.t); |
||
2114 | BrMatrix34TApplyV(&bonny_pos, &tv, &bonny->t.t.mat); |
||
2115 | for (group = 0; group < V11MODEL(b_model)->ngroups; group++) { |
||
2116 | j = 0; |
||
2117 | for (j = 0; j < V11MODEL(b_model)->groups[group].nvertices; j++) { |
||
18 | pmbaty | 2118 | BrVector3Sub(&tv, &V11MODEL(b_model)->groups[group].position[j], &bonny_pos); |
1 | pmbaty | 2119 | ts = (.0144f - BrVector3LengthSquared(&tv) / SRandomBetween(.5f, 1.f)) / .0144f * 127.f; |
2120 | if (ts > 0.f) { |
||
2121 | ts += BR_ALPHA(V11MODEL(b_model)->groups[group].vertex_colours[j]); |
||
2122 | if (ts > 255.f) { |
||
2123 | ts = 255.f; |
||
2124 | } |
||
2125 | if (BR_ALPHA(V11MODEL(b_model)->groups[group].vertex_colours[j]) != (int)ts) { |
||
2126 | data[n].vertex_index = real_vertex_number; |
||
2127 | data[n].light_index = (int)ts - BR_ALPHA(V11MODEL(b_model)->groups[group].vertex_colours[j]); |
||
2128 | V11MODEL(b_model)->groups[group].vertex_colours[j] = (int)ts << 24; |
||
2129 | if ((b_model->flags & BR_MODF_UPDATEABLE) != 0) { |
||
2130 | b_model->vertices[V11MODEL(b_model)->groups[group].vertex_user[j]].index = (int)ts; |
||
2131 | } |
||
2132 | n++; |
||
2133 | if (n >= COUNT_OF(data)) { |
||
2134 | break; |
||
2135 | } |
||
2136 | } |
||
2137 | } |
||
2138 | real_vertex_number++; |
||
2139 | } |
||
2140 | if (n >= COUNT_OF(data)) { |
||
2141 | break; |
||
2142 | } |
||
2143 | } |
||
2144 | if (n > 0) { |
||
2145 | AddSmudgeToPipingSession(pCar->car_ID, pCar->car_actor_count - 1, n, data); |
||
18 | pmbaty | 2146 | // FIXME? |
1 | pmbaty | 2147 | // Added by dethrace to update gpu-buffered vertices |
18 | pmbaty | 2148 | // b_model->flags |= BR_MODF_DETHRACE_FORCE_BUFFER_UPDATE; |
1 | pmbaty | 2149 | } |
2150 | } |
||
2151 | EndPipingSession(); |
||
2152 | } |
||
2153 | } |
||
2154 | |||
2155 | // IDA: void __cdecl ResetSmokeColumns() |
||
2156 | void ResetSmokeColumns(void) { |
||
18 | pmbaty | 2157 | int i; |
1 | pmbaty | 2158 | LOG_TRACE("()"); |
18 | pmbaty | 2159 | |
2160 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
2161 | if (gColumn_flags & (1 << i)) { |
||
2162 | BrActorRemove(gSmoke_column[i].flame_actor); |
||
2163 | } |
||
2164 | } |
||
2165 | gColumn_flags = 0; |
||
1 | pmbaty | 2166 | } |
2167 | |||
2168 | // IDA: void __usercall SetSmokeOn(int pSmoke_on@<EAX>) |
||
2169 | void SetSmokeOn(int pSmoke_on) { |
||
2170 | LOG_TRACE("(%d)", pSmoke_on); |
||
2171 | |||
2172 | gSmoke_on = pSmoke_on; |
||
2173 | } |
||
2174 | |||
2175 | // IDA: void __usercall ReallySetSmokeOn(int pSmoke_on@<EAX>) |
||
2176 | void ReallySetSmokeOn(int pSmoke_on) { |
||
2177 | LOG_TRACE("(%d)", pSmoke_on); |
||
18 | pmbaty | 2178 | |
2179 | ResetSmoke(); |
||
2180 | ResetSmokeColumns(); |
||
1 | pmbaty | 2181 | } |
2182 | |||
2183 | // IDA: void __usercall SetSmoke(int pSmoke_on@<EAX>) |
||
2184 | void SetSmoke(int pSmoke_on) { |
||
2185 | LOG_TRACE("(%d)", pSmoke_on); |
||
2186 | |||
2187 | ReallySetSmokeOn(pSmoke_on); |
||
2188 | SetSmokeOn(pSmoke_on); |
||
2189 | } |
||
2190 | |||
2191 | // IDA: int __cdecl GetSmokeOn() |
||
2192 | int GetSmokeOn(void) { |
||
2193 | LOG_TRACE("()"); |
||
2194 | |||
2195 | return gSmoke_on; |
||
2196 | } |
||
2197 | |||
2198 | // IDA: void __usercall StopCarSmoking(tCar_spec *pCar@<EAX>) |
||
2199 | void StopCarSmoking(tCar_spec* pCar) { |
||
2200 | int i; |
||
2201 | LOG_TRACE("(%p)", pCar); |
||
2202 | |||
2203 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
2204 | if (gSmoke_column[i].car == pCar && gSmoke_column[i].lifetime > 2000) { |
||
2205 | gSmoke_column[i].lifetime = 2000; |
||
2206 | } |
||
2207 | } |
||
2208 | } |
||
2209 | |||
2210 | // IDA: void __usercall StopCarSmokingInstantly(tCar_spec *pCar@<EAX>) |
||
2211 | void StopCarSmokingInstantly(tCar_spec* pCar) { |
||
2212 | int i; |
||
2213 | LOG_TRACE("(%p)", pCar); |
||
2214 | |||
2215 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
2216 | if (gSmoke_column[i].car == pCar) { |
||
2217 | gSmoke_column[i].lifetime = 0; |
||
2218 | } |
||
2219 | } |
||
2220 | } |
||
2221 | |||
2222 | // IDA: void __usercall ConditionalSmokeColumn(tCar_spec *pCar@<EAX>, int pDamage_index@<EDX>, int pColour@<EBX>) |
||
2223 | void ConditionalSmokeColumn(tCar_spec* pCar, int pDamage_index, int pColour) { |
||
2224 | int i; |
||
2225 | LOG_TRACE("(%p, %d, %d)", pCar, pDamage_index, pColour); |
||
2226 | |||
2227 | if (!pColour) { |
||
2228 | pColour = pCar->driver < eDriver_net_human; |
||
2229 | } |
||
2230 | if (pCar->num_smoke_columns != 0) { |
||
2231 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
2232 | if (gSmoke_column[i].car == pCar) { |
||
2233 | if (((1u << i) & gColumn_flags) != 0 && gSmoke_column[i].colour <= pColour && gSmoke_column[i].lifetime) { |
||
2234 | return; |
||
2235 | } |
||
2236 | gSmoke_column[i].lifetime = 2000; |
||
2237 | } |
||
2238 | } |
||
2239 | } |
||
2240 | CreateSmokeColumn(pCar, pColour, pCar->fire_vertex[pDamage_index], 10000000u); |
||
2241 | } |
||
2242 | |||
2243 | // IDA: void __usercall SingleSplash(tCar_spec *pCar@<EAX>, br_vector3 *sp@<EDX>, br_vector3 *normal@<EBX>, tU32 pTime@<ECX>) |
||
2244 | void SingleSplash(tCar_spec* pCar, br_vector3* sp, br_vector3* normal, tU32 pTime) { |
||
2245 | br_matrix34* mat; |
||
2246 | br_matrix34* c_mat; |
||
2247 | br_vector3 tv; |
||
2248 | br_vector3 vel; |
||
2249 | br_scalar size; |
||
2250 | br_scalar speed; |
||
2251 | br_scalar ts; |
||
2252 | LOG_TRACE("(%p, %p, %p, %d)", pCar, sp, normal, pTime); |
||
2253 | |||
2254 | mat = &gSplash[gNext_splash].actor->t.t.mat; |
||
2255 | c_mat = &pCar->car_master_actor->t.t.mat; |
||
2256 | BrMatrix34ApplyP(&gSplash[gNext_splash].actor->t.t.euler.t, sp, c_mat); |
||
2257 | tv.v[0] = sp->v[2] * pCar->omega.v[1] - pCar->omega.v[2] * sp->v[1]; |
||
2258 | tv.v[1] = pCar->omega.v[2] * sp->v[0] - sp->v[2] * pCar->omega.v[0]; |
||
2259 | tv.v[2] = sp->v[1] * pCar->omega.v[0] - pCar->omega.v[1] * sp->v[0]; |
||
2260 | BrMatrix34ApplyV(&vel, &tv, c_mat); |
||
2261 | BrVector3Accumulate(&vel, &pCar->v); |
||
2262 | ts = BrVector3Length(&vel); |
||
2263 | size = (fabs(BrVector3Dot(normal, &vel)) * 5.0 + ts) / 150.0 + 0.047826085; |
||
2264 | if (size > 0.5) { |
||
2265 | size = 0.5; |
||
2266 | } |
||
2267 | if (BrVector3Dot(&pCar->velocity_car_space, sp) < 0.0) { |
||
2268 | size = size / 2.0; |
||
2269 | } |
||
2270 | |||
2271 | gSplash[gNext_splash].size = SRandomBetween(size / 2.0, size); |
||
2272 | if (((1u << gNext_splash) & gSplash_flags) == 0) { |
||
2273 | BrActorAdd(gDont_render_actor, gSplash[gNext_splash].actor); |
||
2274 | } |
||
2275 | gSplash_flags |= 1u << gNext_splash; |
||
2276 | gSplash[gNext_splash].just_done = 1; |
||
2277 | if ((double)pTime * 0.003 > SRandomBetween(0.0, 1.0) && !gAction_replay_mode) { |
||
2278 | BrVector3InvScale(&vel, &vel, WORLD_SCALE); |
||
2279 | BrVector3Scale(&tv, &vel, 0.1f); |
||
2280 | speed = sqrt(ts / 70.0) * 15.0; |
||
2281 | if (speed > 15.0f) { |
||
2282 | speed = 15.0f; |
||
2283 | } |
||
2284 | tv.v[1] += SRandomBetween(5.0, speed) / WORLD_SCALE; |
||
2285 | BrMatrix34TApplyV(&vel, &tv, &pCar->car_master_actor->t.t.mat); |
||
2286 | |||
2287 | BrVector3Cross(&tv, &vel, &pCar->water_normal); |
||
2288 | BrVector3Scale(&tv, &tv, 0.5f); |
||
2289 | if (BrVector3Dot(sp, &tv) <= 0.0) { |
||
2290 | BrVector3Sub(&vel, &vel, &tv); |
||
2291 | } else { |
||
2292 | BrVector3Accumulate(&vel, &tv); |
||
2293 | } |
||
2294 | CreateSingleSpark(pCar, sp, &vel); |
||
2295 | } |
||
2296 | gNext_splash++; |
||
2297 | if (gNext_splash >= COUNT_OF(gSplash)) { |
||
2298 | gNext_splash = 0; |
||
2299 | } |
||
2300 | } |
||
2301 | |||
2302 | // IDA: void __usercall CreateSplash(tCar_spec *pCar@<EAX>, tU32 pTime@<EDX>) |
||
2303 | void CreateSplash(tCar_spec* pCar, tU32 pTime) { |
||
2304 | br_vector3 normal_car_space; |
||
2305 | br_vector3 pos2; |
||
2306 | br_vector3 v_plane; |
||
2307 | br_vector3 p; |
||
2308 | br_vector3 tv; |
||
2309 | br_vector3 tv2; |
||
2310 | br_vector3 cm; |
||
2311 | int i; |
||
2312 | int j; |
||
2313 | int mask; |
||
2314 | int axis1; |
||
2315 | int axis2; |
||
2316 | int axis3; |
||
2317 | //br_bounds bnds; // Pierre-Marie Baty -- unused variable |
||
2318 | br_scalar min; |
||
2319 | br_scalar max; |
||
2320 | br_scalar d; |
||
2321 | //br_scalar d2; // Pierre-Marie Baty -- unused variable |
||
2322 | br_scalar dist; |
||
2323 | br_scalar dist2; |
||
2324 | br_scalar ts; |
||
2325 | br_vector3 back_point[2]; |
||
2326 | br_scalar back_val[2]; |
||
2327 | LOG_TRACE("(%p, %d)", pCar, pTime); |
||
2328 | |||
2329 | back_val[0] = 0.0; |
||
2330 | back_val[1] = 0.0; |
||
2331 | #ifdef DETHRACE_FIX_BUGS |
||
2332 | BrVector3Set(&p, 0.f, 0.f, 0.f); |
||
2333 | #endif |
||
2334 | if (pCar->v.v[2] * pCar->v.v[2] + pCar->v.v[1] * pCar->v.v[1] + pCar->v.v[0] * pCar->v.v[0] >= 1.0) { |
||
2335 | BrMatrix34TApplyV(&normal_car_space, &pCar->water_normal, &pCar->car_master_actor->t.t.mat); |
||
2336 | BrMatrix34ApplyP(&tv, &pCar->bounds[0].min, &pCar->car_master_actor->t.t.mat); |
||
2337 | min = BrVector3Dot(&pCar->water_normal, &tv) - pCar->water_d; |
||
2338 | max = min; |
||
2339 | for (i = 0; i < 3; ++i) { |
||
2340 | if (normal_car_space.v[i] <= 0.0) { |
||
2341 | max = (pCar->bounds[0].max.v[i] - pCar->bounds[0].min.v[i]) * normal_car_space.v[i] + max; |
||
2342 | } else { |
||
2343 | min = (pCar->bounds[0].max.v[i] - pCar->bounds[0].min.v[i]) * normal_car_space.v[i] + min; |
||
2344 | } |
||
2345 | } |
||
2346 | if (min * max <= 0.0) { |
||
2347 | BrVector3InvScale(&back_point[0], &pCar->bounds[1].min, WORLD_SCALE); |
||
2348 | BrVector3InvScale(&back_point[1], &pCar->bounds[1].max, WORLD_SCALE); |
||
2349 | back_point[0].v[1] = (br_scalar) 0.01; // Pierre-Marie Baty -- added type cast |
||
2350 | ts = BrVector3Dot(&pCar->velocity_car_space, &normal_car_space); |
||
2351 | BrVector3Scale(&tv, &normal_car_space, ts); |
||
2352 | BrVector3Sub(&v_plane, &pCar->velocity_car_space, &tv); |
||
2353 | d = pCar->water_d |
||
2354 | - (pCar->car_master_actor->t.t.mat.m[3][1] * pCar->water_normal.v[1] |
||
2355 | + pCar->car_master_actor->t.t.mat.m[3][2] * pCar->water_normal.v[2] |
||
2356 | + pCar->car_master_actor->t.t.mat.m[3][0] * pCar->water_normal.v[0]); |
||
2357 | mask = IRandomBetween(0, 3); |
||
2358 | axis2 = 2; |
||
2359 | for (axis1 = 0; axis1 < 3; ++axis1) { |
||
2360 | axis3 = 3 - axis1 - axis2; |
||
2361 | for (j = 0; j < 4; ++j) { |
||
2362 | i = j ^ mask; |
||
2363 | if (((j ^ mask) & 1) != 0) { |
||
2364 | tv2.v[axis3] = back_point[0].v[axis3]; |
||
2365 | } else { |
||
2366 | tv2.v[axis3] = back_point[1].v[axis3]; |
||
2367 | } |
||
2368 | if (((j ^ mask) & 1) != 0) { |
||
2369 | tv2.v[axis2] = back_point[0].v[axis2]; |
||
2370 | } else { |
||
2371 | tv2.v[axis2] = back_point[1].v[axis2]; |
||
2372 | } |
||
2373 | |||
2374 | ts = d - tv2.v[axis3] * normal_car_space.v[axis3] - tv2.v[axis2] * normal_car_space.v[axis2]; |
||
2375 | ts = ts / normal_car_space.v[axis1]; |
||
2376 | if (ts >= back_point[0].v[axis1] && back_point[1].v[axis1] >= ts) { |
||
2377 | tv2.v[axis1] = ts; |
||
2378 | ts = BrVector3Dot(&pCar->velocity_car_space, &tv2); |
||
2379 | if (ts >= back_val[0]) { |
||
2380 | if (back_val[1] <= ts) { |
||
2381 | SingleSplash(pCar, &tv2, &normal_car_space, pTime); |
||
2382 | } else { |
||
2383 | if (back_val[1] < 0.0) { |
||
2384 | SingleSplash(pCar, &pos2, &normal_car_space, pTime); |
||
2385 | } |
||
2386 | back_val[1] = ts; |
||
2387 | pos2 = tv2; |
||
2388 | } |
||
2389 | } else { |
||
2390 | if (back_val[1] < 0.0) { |
||
2391 | SingleSplash(pCar, &pos2, &normal_car_space, pTime); |
||
2392 | } |
||
2393 | back_val[1] = back_val[0]; |
||
2394 | back_val[0] = ts; |
||
2395 | pos2 = p; |
||
2396 | p = tv2; |
||
2397 | } |
||
2398 | } |
||
2399 | } |
||
2400 | axis2 = axis1; |
||
2401 | } |
||
2402 | if (back_val[1] >= 0.0) { |
||
2403 | if (back_val[0] < 0.0) { |
||
2404 | SingleSplash(pCar, &p, &normal_car_space, pTime); |
||
2405 | } |
||
2406 | } else { |
||
2407 | tv.v[0] = pos2.v[0] - p.v[0]; |
||
2408 | tv.v[1] = pos2.v[1] - p.v[1]; |
||
2409 | tv.v[2] = pos2.v[2] - p.v[2]; |
||
2410 | BrVector3Sub(&tv, &pos2, &p); |
||
2411 | ts = SRandomBetween((br_scalar) 0.4, (br_scalar) 0.6); // Pierre-Marie Baty -- added type casts |
||
2412 | BrVector3Scale(&tv2, &tv, ts); |
||
2413 | BrVector3Accumulate(&tv2, &p); |
||
2414 | ts = SRandomBetween((br_scalar) 0.2, (br_scalar) 0.3); // Pierre-Marie Baty -- added type casts |
||
2415 | BrVector3Scale(&cm, &tv, ts); |
||
2416 | BrVector3Accumulate(&p, &cm); |
||
2417 | ts = -SRandomBetween((br_scalar) 0.2, (br_scalar) 0.3); // Pierre-Marie Baty -- added type casts |
||
2418 | BrVector3Scale(&cm, &tv, ts); |
||
2419 | BrVector3Accumulate(&pos2, &cm); |
||
2420 | ts = BrVector3Dot(&pCar->velocity_car_space, &normal_car_space); |
||
2421 | BrVector3Scale(&tv, &normal_car_space, -ts); |
||
2422 | BrVector3Add(&v_plane, &pCar->velocity_car_space, &tv); |
||
2423 | BrVector3Normalise(&tv, &v_plane); |
||
2424 | BrVector3Scale(&tv, &tv, -0.028985508f); |
||
2425 | BrVector3Accumulate(&tv2, &tv); |
||
2426 | BrVector3Scale(&tv, &tv, 0.5f); |
||
2427 | BrVector3Accumulate(&p, &tv); |
||
2428 | BrVector3Accumulate(&pos2, &tv); |
||
2429 | SingleSplash(pCar, &tv2, &normal_car_space, pTime); |
||
2430 | SingleSplash(pCar, &p, &normal_car_space, pTime); |
||
2431 | SingleSplash(pCar, &pos2, &normal_car_space, pTime); |
||
2432 | } |
||
2433 | d = d * WORLD_SCALE; |
||
2434 | dist = d - BrVector3Dot(&pCar->cmpos, &normal_car_space); |
||
2435 | for (i = 0; pCar->extra_point_num > i; ++i) { |
||
2436 | dist2 = d |
||
2437 | - (pCar->extra_points[i].v[1] * normal_car_space.v[1] |
||
2438 | + pCar->extra_points[i].v[2] * normal_car_space.v[2] |
||
2439 | + pCar->extra_points[i].v[0] * normal_car_space.v[0]); |
||
2440 | if ((dist > 0.0) != (dist2 > 0.0)) { |
||
2441 | ts = dist / (dist - dist2); |
||
2442 | BrVector3Sub(&tv, &pCar->extra_points[i], &pCar->cmpos); |
||
2443 | BrVector3Scale(&tv, &tv, ts); |
||
2444 | BrVector3Accumulate(&tv, &pCar->cmpos); |
||
2445 | if (pCar->bounds[1].max.v[1] - 0.028985508 > tv.v[1] |
||
2446 | || pCar->bounds[1].min.v[0] > tv.v[0] |
||
2447 | || pCar->bounds[1].max.v[0] < tv.v[1] |
||
2448 | || pCar->bounds[1].min.v[2] > tv.v[2] |
||
2449 | || pCar->bounds[1].max.v[2] < tv.v[2]) { |
||
2450 | BrVector3InvScale(&tv, &tv, WORLD_SCALE); |
||
2451 | SingleSplash(pCar, &tv, &normal_car_space, pTime); |
||
2452 | } |
||
2453 | } |
||
2454 | } |
||
2455 | for (i = 0; i < 4; ++i) { |
||
2456 | if ((i & 1) != 0) { |
||
2457 | tv.v[0] = pCar->bounds[1].max.v[0]; |
||
2458 | } else { |
||
2459 | tv.v[0] = pCar->bounds[1].min.v[0]; |
||
2460 | } |
||
2461 | tv.v[1] = pCar->bounds[1].max.v[1]; |
||
2462 | tv.v[2] = pCar->wpos[i].v[2]; |
||
2463 | dist = d - BrVector3Dot(&tv, &normal_car_space); |
||
2464 | dist2 = (pCar->bounds[1].max.v[1] - 0.01) * normal_car_space.v[1] + dist; |
||
2465 | if ((dist > 0.0) != (dist2 > 0.0)) { |
||
2466 | ts = dist / (dist - dist2); |
||
2467 | tv.v[1] -= (pCar->bounds[1].max.v[1] - 0.01) * ts; |
||
2468 | BrVector3InvScale(&tv, &tv, WORLD_SCALE); |
||
2469 | SingleSplash(pCar, &tv, &normal_car_space, pTime); |
||
2470 | } |
||
2471 | } |
||
2472 | } else { |
||
2473 | min = min + 1.0; |
||
2474 | } |
||
2475 | } |
||
2476 | } |
||
2477 | |||
2478 | // IDA: void __usercall MungeSplash(tU32 pTime@<EAX>) |
||
2479 | void MungeSplash(tU32 pTime) { |
||
2480 | int i; |
||
2481 | //br_vector3 tv; // Pierre-Marie Baty -- unused variable |
||
2482 | br_scalar dt; |
||
2483 | br_scalar ts; |
||
2484 | tCar_spec* car; |
||
2485 | tVehicle_type type; |
||
2486 | LOG_TRACE("(%d)", pTime); |
||
2487 | |||
2488 | if (gNum_splash_types == 0) { |
||
2489 | return; |
||
2490 | } |
||
2491 | if (!gAction_replay_mode || GetReplayRate() == 0.0) { |
||
2492 | if (!gAction_replay_mode) { |
||
2493 | for (i = 0; i < gNum_cars_and_non_cars; i++) { |
||
2494 | if (gActive_car_list[i]->water_d != 10000.0 && gActive_car_list[i]->driver != eDriver_local_human) { |
||
2495 | CreateSplash(gActive_car_list[i], pTime); |
||
2496 | } |
||
2497 | } |
||
2498 | if (gProgram_state.current_car.water_d != 10000.0) { |
||
2499 | CreateSplash(&gProgram_state.current_car, 100); |
||
2500 | } |
||
2501 | } |
||
2502 | } else { |
||
2503 | for (type = eVehicle_net_player; type <= eVehicle_rozzer; type++) { |
||
2504 | for (i = 0;; i++) { |
||
2505 | if (i >= type ? GetCarCount(type) : 1) { |
||
2506 | break; |
||
2507 | } |
||
2508 | if (type) { |
||
2509 | car = GetCarSpec(type, i); |
||
2510 | } else { |
||
2511 | car = &gProgram_state.current_car; |
||
2512 | } |
||
2513 | if (car->water_d != 10000.0 && car->driver != eDriver_local_human) { |
||
2514 | CreateSplash(car, pTime); |
||
2515 | } |
||
2516 | } |
||
2517 | } |
||
2518 | if (gProgram_state.current_car.water_d != 10000.0) { |
||
2519 | CreateSplash(&gProgram_state.current_car, 0x64u); |
||
2520 | } |
||
2521 | } |
||
2522 | if (!gSplash_flags) { |
||
2523 | return; |
||
2524 | } |
||
2525 | for (i = 0; i < COUNT_OF(gSplash); i++) { |
||
2526 | if (((1u << i) & gSplash_flags) == 0) { |
||
2527 | continue; |
||
2528 | } |
||
2529 | if (gSplash[i].just_done || (gAction_replay_mode && GetReplayRate() == 0.0f)) { |
||
2530 | dt = gSplash[i].size * gSplash[i].scale_x; |
||
2531 | gSplash[i].actor->t.t.mat.m[0][0] = gCamera_to_world.m[0][0] * dt; |
||
2532 | gSplash[i].actor->t.t.mat.m[0][1] = gCamera_to_world.m[0][1] * dt; |
||
2533 | gSplash[i].actor->t.t.mat.m[0][2] = gCamera_to_world.m[0][2] * dt; |
||
2534 | gSplash[i].actor->t.t.mat.m[1][0] = gSplash[i].size * gCamera_to_world.m[1][0]; |
||
2535 | gSplash[i].actor->t.t.mat.m[1][1] = gSplash[i].size * gCamera_to_world.m[1][1]; |
||
2536 | gSplash[i].actor->t.t.mat.m[1][2] = gSplash[i].size * gCamera_to_world.m[1][2]; |
||
2537 | gSplash[i].actor->t.t.mat.m[2][0] = gSplash[i].size * gCamera_to_world.m[2][0]; |
||
2538 | gSplash[i].actor->t.t.mat.m[2][1] = gSplash[i].size * gCamera_to_world.m[2][1]; |
||
2539 | gSplash[i].actor->t.t.mat.m[2][2] = gSplash[i].size * gCamera_to_world.m[2][2]; |
||
2540 | if (gProgram_state.cockpit_on) { |
||
2541 | ts = sqrt(gCamera_to_world.m[0][2] * gCamera_to_world.m[0][2] + gCamera_to_world.m[0][0] * gCamera_to_world.m[0][0]); |
||
2542 | DRMatrix34PreRotateZ(&gSplash[i].actor->t.t.mat, -FastScalarArcTan2Angle(gCamera_to_world.m[0][1], ts)); |
||
2543 | } |
||
2544 | gSplash[i].just_done = 0; |
||
2545 | } else { |
||
2546 | gSplash_flags &= ~(1u << i); |
||
2547 | BrActorRemove(gSplash[i].actor); |
||
2548 | } |
||
2549 | } |
||
2550 | } |
||
2551 | |||
2552 | // IDA: void __cdecl RenderSplashes() |
||
2553 | void RenderSplashes(void) { |
||
2554 | int i; |
||
2555 | LOG_TRACE("()"); |
||
2556 | |||
2557 | for (i = 0; i < COUNT_OF(gSplash); i++) { |
||
2558 | if (gSplash_flags & (1u << i)) { |
||
2559 | BrActorRelink(gNon_track_actor, gSplash[i].actor); |
||
2560 | BrZbSceneRenderAdd(gSplash[i].actor); |
||
2561 | BrActorRelink(gDont_render_actor, gSplash[i].actor); |
||
2562 | } |
||
2563 | } |
||
2564 | } |
||
2565 | |||
2566 | // IDA: void __usercall GetSmokeShadeTables(FILE *f@<EAX>) |
||
2567 | void GetSmokeShadeTables(FILE* f) { |
||
2568 | int i; |
||
2569 | int red; |
||
2570 | int green; |
||
2571 | int blue; |
||
2572 | br_scalar quarter; |
||
2573 | br_scalar half; |
||
2574 | br_scalar three_quarter; |
||
2575 | LOG_TRACE("(%p)", f); |
||
2576 | |||
2577 | gNum_dust_tables = GetAnInt(f); |
||
2578 | if (gNum_dust_tables > 8) { |
||
2579 | gNum_dust_tables = 8; |
||
2580 | } |
||
2581 | for (i = 0; gNum_dust_tables > i; ++i) { |
||
2582 | PossibleService(); |
||
2583 | GetThreeInts(f, &red, &green, &blue); |
||
2584 | GetThreeScalars(f, &quarter, &half, &three_quarter); |
||
2585 | gDust_table[i] = GenerateShadeTable(16, gRender_palette, red, green, blue, quarter, half, three_quarter); |
||
2586 | } |
||
2587 | } |
||
2588 | |||
2589 | // IDA: void __cdecl FreeSmokeShadeTables() |
||
2590 | void FreeSmokeShadeTables(void) { |
||
2591 | int i; |
||
2592 | LOG_TRACE("()"); |
||
2593 | |||
2594 | for (i = 0; i < gNum_dust_tables; i++) { |
||
2595 | PossibleService(); |
||
2596 | BrTableRemove(gDust_table[i]); |
||
2597 | BrPixelmapFree(gDust_table[i]); |
||
2598 | } |
||
2599 | } |
||
2600 | |||
2601 | // IDA: void __usercall LoadInKevStuff(FILE *pF@<EAX>) |
||
2602 | void LoadInKevStuff(FILE* pF) { |
||
2603 | LOG_TRACE("(%p)", pF); |
||
2604 | |||
2605 | PossibleService(); |
||
2606 | LoadInShrapnel(); |
||
2607 | PossibleService(); |
||
2608 | InitShrapnel(); |
||
2609 | PossibleService(); |
||
2610 | InitFlame(); |
||
2611 | PossibleService(); |
||
2612 | InitSplash(pF); |
||
2613 | } |
||
2614 | |||
2615 | // IDA: void __cdecl DisposeKevStuff() |
||
2616 | void DisposeKevStuff(void) { |
||
2617 | LOG_TRACE("()"); |
||
2618 | |||
2619 | DisposeShrapnel(); |
||
2620 | DisposeFlame(); |
||
2621 | DisposeSplash(); |
||
2622 | } |
||
2623 | |||
2624 | // IDA: void __usercall DisposeKevStuffCar(tCar_spec *pCar@<EAX>) |
||
2625 | void DisposeKevStuffCar(tCar_spec* pCar) { |
||
2626 | int i; |
||
2627 | LOG_TRACE("(%p)", pCar); |
||
2628 | |||
2629 | for (i = 0; i < MAX_SMOKE_COLUMNS; i++) { |
||
2630 | if (gSmoke_column[i].car == pCar) { |
||
2631 | gSmoke_column[i].lifetime = 0; |
||
2632 | gSmoke_column[i].car = NULL; |
||
2633 | } |
||
2634 | } |
||
2635 | for (i = 0; i < COUNT_OF(gSparks); i++) { |
||
2636 | if ((gSpark_flags & (1u << i)) && gSparks[i].car == pCar) { |
||
2637 | gSparks[i].count = 0; |
||
2638 | gSpark_flags &= ~(1u << i); |
||
2639 | } |
||
2640 | if (gCar_to_view == pCar) { |
||
2641 | gCamera_yaw = 0; |
||
2642 | gCar_to_view = &gProgram_state.current_car; |
||
2643 | InitialiseExternalCamera(); |
||
2644 | PositionExternalCamera(gCar_to_view, 200); |
||
2645 | gCar_to_view = &gProgram_state.current_car; |
||
2646 | } |
||
2647 | } |
||
2648 | } |
||
2649 | |||
2650 | // IDA: void __cdecl DoTrueColModelThing(br_actor *actor, br_model *pModel, br_material *material, void *render_data, br_uint_8 style, int on_screen) |
||
2651 | void DoTrueColModelThing(br_actor* actor, br_model* pModel, br_material* material, void* render_data, br_uint_8 style, int on_screen) { |
||
18 | pmbaty | 2652 | int group; |
2653 | int j; |
||
2654 | int val; |
||
1 | pmbaty | 2655 | LOG_TRACE("(%p, %p, %p, %p, %d, %d)", actor, pModel, material, render_data, style, on_screen); |
2656 | NOT_IMPLEMENTED(); |
||
2657 | } |
||
2658 | |||
2659 | // IDA: void __cdecl DoModelThing(br_actor *actor, br_model *pModel, br_material *material, void *render_data, br_uint_8 style, int on_screen) |
||
2660 | void DoModelThing(br_actor* actor, br_model* pModel, br_material* material, void* render_data, br_uint_8 style, int on_screen) { |
||
18 | pmbaty | 2661 | int j; |
2662 | int i; |
||
2663 | int group; |
||
2664 | tU32 t; |
||
2665 | int val; |
||
1 | pmbaty | 2666 | LOG_TRACE("(%p, %p, %p, %p, %d, %d)", actor, pModel, material, render_data, style, on_screen); |
18 | pmbaty | 2667 | |
2668 | GetRaceTime(); |
||
2669 | for (group = 0; group < V11MODEL(pModel)->ngroups; group++) { |
||
2670 | for (j = 0; j < V11MODEL(pModel)->groups[group].nvertices; j++) { |
||
2671 | if (!(((V11MODEL(pModel)->groups[group].vertex_colours[j]) >> 24) & 1)) { |
||
2672 | if (((V11MODEL(pModel)->groups[group].vertex_colours[j]) >> 24) < 0xc9) { |
||
2673 | val = ((V11MODEL(pModel)->groups[group].vertex_colours[j]) >> 24) + 2 * IRandomBetween(5, 10); |
||
2674 | V11MODEL(pModel)->groups[group].vertex_colours[j] = BR_COLOUR_RGBA(0, 0, 0, val); |
||
2675 | if (pModel->flags & BR_MODF_UPDATEABLE) { |
||
2676 | pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = val; |
||
2677 | } |
||
2678 | } else { |
||
2679 | V11MODEL(pModel)->groups[group].vertex_colours[j] = BR_COLOUR_RGBA(0, 0, 0, 0xc9); |
||
2680 | if (pModel->flags & BR_MODF_UPDATEABLE) { |
||
2681 | pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = 0xc9; |
||
2682 | } |
||
2683 | } |
||
2684 | } else if ((V11MODEL(pModel)->groups[group].vertex_colours[j] >> 24) < 20) { |
||
2685 | V11MODEL(pModel)->groups[group].vertex_colours[j] = 0; |
||
2686 | if (pModel->flags & BR_MODF_UPDATEABLE) { |
||
2687 | pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = 0; |
||
2688 | } |
||
2689 | } else { |
||
2690 | val = ((V11MODEL(pModel)->groups[group].vertex_colours[j] >> 24) - 2 * IRandomBetween(5, 10)) << 24; |
||
2691 | V11MODEL(pModel)->groups[group].vertex_colours[j] = BR_COLOUR_RGBA(0, 0, 0, val); |
||
2692 | if (pModel->flags & BR_MODF_UPDATEABLE) { |
||
2693 | pModel->vertices[V11MODEL(pModel)->groups[group].vertex_user[j]].index = val; |
||
2694 | } |
||
2695 | } |
||
2696 | } |
||
2697 | } |
||
2698 | if ((pModel->flags & BR_MODF_UPDATEABLE) && pModel->user != NULL) { |
||
2699 | BrModelUpdate(pModel, BR_MODU_VERTEX_POSITIONS); |
||
2700 | } |
||
2701 | pModel->user = NULL; |
||
2702 | BrZbModelRender(actor, pModel, material, style, BrOnScreenCheck(&pModel->bounds), 0); |
||
1 | pmbaty | 2703 | } |
2704 | |||
2705 | // IDA: void __usercall SetModelShade(br_actor *pActor@<EAX>, br_pixelmap *pShade@<EDX>) |
||
2706 | void SetModelShade(br_actor* pActor, br_pixelmap* pShade) { |
||
2707 | int i; |
||
2708 | br_material* material; |
||
2709 | br_model* model; |
||
2710 | LOG_TRACE("(%p, %p)", pActor, pShade); |
||
2711 | |||
2712 | model = pActor->model; |
||
2713 | if (pActor->material != NULL && pActor->material->index_shade != pShade) { |
||
2714 | pActor->material->index_shade = pShade; |
||
2715 | BrMaterialUpdate(pActor->material, BR_MATU_ALL); |
||
2716 | } |
||
2717 | for (i = 0; i < model->nfaces; i++) { |
||
2718 | material = model->faces[i].material; |
||
2719 | if (material != NULL && material->index_shade != pShade) { |
||
2720 | material->index_shade = pShade; |
||
2721 | BrMaterialUpdate(material, BR_MATU_ALL); |
||
2722 | } |
||
2723 | } |
||
2724 | } |
||
2725 | |||
2726 | // IDA: void __usercall MakeCarIt(tCar_spec *pCar@<EAX>) |
||
2727 | void MakeCarIt(tCar_spec* pCar) { |
||
2728 | br_actor* actor; |
||
2729 | br_actor* bonny; |
||
2730 | br_pixelmap* shade[6]; |
||
2731 | static int shade_num = 0; |
||
2732 | //int i; // Pierre-Marie Baty -- unused variable |
||
2733 | LOG_TRACE("(%p)", pCar); |
||
2734 | |||
2735 | shade[0] = gIt_shade_table; |
||
2736 | shade[1] = gFog_shade_table; |
||
2737 | shade[2] = gShade_list[0]; |
||
2738 | shade[3] = gShade_list[1]; |
||
2739 | shade[4] = gShade_list[2]; |
||
2740 | shade[5] = NULL; |
||
2741 | |||
2742 | actor = pCar->car_model_actors[pCar->principal_car_actor].actor; |
||
2743 | bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor; |
||
18 | pmbaty | 2744 | if (!(actor->model->flags & BR_MODF_CUSTOM) || actor->model->custom != DoModelThing) { |
1 | pmbaty | 2745 | SetModelShade(actor, shade[shade_num]); |
18 | pmbaty | 2746 | actor->model->user = DoModelThing; |
2747 | actor->model->custom = DoModelThing; |
||
1 | pmbaty | 2748 | actor->model->flags |= BR_MODF_CUSTOM; |
2749 | if (bonny != actor) { |
||
18 | pmbaty | 2750 | bonny->model->user = DoModelThing; |
2751 | bonny->model->custom = DoModelThing; |
||
1 | pmbaty | 2752 | bonny->model->flags |= BR_MODF_CUSTOM; |
2753 | SetModelShade(bonny, shade[shade_num]); |
||
2754 | } |
||
2755 | } |
||
2756 | } |
||
2757 | |||
2758 | // IDA: void __usercall StopCarBeingIt(tCar_spec *pCar@<EAX>) |
||
2759 | void StopCarBeingIt(tCar_spec* pCar) { |
||
18 | pmbaty | 2760 | int i; |
2761 | int group; |
||
2762 | br_actor* actor; |
||
2763 | br_actor* bonny; |
||
1 | pmbaty | 2764 | LOG_TRACE("(%p)", pCar); |
18 | pmbaty | 2765 | |
2766 | actor = pCar->car_model_actors[pCar->principal_car_actor].actor; |
||
2767 | bonny = pCar->car_model_actors[pCar->car_actor_count - 1].actor; |
||
2768 | if (actor->model->custom == DoModelThing) { |
||
2769 | actor->model->flags &= ~BR_MODF_CUSTOM; |
||
2770 | SetModelShade(actor, gShade_list[0]); |
||
2771 | for (group = 0; group < V11MODEL(actor->model)->ngroups; group++) { |
||
2772 | for (i = 0; i < V11MODEL(actor->model)->groups[group].nvertices; i++) { |
||
2773 | V11MODEL(actor->model)->groups[group].vertex_colours[i] = 0; |
||
2774 | if (actor->model->flags & BR_MODF_UPDATEABLE) { |
||
2775 | actor->model->vertices[V11MODEL(actor->model)->groups[group].vertex_user[i]].index = 0; |
||
2776 | } |
||
2777 | } |
||
2778 | } |
||
2779 | SetModelForUpdate(actor->model, pCar, 0); |
||
2780 | if (bonny != actor) { |
||
2781 | bonny->model->flags &= ~BR_MODF_CUSTOM; |
||
2782 | SetModelShade(bonny, gShade_list[0]); |
||
2783 | for (group = 0; group < V11MODEL(bonny->model)->ngroups; group++) { |
||
2784 | for (i = 0; i < V11MODEL(bonny->model)->groups[group].nvertices; i++) { |
||
2785 | V11MODEL(bonny->model)->groups[group].vertex_colours[i] = 0; |
||
2786 | if (bonny->model->flags & BR_MODF_UPDATEABLE) { |
||
2787 | bonny->model->vertices[V11MODEL(bonny->model)->groups[group].vertex_user[i]].index = 0; |
||
2788 | } |
||
2789 | } |
||
2790 | } |
||
2791 | SetModelForUpdate(bonny->model, pCar, 0); |
||
2792 | } |
||
2793 | } |
||
1 | pmbaty | 2794 | } |