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 "finteray.h" |
18 | pmbaty | 2 | #include "brender.h" |
1 | pmbaty | 3 | #include "brucetrk.h" |
4 | #include "car.h" |
||
18 | pmbaty | 5 | #include "formats.h" |
1 | pmbaty | 6 | #include "globvars.h" |
7 | #include "harness/trace.h" |
||
8 | #include "raycast.h" |
||
9 | #include "world.h" |
||
10 | #include <math.h> |
||
11 | #include <stdlib.h> |
||
12 | |||
13 | int gPling_materials = 1; |
||
14 | br_material* gSub_material; |
||
15 | br_material* gReal_material; |
||
16 | int gNfaces; |
||
17 | br_matrix34 gPick_model_to_view__finteray; // suffix added to avoid duplicate symbol |
||
18 | int gTemp_group; |
||
19 | br_model* gNearest_model; |
||
20 | br_model* gSelected_model; |
||
21 | int gNearest_face_group; |
||
22 | int gNearest_face; |
||
23 | br_scalar gNearest_T; |
||
24 | tFace_ref* gPling_face; |
||
25 | |||
26 | // IDA: int __cdecl BadDiv(br_scalar a, br_scalar b) |
||
27 | // Suffix added to avoid duplicate symbol |
||
28 | int BadDiv__finteray(br_scalar a, br_scalar b) { |
||
29 | // LOG_TRACE("(%f, %f)", a, b); |
||
30 | |||
31 | return fabsf(b) < 1.0f && fabsf(a) > fabsf(b) * BR_SCALAR_MAX; |
||
32 | } |
||
33 | |||
34 | // IDA: void __usercall DRVector2AccumulateScale(br_vector2 *a@<EAX>, br_vector2 *b@<EDX>, br_scalar s) |
||
35 | // Suffix added to avoid duplicate symbol |
||
36 | void DRVector2AccumulateScale__finteray(br_vector2* a, br_vector2* b, br_scalar s) { |
||
37 | LOG_TRACE("(%p, %p, %f)", a, b, s); |
||
38 | |||
39 | a->v[0] = b->v[0] * s + a->v[0]; |
||
40 | a->v[1] = b->v[1] * s + a->v[1]; |
||
41 | } |
||
42 | |||
43 | // IDA: int __usercall PickBoundsTestRay@<EAX>(br_bounds *b@<EAX>, br_vector3 *rp@<EDX>, br_vector3 *rd@<EBX>, br_scalar t_near, br_scalar t_far, br_scalar *new_t_near, br_scalar *new_t_far) |
||
44 | // Suffix added to avoid duplicate symbol |
||
45 | int PickBoundsTestRay__finteray(br_bounds* b, br_vector3* rp, br_vector3* rd, br_scalar t_near, br_scalar t_far, br_scalar* new_t_near, br_scalar* new_t_far) { |
||
46 | int i; |
||
47 | float s; |
||
48 | float t; |
||
49 | LOG_TRACE("(%p, %p, %p, %f, %f, %p, %p)", b, rp, rd, t_near, t_far, new_t_near, new_t_far); |
||
50 | |||
51 | for (i = 0; i < 3; i++) { |
||
52 | if (rd->v[i] >= -0.00000023841858) { |
||
53 | if (rd->v[i] <= 0.00000023841858) { |
||
54 | if (b->max.v[i] < rp->v[i] || rp->v[i] < b->min.v[i]) { |
||
55 | return 0; |
||
56 | } |
||
57 | } else { |
||
58 | s = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); |
||
59 | if (s >= BR_SCALAR_MIN) { |
||
60 | if (s < t_far) { |
||
61 | t_far = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); |
||
62 | } |
||
63 | } else { |
||
64 | t_far = BR_SCALAR_MIN; |
||
65 | } |
||
66 | t = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); |
||
67 | if (t <= BR_SCALAR_MAX) { |
||
68 | if (t > t_near) { |
||
69 | t_near = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); |
||
70 | } |
||
71 | } else { |
||
72 | t_near = BR_SCALAR_MAX; |
||
73 | } |
||
74 | } |
||
75 | } else { |
||
76 | s = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); |
||
77 | if (s <= BR_SCALAR_MAX) { |
||
78 | if (s > t_near) { |
||
79 | t_near = (-1.0f / rd->v[i]) * (rp->v[i] - b->max.v[i]); |
||
80 | } |
||
81 | } else { |
||
82 | t_near = BR_SCALAR_MAX; |
||
83 | } |
||
84 | t = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); |
||
85 | if (t >= BR_SCALAR_MIN) { |
||
86 | if (t < t_far) { |
||
87 | t_far = (-1.0f / rd->v[i]) * (rp->v[i] - b->min.v[i]); |
||
88 | } |
||
89 | } else { |
||
90 | t_far = BR_SCALAR_MIN; |
||
91 | } |
||
92 | } |
||
93 | } |
||
94 | if (t_far < t_near) { |
||
95 | return 0; |
||
96 | } |
||
97 | *new_t_near = t_near; |
||
98 | *new_t_far = t_far; |
||
99 | return 1; |
||
100 | } |
||
101 | |||
102 | // IDA: int __usercall ActorRayPick2D@<EAX>(br_actor *ap@<EAX>, br_vector3 *pPosition@<EDX>, br_vector3 *pDir@<EBX>, br_model *model@<ECX>, br_material *material, dr_pick2d_cbfn *callback) |
||
103 | int ActorRayPick2D(br_actor* ap, br_vector3* pPosition, br_vector3* pDir, br_model* model, br_material* material, dr_pick2d_cbfn* callback) { |
||
104 | br_actor* a; |
||
105 | br_model* this_model; |
||
106 | br_material* this_material; |
||
107 | br_scalar t_near; |
||
108 | br_scalar t_far; |
||
109 | int r; |
||
110 | br_matrix34 mat; |
||
111 | br_matrix34 invmat; |
||
112 | br_vector3 pos; |
||
113 | br_vector3 dir; |
||
114 | void* arg; |
||
115 | LOG_TRACE("(%p, %p, %p, %p, %p, %p)", ap, pPosition, pDir, model, material, callback); |
||
116 | |||
117 | t_near = 0.0; |
||
118 | t_far = 1.0; |
||
119 | r = 0; |
||
120 | arg = NULL; |
||
121 | if (ap->model != NULL) { |
||
122 | this_model = ap->model; |
||
123 | } else { |
||
124 | this_model = model; |
||
125 | } |
||
126 | if (ap->material != NULL) { |
||
127 | this_material = ap->material; |
||
128 | } else { |
||
129 | this_material = material; |
||
130 | } |
||
131 | if (ap->render_style == BR_RSTYLE_NONE) { |
||
132 | return 0; |
||
133 | } |
||
134 | if (ap->identifier != NULL && ap->identifier[0] == '&') { |
||
135 | BrTransformToMatrix34(&mat, &ap->t); |
||
136 | BrMatrix34Inverse(&invmat, &mat); |
||
137 | BrMatrix34ApplyP(&pos, pPosition, &invmat); |
||
138 | BrMatrix34ApplyV(&dir, pDir, &invmat); |
||
139 | pPosition = &pos; |
||
140 | pDir = &dir; |
||
141 | } |
||
142 | if (ap->type == BR_ACTOR_MODEL) { |
||
143 | if (PickBoundsTestRay__finteray(&this_model->bounds, pPosition, pDir, t_near, t_far, &t_near, &t_far)) { |
||
144 | t_near = 0.0; |
||
145 | t_far = MIN(1.f, gNearest_T); |
||
146 | r = callback(ap, this_model, this_material, pPosition, pDir, t_near, t_far, arg); |
||
147 | if (r) { |
||
148 | return r; |
||
149 | } |
||
150 | } |
||
151 | if (r) { |
||
152 | return r; |
||
153 | } |
||
154 | } else if (ap->type >= BR_ACTOR_BOUNDS && ap->type <= BR_ACTOR_BOUNDS_CORRECT) { |
||
155 | if (PickBoundsTestRay__finteray((br_bounds*)ap->type_data, pPosition, pDir, t_near, t_far, &t_near, &t_far)) { |
||
156 | for (a = ap->children; a != NULL; a = a->next) { |
||
157 | r = ActorRayPick2D(a, pPosition, pDir, this_model, this_material, callback); |
||
158 | if (r) { |
||
159 | break; |
||
160 | } |
||
161 | } |
||
162 | } |
||
163 | return r; |
||
164 | } |
||
165 | for (a = ap->children; a != NULL; a = a->next) { |
||
166 | r = ActorRayPick2D(a, pPosition, pDir, this_model, this_material, callback); |
||
167 | if (r) { |
||
168 | break; |
||
169 | } |
||
170 | } |
||
171 | return r; |
||
172 | } |
||
173 | |||
174 | // IDA: int __usercall DRSceneRayPick2D@<EAX>(br_actor *world@<EAX>, br_vector3 *pPosition@<EDX>, br_vector3 *pDir@<EBX>, dr_pick2d_cbfn *callback@<ECX>) |
||
175 | int DRSceneRayPick2D(br_actor* world, br_vector3* pPosition, br_vector3* pDir, dr_pick2d_cbfn* callback) { |
||
176 | LOG_TRACE("(%p, %p, %p, %p)", world, pPosition, pDir, callback); |
||
177 | |||
178 | BrMatrix34Inverse(&gPick_model_to_view__finteray, &world->t.t.mat); |
||
179 | LOG_WARN_ONCE("Missing material and model pointers to ActorRayPick2D"); |
||
180 | return ActorRayPick2D(world, pPosition, pDir, NULL, NULL, callback); |
||
181 | } |
||
182 | |||
183 | // IDA: int __usercall DRModelPick2D@<EAX>(br_model *model@<EAX>, br_material *material@<EDX>, br_vector3 *ray_pos@<EBX>, br_vector3 *ray_dir@<ECX>, br_scalar t_near, br_scalar t_far, dr_modelpick2d_cbfn *callback, void *arg) |
||
184 | // Suffix added to avoid duplicate symbol |
||
185 | int DRModelPick2D__finteray(br_model* model, br_material* material, br_vector3* ray_pos, br_vector3* ray_dir, br_scalar t_near, br_scalar t_far, dr_modelpick2d_cbfn* callback, void* arg) { |
||
18 | pmbaty | 186 | // DR_FACE* fp; |
1 | pmbaty | 187 | int f; |
188 | int axis_m; |
||
189 | int axis_0; |
||
190 | int axis_1; |
||
191 | br_scalar t; |
||
18 | pmbaty | 192 | br_scalar n; |
1 | pmbaty | 193 | br_scalar d; |
194 | br_vector3 p; |
||
195 | float u0; |
||
196 | float u1; |
||
197 | float u2; |
||
198 | float v0; |
||
199 | float v1; |
||
200 | float v2; |
||
201 | br_scalar v0i1; |
||
202 | br_scalar v0i2; |
||
203 | float alpha; |
||
204 | float beta; |
||
205 | float f_d; |
||
206 | float f_n; |
||
207 | br_scalar s_alpha; |
||
208 | br_scalar s_beta; |
||
209 | br_vector2 map; |
||
210 | int v; |
||
211 | int e; |
||
212 | int r; |
||
213 | br_material* this_material; |
||
214 | br_scalar numerator; |
||
18 | pmbaty | 215 | float f_numerator; |
1 | pmbaty | 216 | int group; |
217 | LOG_TRACE("(%p, %p, %p, %p, %f, %f, %p, %p)", model, material, ray_pos, ray_dir, t_near, t_far, callback, arg); |
||
218 | |||
18 | pmbaty | 219 | struct v11group* grp_ptr; |
220 | br_vector4* eqn; |
||
221 | |||
1 | pmbaty | 222 | t_near -= 0.00001f; |
223 | t_far += 0.00001f; |
||
224 | for (group = 0; group < V11MODEL(model)->ngroups; group++) { |
||
18 | pmbaty | 225 | grp_ptr = &V11MODEL(model)->groups[group]; |
1 | pmbaty | 226 | for (f = 0; f < V11MODEL(model)->groups[group].nfaces; f++) { |
18 | pmbaty | 227 | eqn = &V11MODEL(model)->groups[group].eqn[f]; |
228 | if (V11MODEL(model)->groups[group].user) { |
||
229 | this_material = V11MODEL(model)->groups[group].user; |
||
1 | pmbaty | 230 | } else { |
231 | this_material = material; |
||
232 | } |
||
18 | pmbaty | 233 | d = BrVector3Dot(eqn, ray_dir); |
1 | pmbaty | 234 | if (fabs(d) >= 0.00000023841858 && (!this_material || !this_material->identifier || *this_material->identifier != '!' || !gPling_materials) |
235 | && (!this_material || (this_material->flags & 0x1800) != 0 || d <= 0.0)) { |
||
18 | pmbaty | 236 | numerator = eqn->v[1] * ray_pos->v[1] |
237 | + eqn->v[2] * ray_pos->v[2] |
||
238 | + eqn->v[0] * ray_pos->v[0] |
||
239 | - eqn->v[3]; |
||
1 | pmbaty | 240 | if (!BadDiv__finteray(numerator, d)) { |
241 | t = -(numerator / d); |
||
242 | if (t >= t_near && t <= t_far) { |
||
243 | BrVector3Scale(&p, ray_dir, t); |
||
244 | BrVector3Accumulate(&p, ray_pos); |
||
18 | pmbaty | 245 | axis_m = fabsf(eqn->v[0]) < fabsf(eqn->v[1]); |
246 | if (fabsf(eqn->v[2]) > fabsf(eqn->v[axis_m])) { |
||
1 | pmbaty | 247 | axis_m = 2; |
248 | } |
||
249 | if (axis_m) { |
||
250 | axis_0 = 0; |
||
251 | if (axis_m == 1) { |
||
252 | axis_1 = 2; |
||
253 | } else { |
||
254 | axis_1 = 1; |
||
255 | } |
||
256 | } else { |
||
257 | axis_0 = 1; |
||
258 | axis_1 = 2; |
||
259 | } |
||
260 | |||
18 | pmbaty | 261 | v0 = grp_ptr->position[grp_ptr->vertex_numbers[f].v[0]].v[axis_0]; |
262 | u0 = grp_ptr->position[grp_ptr->vertex_numbers[f].v[0]].v[axis_1]; |
||
263 | v1 = grp_ptr->position[grp_ptr->vertex_numbers[f].v[1]].v[axis_0] - v0; |
||
264 | u1 = grp_ptr->position[grp_ptr->vertex_numbers[f].v[1]].v[axis_1] - u0; |
||
265 | v2 = grp_ptr->position[grp_ptr->vertex_numbers[f].v[2]].v[axis_0] - v0; |
||
266 | u2 = grp_ptr->position[grp_ptr->vertex_numbers[f].v[2]].v[axis_1] - u0; |
||
1 | pmbaty | 267 | |
268 | v0i1 = p.v[axis_0] - v0; |
||
269 | v0i2 = p.v[axis_1] - u0; |
||
270 | if (fabs(v1) > 0.0000002384185791015625) { |
||
271 | f_n = u2 * v1 - u1 * v2; |
||
272 | f_d = v0i2 * v1 - u1 * v0i1; |
||
273 | if (fabs(f_n) < fabs(f_d)) { |
||
274 | continue; |
||
275 | } |
||
276 | if (f_n == 0) { |
||
277 | continue; |
||
278 | } |
||
279 | beta = f_d / f_n; |
||
280 | if (beta < 0.0 || beta > 1.0 || v1 == 0.0) { |
||
281 | continue; |
||
282 | } |
||
283 | alpha = (v0i1 - beta * v2) / v1; |
||
284 | } else { |
||
285 | if (fabsf(v2) < fabsf(v0i1)) { |
||
286 | continue; |
||
287 | } |
||
288 | if (v2 == 0) { |
||
289 | continue; |
||
290 | } |
||
291 | |||
292 | beta = v0i1 / v2; |
||
293 | if (beta < 0.0 || beta > 1.0 || u1 == 0.0) { |
||
294 | continue; |
||
295 | } |
||
296 | alpha = (v0i2 - beta * u2) / u1; |
||
297 | } |
||
298 | |||
299 | if (alpha >= 0.0 && beta + alpha <= 1.0) { |
||
300 | s_alpha = alpha; |
||
301 | s_beta = beta; |
||
18 | pmbaty | 302 | BrVector2Scale(&map, &grp_ptr->map[grp_ptr->vertex_numbers[f].v[1]], s_alpha); |
1 | pmbaty | 303 | DRVector2AccumulateScale__finteray( |
304 | &map, |
||
18 | pmbaty | 305 | &grp_ptr->map[grp_ptr->vertex_numbers[f].v[2]], |
1 | pmbaty | 306 | s_beta); |
307 | DRVector2AccumulateScale__finteray( |
||
308 | &map, |
||
18 | pmbaty | 309 | &grp_ptr->map[grp_ptr->vertex_numbers[f].v[0]], |
1 | pmbaty | 310 | 1.0 - (s_alpha + s_beta)); |
311 | v = 0; |
||
312 | e = 1; |
||
313 | if (s_alpha <= s_beta) { |
||
314 | if (0.5 - s_beta / 2.0 > s_alpha) { |
||
315 | e = 0; |
||
316 | } |
||
317 | if (1.0 - s_beta * 2.0 < s_alpha) { |
||
318 | v = 1; |
||
319 | } |
||
320 | } else { |
||
321 | if (1.0 - s_beta * 2.0 > s_alpha) { |
||
322 | e = 2; |
||
323 | } |
||
324 | if (0.5 - s_beta / 2.0 < s_alpha) { |
||
325 | v = 2; |
||
326 | } |
||
327 | } |
||
328 | gTemp_group = group; |
||
329 | r = callback(model, this_material, ray_pos, ray_dir, t, f, e, v, &p, &map, arg); |
||
330 | if (r) { |
||
331 | return r; |
||
332 | } |
||
333 | } |
||
334 | } |
||
335 | } |
||
336 | } |
||
337 | } |
||
338 | } |
||
339 | return 0; |
||
340 | } |
||
341 | |||
342 | // IDA: int __cdecl FindHighestPolyCallBack(br_model *pModel, br_material *pMaterial, br_vector3 *pRay_pos, br_vector3 *pRay_dir, br_scalar pT, int pF, int pE, int pV, br_vector3 *pPoint, br_vector2 *pMap, void *pArg) |
||
343 | // Suffix added to avoid duplicate symbol |
||
344 | int FindHighestPolyCallBack__finteray(br_model* pModel, br_material* pMaterial, br_vector3* pRay_pos, br_vector3* pRay_dir, br_scalar pT, int pF, int pE, int pV, br_vector3* pPoint, br_vector2* pMap, void* pArg) { |
||
345 | LOG_TRACE("(%p, %p, %p, %p, %f, %d, %d, %d, %p, %p, %p)", pModel, pMaterial, pRay_pos, pRay_dir, pT, pF, pE, pV, pPoint, pMap, pArg); |
||
346 | |||
347 | if (pT < (double)gNearest_T) { |
||
348 | gNearest_T = pT; |
||
349 | gNearest_model = pModel; |
||
350 | gNearest_face = pF; |
||
351 | gNearest_face_group = gTemp_group; |
||
352 | } |
||
353 | return 0; |
||
354 | } |
||
355 | |||
356 | // IDA: int __cdecl FindHighestCallBack(br_actor *pActor, br_model *pModel, br_material *pMaterial, br_vector3 *pRay_pos, br_vector3 *pRay_dir, br_scalar pT_near, br_scalar pT_far, void *pArg) |
||
357 | // Suffix added to avoid duplicate symbol |
||
358 | int FindHighestCallBack__finteray(br_actor* pActor, br_model* pModel, br_material* pMaterial, br_vector3* pRay_pos, br_vector3* pRay_dir, br_scalar pT_near, br_scalar pT_far, void* pArg) { |
||
359 | LOG_TRACE("(%p, %p, %p, %p, %p, %f, %f, %p)", pActor, pModel, pMaterial, pRay_pos, pRay_dir, pT_near, pT_far, pArg); |
||
360 | |||
361 | if (gProgram_state.current_car.current_car_actor < 0 |
||
362 | || gProgram_state.current_car.car_model_actors[gProgram_state.current_car.current_car_actor].actor != pActor) { |
||
363 | DRModelPick2D__finteray(pModel, pMaterial, pRay_pos, pRay_dir, pT_near, pT_far, FindHighestPolyCallBack__finteray, pArg); |
||
364 | } |
||
365 | return 0; |
||
366 | } |
||
367 | |||
368 | // IDA: void __usercall FindFace(br_vector3 *pPosition@<EAX>, br_vector3 *pDir@<EDX>, br_vector3 *nor@<EBX>, br_scalar *t@<ECX>, br_material **material) |
||
369 | void FindFace(br_vector3* pPosition, br_vector3* pDir, br_vector3* nor, br_scalar* t, br_material** material) { |
||
370 | int group; |
||
371 | LOG_TRACE("(%p, %p, %p, %p, %p)", pPosition, pDir, nor, t, material); |
||
372 | |||
18 | pmbaty | 373 | br_vector4* eqn; |
374 | |||
1 | pmbaty | 375 | gNearest_T = 100.0f; |
376 | DRSceneRayPick2D(gTrack_actor, pPosition, pDir, FindHighestCallBack__finteray); |
||
377 | *t = gNearest_T; |
||
378 | if (*t < 100.0f) { |
||
379 | group = gNearest_face_group; |
||
18 | pmbaty | 380 | eqn = &V11MODEL(gNearest_model)->groups[group].eqn[gNearest_face]; |
381 | nor->v[0] = eqn->v[0]; |
||
382 | nor->v[1] = eqn->v[1]; |
||
383 | nor->v[2] = eqn->v[2]; |
||
384 | *material = V11MODEL(gNearest_model)->groups[group].user; |
||
1 | pmbaty | 385 | } |
386 | } |
||
387 | |||
388 | // IDA: void __cdecl EnablePlingMaterials() |
||
389 | void EnablePlingMaterials(void) { |
||
390 | LOG_TRACE("()"); |
||
391 | |||
392 | gPling_materials = 1; |
||
393 | } |
||
394 | |||
395 | // IDA: void __cdecl DisablePlingMaterials() |
||
396 | void DisablePlingMaterials(void) { |
||
397 | LOG_TRACE("()"); |
||
398 | |||
399 | gPling_materials = 0; |
||
400 | } |
||
401 | |||
402 | // IDA: void __usercall CheckSingleFace(tFace_ref *pFace@<EAX>, br_vector3 *ray_pos@<EDX>, br_vector3 *ray_dir@<EBX>, br_vector3 *normal@<ECX>, br_scalar *rt) |
||
403 | void CheckSingleFace(tFace_ref* pFace, br_vector3* ray_pos, br_vector3* ray_dir, br_vector3* normal, br_scalar* rt) { |
||
404 | br_scalar t; |
||
405 | br_scalar numerator; |
||
406 | br_scalar d; |
||
407 | br_vector3 p; |
||
408 | br_vector3 tv; |
||
409 | int axis_m; |
||
410 | int axis_0; |
||
411 | int axis_1; |
||
412 | double u0; |
||
413 | double u1; |
||
414 | double u2; |
||
415 | double v0; |
||
416 | double v1; |
||
417 | double v2; |
||
418 | br_scalar v0i1; |
||
419 | br_scalar v0i2; |
||
420 | double alpha; |
||
421 | double beta; |
||
422 | double f_d; |
||
423 | //double f_n; // Pierre-Marie Baty -- unused variable |
||
424 | //double f_numerator; // Pierre-Marie Baty -- unused variable |
||
425 | br_material* this_material; |
||
426 | LOG_TRACE("(%p, %p, %p, %p, %p)", pFace, ray_pos, ray_dir, normal, rt); |
||
427 | |||
428 | this_material = pFace->material; |
||
429 | *rt = 100.0; |
||
430 | |||
431 | d = pFace->normal.v[1] * ray_dir->v[1] + ray_dir->v[2] * pFace->normal.v[2] + ray_dir->v[0] * pFace->normal.v[0]; |
||
18 | pmbaty | 432 | if ((this_material == NULL || (this_material->flags & (BR_MATF_TWO_SIDED | BR_MATF_ALWAYS_VISIBLE)) != 0 || d <= 0.0) |
1 | pmbaty | 433 | && (!this_material || !this_material->identifier || *this_material->identifier != '!' || !gPling_materials) |
434 | && fabs(d) >= 0.00000023841858) { |
||
435 | BrVector3Sub(&p, ray_pos, &pFace->v[0]); |
||
436 | numerator = BrVector3Dot(&pFace->normal, &p); |
||
437 | if (!BadDiv__finteray(numerator, d)) { |
||
438 | if (d > 0.0) { |
||
439 | if (-numerator < -0.001 || -numerator > d + 0.003) { |
||
440 | return; |
||
441 | } |
||
442 | } else if (numerator < -0.001 || 0.003 - d < numerator) { |
||
443 | return; |
||
444 | } |
||
445 | t = -(numerator / d); |
||
446 | if (t > 1.0) { |
||
447 | t = 1.0; |
||
448 | } |
||
449 | BrVector3Scale(&tv, ray_dir, t); |
||
450 | BrVector3Accumulate(&tv, ray_pos); |
||
451 | axis_m = fabs(pFace->normal.v[0]) < fabs(pFace->normal.v[1]); |
||
452 | if (fabs(pFace->normal.v[2]) > fabs(pFace->normal.v[axis_m])) { |
||
453 | axis_m = 2; |
||
454 | } |
||
455 | if (axis_m) { |
||
456 | axis_0 = 0; |
||
457 | if (axis_m == 1) { |
||
458 | axis_1 = 2; |
||
459 | } else { |
||
460 | axis_1 = 1; |
||
461 | } |
||
462 | } else { |
||
463 | axis_0 = 1; |
||
464 | axis_1 = 2; |
||
465 | } |
||
466 | v0i1 = pFace->v[0].v[axis_0]; |
||
467 | v0i2 = pFace->v[0].v[axis_1]; |
||
468 | u0 = pFace->v[1].v[axis_0] - v0i1; |
||
469 | u1 = pFace->v[1].v[axis_1] - v0i2; |
||
470 | v0 = pFace->v[2].v[axis_0] - v0i1; |
||
471 | v1 = pFace->v[2].v[axis_1] - v0i2; |
||
472 | u2 = tv.v[axis_0] - v0i1; |
||
473 | v2 = tv.v[axis_1] - v0i2; |
||
474 | if (fabs(u0) > 0.0000002384185791015625) { |
||
475 | f_d = v1 * u0 - u1 * v0; |
||
476 | if (f_d == 0) { |
||
477 | return; |
||
478 | } |
||
479 | alpha = (v2 * u0 - u1 * u2) / f_d; |
||
480 | beta = (u2 - alpha * v0) / u0; |
||
481 | } else { |
||
482 | alpha = u2 / v0; |
||
483 | beta = (v2 - alpha * v1) / u1; |
||
484 | } |
||
485 | if (beta >= -0.0001 && alpha >= -0.0001 && alpha + beta <= 1.0001) { |
||
486 | *rt = t; |
||
487 | *normal = pFace->normal; |
||
488 | if (d > 0.0) { |
||
489 | BrVector3Negate(normal, normal); |
||
490 | } |
||
491 | } |
||
492 | } |
||
493 | } |
||
494 | } |
||
495 | |||
496 | // IDA: void __usercall MultiRayCheckSingleFace(int pNum_rays@<EAX>, tFace_ref *pFace@<EDX>, br_vector3 *ray_pos@<EBX>, br_vector3 *ray_dir@<ECX>, br_vector3 *normal, br_scalar *rt) |
||
497 | void MultiRayCheckSingleFace(int pNum_rays, tFace_ref* pFace, br_vector3* ray_pos, br_vector3* ray_dir, br_vector3* normal, br_scalar* rt) { |
||
498 | int i; |
||
499 | br_scalar t[4]; |
||
500 | br_scalar numerator; |
||
501 | br_scalar d; |
||
502 | br_vector3 p[4]; |
||
503 | br_vector3 tv; |
||
504 | int axis_m; |
||
505 | int axis_0; |
||
506 | int axis_1; |
||
507 | double u0[4]; |
||
508 | double u1; |
||
509 | double u2; |
||
510 | double v0[4]; |
||
511 | double v1; |
||
512 | double v2; |
||
513 | br_scalar v0i1; |
||
514 | br_scalar v0i2; |
||
515 | double alpha; |
||
516 | double beta; |
||
517 | double f_d; |
||
518 | double f_n; |
||
519 | double f_numerator; |
||
520 | br_material* this_material; |
||
521 | LOG_TRACE("(%d, %p, %p, %p, %p, %p)", pNum_rays, pFace, ray_pos, ray_dir, normal, rt); |
||
522 | |||
523 | this_material = pFace->material; |
||
524 | d = ray_dir->v[2] * pFace->normal.v[2] + ray_dir->v[1] * pFace->normal.v[1] + ray_dir->v[0] * pFace->normal.v[0]; |
||
525 | for (i = 0; i < pNum_rays; ++i) { |
||
526 | rt[i] = 100.0; |
||
527 | } |
||
528 | if ((!this_material || (this_material->flags & 0x1800) != 0 || d <= 0.0) |
||
529 | && (!this_material || !this_material->identifier || *this_material->identifier != '!' || !gPling_materials) |
||
530 | && fabs(d) >= 0.00000023841858) { |
||
531 | for (i = 0;; ++i) { |
||
532 | if (i >= pNum_rays) { |
||
533 | axis_m = fabs(pFace->normal.v[0]) < fabs(pFace->normal.v[1]); |
||
534 | if (fabs(pFace->normal.v[2]) > fabs(pFace->normal.v[axis_m])) { |
||
535 | axis_m = 2; |
||
536 | } |
||
537 | if (axis_m) { |
||
538 | axis_0 = 0; |
||
539 | if (axis_m == 1) { |
||
540 | axis_1 = 2; |
||
541 | } else { |
||
542 | axis_1 = 1; |
||
543 | } |
||
544 | } else { |
||
545 | axis_0 = 1; |
||
546 | axis_1 = 2; |
||
547 | } |
||
548 | v0i1 = pFace->v[0].v[axis_0]; |
||
549 | v0i2 = pFace->v[0].v[axis_1]; |
||
550 | u1 = pFace->v[1].v[axis_0] - v0i1; |
||
551 | v1 = pFace->v[1].v[axis_1] - v0i2; |
||
552 | u2 = pFace->v[2].v[axis_0] - v0i1; |
||
553 | v2 = pFace->v[2].v[axis_1] - v0i2; |
||
554 | i = 0; |
||
555 | while (1) { |
||
556 | if (i >= pNum_rays) { |
||
557 | return; |
||
558 | } |
||
559 | if (t[i] != 100.0) { |
||
560 | u0[i] = p[i].v[axis_0] - v0i1; |
||
561 | v0[i] = p[i].v[axis_1] - v0i2; |
||
562 | if (fabs(u1) <= 0.0000002384185791015625) { |
||
563 | alpha = u0[i] / u2; |
||
564 | beta = v0[i] - alpha * v2; |
||
565 | f_d = beta / v1; |
||
566 | goto LABEL_43; |
||
567 | } |
||
568 | f_numerator = v0[i] * u1 - u0[i] * v1; |
||
569 | f_n = v2 * u1 - v1 * u2; |
||
570 | if (f_n != 0) { |
||
571 | alpha = f_numerator / f_n; |
||
572 | beta = u0[i] - alpha * u2; |
||
573 | f_d = beta / u1; |
||
574 | LABEL_43: |
||
575 | if (f_d >= -0.0001 && alpha >= -0.0001 && alpha + f_d <= 1.0001) { |
||
576 | rt[i] = t[i]; |
||
577 | *normal = pFace->normal; |
||
578 | if (d > 0.0) { |
||
579 | normal->v[0] = -pFace->normal.v[0]; |
||
580 | normal->v[1] = -pFace->normal.v[1]; |
||
581 | normal->v[2] = -pFace->normal.v[2]; |
||
582 | } |
||
583 | } |
||
584 | } |
||
585 | } |
||
586 | ++i; |
||
587 | continue; |
||
588 | } |
||
589 | } |
||
590 | tv.v[0] = ray_pos[i].v[0] - pFace->v[0].v[0]; |
||
591 | tv.v[1] = ray_pos[i].v[1] - pFace->v[0].v[1]; |
||
592 | tv.v[2] = ray_pos[i].v[2] - pFace->v[0].v[2]; |
||
593 | numerator = pFace->normal.v[2] * tv.v[2] + pFace->normal.v[1] * tv.v[1] + pFace->normal.v[0] * tv.v[0]; |
||
594 | if (BadDiv__finteray(numerator, d)) { |
||
595 | return; |
||
596 | } |
||
597 | if (d > 0.0) { |
||
598 | if (-numerator < -0.001 || -numerator > d + 0.003) { |
||
599 | t[i] = 100.0; |
||
600 | continue; |
||
601 | } |
||
602 | } else if (numerator < -0.001 || 0.003 - d < numerator) { |
||
603 | t[i] = 100.0; |
||
604 | continue; |
||
605 | } |
||
606 | t[i] = -(numerator / d); |
||
607 | if (t[i] > 1.0) { |
||
608 | t[i] = 1.0; |
||
609 | } |
||
610 | p[i].v[0] = t[i] * ray_dir->v[0]; |
||
611 | p[i].v[1] = t[i] * ray_dir->v[1]; |
||
612 | p[i].v[2] = t[i] * ray_dir->v[2]; |
||
613 | p[i].v[0] = ray_pos[i].v[0] + p[i].v[0]; |
||
614 | p[i].v[1] = ray_pos[i].v[1] + p[i].v[1]; |
||
615 | p[i].v[2] = ray_pos[i].v[2] + p[i].v[2]; |
||
616 | } |
||
617 | } |
||
618 | } |
||
619 | |||
620 | // IDA: void __usercall GetNewBoundingBox(br_bounds *b2@<EAX>, br_bounds *b1@<EDX>, br_matrix34 *m@<EBX>) |
||
621 | void GetNewBoundingBox(br_bounds* b2, br_bounds* b1, br_matrix34* m) { |
||
622 | br_vector3 a; |
||
623 | br_vector3 c[3]; |
||
624 | int j; |
||
625 | LOG_TRACE("(%p, %p, %p)", b2, b1, m); |
||
626 | |||
627 | BrMatrix34ApplyP(&b2->min, &b1->min, m); |
||
628 | BrVector3Copy(&b2->max, &b2->min); |
||
629 | BrVector3Sub(&a, &b1->max, &b1->min); |
||
630 | for (j = 0; j < 3; j++) { |
||
631 | BrVector3Scale(&c[j], (br_vector3*)m->m[j], a.v[j]); |
||
632 | } |
||
633 | for (j = 0; j < 3; ++j) { |
||
634 | b2->min.v[j] = (float)(c[2].v[j] < 0.f) * c[2].v[j] |
||
635 | + (float)(c[1].v[j] < 0.f) * c[1].v[j] |
||
636 | + (float)(c[0].v[j] < 0.f) * c[0].v[j] |
||
637 | + b2->min.v[j]; |
||
638 | b2->max.v[j] = (float)(c[0].v[j] > 0.f) * c[0].v[j] |
||
639 | + (float)(c[2].v[j] > 0.f) * c[2].v[j] |
||
640 | + (float)(c[1].v[j] > 0.f) * c[1].v[j] |
||
641 | + b2->max.v[j]; |
||
642 | } |
||
643 | } |
||
644 | |||
645 | // IDA: int __usercall FindFacesInBox@<EAX>(tBounds *bnds@<EAX>, tFace_ref *face_list@<EDX>, int max_face@<EBX>) |
||
646 | int FindFacesInBox(tBounds* bnds, tFace_ref* face_list, int max_face) { |
||
647 | br_vector3 a; |
||
648 | br_vector3 b; |
||
649 | br_vector3 c[3]; |
||
650 | int i; |
||
651 | int j; |
||
652 | int x; |
||
653 | int z; |
||
654 | tU8 cx_min; |
||
655 | tU8 cx_max; |
||
656 | tU8 cz_min; |
||
657 | tU8 cz_max; |
||
658 | tTrack_spec* track_spec; |
||
659 | LOG_TRACE("(%p, %p, %d)", bnds, face_list, max_face); |
||
660 | |||
661 | j = 0; |
||
662 | track_spec = &gProgram_state.track_spec; |
||
663 | BrVector3Add(&a, &bnds->original_bounds.min, &bnds->original_bounds.max); |
||
664 | BrVector3Scale(&a, &a, 0.5f); |
||
665 | BrMatrix34ApplyP(&bnds->box_centre, &a, bnds->mat); |
||
666 | BrVector3Sub(&b, &bnds->original_bounds.max, &bnds->original_bounds.min); |
||
667 | bnds->radius = BrVector3Length(&b) / 2.f; |
||
668 | BrMatrix34ApplyP(&bnds->real_bounds.min, &bnds->original_bounds.min, bnds->mat); |
||
669 | BrVector3Copy(&bnds->real_bounds.max, &bnds->real_bounds.min); |
||
670 | for (i = 0; i < 3; ++i) { |
||
671 | c[i].v[0] = bnds->mat->m[i][0] * b.v[i]; |
||
672 | c[i].v[1] = bnds->mat->m[i][1] * b.v[i]; |
||
673 | c[i].v[2] = bnds->mat->m[i][2] * b.v[i]; |
||
674 | } |
||
675 | for (i = 0; i < 3; ++i) { |
||
676 | bnds->real_bounds.min.v[i] += MIN(c[0].v[i], 0.f) |
||
677 | + MIN(c[1].v[i], 0.f) |
||
678 | + MIN(c[2].v[i], 0.f); |
||
679 | bnds->real_bounds.max.v[i] += MAX(c[0].v[i], 0.f) |
||
680 | + MAX(c[1].v[i], 0.f) |
||
681 | + MAX(c[2].v[i], 0.f); |
||
682 | } |
||
683 | XZToColumnXZ(&cx_min, &cz_min, bnds->real_bounds.min.v[0], bnds->real_bounds.min.v[2], track_spec); |
||
684 | XZToColumnXZ(&cx_max, &cz_max, bnds->real_bounds.max.v[0], bnds->real_bounds.max.v[2], track_spec); |
||
685 | if (cx_min != 0) { |
||
686 | cx_min--; |
||
687 | } |
||
688 | if (cz_min != 0) { |
||
689 | cz_min--; |
||
690 | } |
||
691 | if (cx_max + 1 < track_spec->ncolumns_x) { |
||
692 | cx_max++; |
||
693 | } |
||
694 | if (cz_max + 1 < track_spec->ncolumns_z) { |
||
695 | cz_max++; |
||
696 | } |
||
697 | for (x = cx_min; x <= cx_max; x++) { |
||
698 | for (z = cz_min; z <= cz_max; z++) { |
||
699 | if (track_spec->columns[z][x] != NULL) { |
||
700 | if (track_spec->blends[z][x] != NULL) { |
||
701 | track_spec->blends[z][x]->render_style = BR_RSTYLE_FACES; |
||
702 | } |
||
703 | j = max_face - ActorBoxPick(bnds, track_spec->columns[z][x], model_unk1, material_unk1, &face_list[j], max_face - j, NULL); |
||
704 | if (track_spec->blends[z][x] != NULL) { |
||
705 | track_spec->blends[z][x]->render_style = BR_RSTYLE_NONE; |
||
706 | } |
||
707 | } |
||
708 | if (track_spec->lollipops[z][x] != NULL) { |
||
709 | j = max_face - ActorBoxPick(bnds, track_spec->lollipops[z][x], model_unk1, material_unk1, &face_list[j], max_face - j, NULL); |
||
710 | } |
||
711 | } |
||
712 | } |
||
713 | return j; |
||
714 | } |
||
715 | |||
716 | // IDA: int __usercall FindFacesInBox2@<EAX>(tBounds *bnds@<EAX>, tFace_ref *face_list@<EDX>, int max_face@<EBX>) |
||
717 | int FindFacesInBox2(tBounds* bnds, tFace_ref* face_list, int max_face) { |
||
18 | pmbaty | 718 | br_vector3 a; |
719 | br_vector3 b; |
||
720 | br_vector3 c[3]; |
||
721 | int i; |
||
722 | int j; |
||
1 | pmbaty | 723 | LOG_TRACE("(%p, %p, %d)", bnds, face_list, max_face); |
18 | pmbaty | 724 | |
725 | a.v[0] = (bnds->original_bounds.min.v[0] + bnds->original_bounds.max.v[0]) * .5f; |
||
726 | a.v[1] = (bnds->original_bounds.min.v[1] + bnds->original_bounds.max.v[1]) * .5f; |
||
727 | a.v[2] = (bnds->original_bounds.min.v[2] + bnds->original_bounds.max.v[2]) * .5f; |
||
728 | BrMatrix34ApplyP(&bnds->box_centre, &a, bnds->mat); |
||
729 | BrVector3Sub(&b, &bnds->original_bounds.max, &bnds->original_bounds.min); |
||
730 | bnds->radius = BrVector3Length(&b) / 2.f; |
||
731 | BrMatrix34ApplyP(&bnds->real_bounds.min, &bnds->original_bounds.min, bnds->mat); |
||
732 | BrVector3Copy(&bnds->real_bounds.max, &bnds->real_bounds.min); |
||
733 | for (i = 0; i < 3; i++) { |
||
734 | BrVector3Scale(&c[i], (br_vector3*)bnds->mat->m[i], b.v[i]); |
||
735 | } |
||
736 | for (i = 0; i < 3; i++) { |
||
737 | bnds->real_bounds.min.v[i] += MIN(0.f, c[0].v[i]) + MIN(0.f, c[1].v[i]) + MIN(0.f, c[2].v[i]); |
||
738 | bnds->real_bounds.max.v[i] += MAX(0.f, c[0].v[i]) + MAX(0.f, c[1].v[i]) + MAX(0.f, c[2].v[i]); |
||
739 | } |
||
740 | return max_face - ActorBoxPick(bnds, gTrack_actor, model_unk1, material_unk1, face_list, max_face, NULL); |
||
1 | pmbaty | 741 | } |
742 | |||
743 | // IDA: int __usercall ActorBoxPick@<EAX>(tBounds *bnds@<EAX>, br_actor *ap@<EDX>, br_model *model@<EBX>, br_material *material@<ECX>, tFace_ref *face_list, int max_face, br_matrix34 *pMat) |
||
744 | int ActorBoxPick(tBounds* bnds, br_actor* ap, br_model* model, br_material* material, tFace_ref* face_list, int max_face, br_matrix34* pMat) { |
||
745 | br_model* this_model; |
||
746 | br_material* this_material; |
||
747 | int i; |
||
748 | int n; |
||
749 | int test_children; |
||
750 | br_actor* a; |
||
751 | br_actor* next_a; |
||
752 | br_matrix34 mat; |
||
753 | br_matrix34 mat2; |
||
754 | br_matrix34 invmat; |
||
755 | br_matrix34 box_to_actor; |
||
756 | tBounds new_bounds; |
||
757 | br_bounds br_bnds; |
||
758 | LOG_TRACE("(%p, %p, %p, %p, %p, %d, %p)", bnds, ap, model, material, face_list, max_face, pMat); |
||
759 | |||
760 | i = 0; |
||
761 | test_children = 1; |
||
762 | if (ap->model != NULL) { |
||
763 | this_model = ap->model; |
||
764 | } else { |
||
765 | this_model = model; |
||
766 | } |
||
767 | if (ap->material != NULL) { |
||
768 | this_material = ap->material; |
||
769 | } else { |
||
770 | this_material = material; |
||
771 | } |
||
772 | if (ap->render_style == BR_RSTYLE_NONE) { |
||
773 | return max_face; |
||
774 | } |
||
775 | if (ap->identifier != NULL && ap->identifier[0] == '&') { |
||
776 | if (ap->children == NULL) { |
||
777 | if (ap->type != BR_ACTOR_MODEL) { |
||
778 | return max_face; |
||
779 | } |
||
780 | if (!BoundsTransformTest(&this_model->bounds, &bnds->real_bounds, &ap->t.t.mat)) { |
||
781 | return max_face; |
||
782 | } |
||
783 | } |
||
784 | if (pMat != NULL) { |
||
785 | BrMatrix34Mul(&mat, &ap->t.t.mat, pMat); |
||
786 | pMat = &mat; |
||
787 | } else { |
||
788 | pMat = &ap->t.t.mat; |
||
789 | } |
||
790 | BrMatrix34LPInverse(&invmat, &ap->t.t.mat); |
||
791 | BrMatrix34Mul(&mat2, bnds->mat, &invmat); |
||
792 | new_bounds.mat = &mat2; |
||
793 | BrVector3Copy(&new_bounds.original_bounds.min, &bnds->original_bounds.min); |
||
794 | BrVector3Copy(&new_bounds.original_bounds.max, &bnds->original_bounds.max); |
||
795 | BrMatrix34ApplyP(&new_bounds.box_centre, &bnds->box_centre, &invmat); |
||
796 | new_bounds.radius = bnds->radius; |
||
797 | GetNewBoundingBox(&new_bounds.real_bounds, &new_bounds.original_bounds, new_bounds.mat); |
||
798 | if (ap->identifier[1] >= '0' && ap->identifier[1] <= '9') { |
||
799 | if (!BoundsOverlapTest__finteray(&new_bounds.real_bounds, &this_model->bounds)) { |
||
800 | return max_face; |
||
801 | } |
||
802 | BrMatrix34LPInverse(&invmat, bnds->mat); |
||
803 | BrMatrix34Mul(&box_to_actor, &ap->t.t.mat, &invmat); |
||
804 | GetNewBoundingBox(&br_bnds, &ap->model->bounds, &box_to_actor); |
||
805 | if (!BoundsOverlapTest__finteray(&br_bnds, &bnds->original_bounds)) { |
||
806 | return max_face; |
||
807 | } |
||
808 | if (PullActorFromWorld(ap)) { |
||
809 | return max_face; |
||
810 | } |
||
811 | } |
||
812 | bnds = &new_bounds; |
||
813 | } |
||
814 | if (ap->type == BR_ACTOR_MODEL) { |
||
815 | if (BoundsOverlapTest__finteray(&bnds->real_bounds, &this_model->bounds)) { |
||
816 | n = ModelPickBox(ap, bnds, this_model, this_material, &face_list[i], max_face, pMat); |
||
817 | if (pMat && max_face != n) { |
||
818 | StopGroovidelic(ap); |
||
819 | } |
||
820 | i += max_face - n; |
||
821 | max_face = n; |
||
822 | } |
||
823 | } else if (ap->type == BR_ACTOR_BOUNDS || ap->type == BR_ACTOR_BOUNDS_CORRECT) { |
||
824 | test_children = BoundsOverlapTest__finteray(&bnds->real_bounds, (br_bounds*)ap->type_data); |
||
825 | } |
||
826 | if (test_children) { |
||
827 | for (a = ap->children; a != NULL; a = next_a) { |
||
828 | next_a = a->next; |
||
829 | n = ActorBoxPick(bnds, a, this_model, this_material, &face_list[i], max_face, pMat); |
||
830 | i += max_face - n; |
||
831 | max_face = n; |
||
832 | } |
||
833 | } |
||
834 | return max_face; |
||
835 | } |
||
836 | |||
837 | // IDA: int __usercall ModelPickBox@<EAX>(br_actor *actor@<EAX>, tBounds *bnds@<EDX>, br_model *model@<EBX>, br_material *model_material@<ECX>, tFace_ref *face_list, int max_face, br_matrix34 *pMat) |
||
838 | int ModelPickBox(br_actor* actor, tBounds* bnds, br_model* model, br_material* model_material, tFace_ref* face_list, int max_face, br_matrix34* pMat) { |
||
839 | int f; |
||
840 | int i; |
||
841 | int n; |
||
842 | int group; |
||
18 | pmbaty | 843 | // DR_FACE* fp; |
1 | pmbaty | 844 | int v1; |
845 | int v2; |
||
846 | int v3; |
||
847 | br_vector3 polygon[12]; |
||
848 | br_vector3 a; |
||
849 | br_vector3 tv; |
||
850 | br_scalar t; |
||
18 | pmbaty | 851 | struct v11model* prepared; |
1 | pmbaty | 852 | LOG_TRACE("(%p, %p, %p, %p, %p, %d, %p)", actor, bnds, model, model_material, face_list, max_face, pMat); |
853 | |||
18 | pmbaty | 854 | struct v11group* grp_ptr; |
855 | |||
1 | pmbaty | 856 | prepared = model->prepared; |
857 | if (max_face <= 0) { |
||
858 | return 0; |
||
859 | } |
||
860 | for (group = 0; prepared->ngroups > group; group++) { |
||
18 | pmbaty | 861 | grp_ptr = &prepared->groups[group]; |
1 | pmbaty | 862 | for (f = 0; f < prepared->groups[group].nfaces; f++) { |
18 | pmbaty | 863 | // fp = &prepared->groups[group].faces[f]; |
864 | v1 = grp_ptr->vertex_numbers[f].v[0]; // fp->vertices[0]; |
||
865 | // BrVector3Sub(&a, &prepared->groups[group].vertices[v1].p, &bnds->box_centre); |
||
866 | BrVector3Sub(&a, &grp_ptr->position[v1], &bnds->box_centre); |
||
867 | // t = BrVector3Dot((br_vector3*)&fp->eqn, &a); |
||
868 | t = BrVector3Dot((br_vector3*)&grp_ptr->eqn[f], &a); |
||
1 | pmbaty | 869 | if (fabsf(t) > bnds->radius) { |
870 | continue; |
||
871 | } |
||
18 | pmbaty | 872 | // v2 = fp->vertices[1]; |
873 | // v3 = fp->vertices[2]; |
||
874 | v2 = grp_ptr->vertex_numbers[f].v[1]; |
||
875 | v3 = grp_ptr->vertex_numbers[f].v[2]; |
||
1 | pmbaty | 876 | |
877 | t = bnds->real_bounds.min.v[0]; |
||
18 | pmbaty | 878 | if (t > grp_ptr->position[v1].v[0] |
879 | && t > grp_ptr->position[v2].v[0] |
||
880 | && t > grp_ptr->position[v3].v[0]) { |
||
1 | pmbaty | 881 | continue; |
882 | } |
||
883 | t = bnds->real_bounds.max.v[0]; |
||
18 | pmbaty | 884 | if (t < grp_ptr->position[v1].v[0] |
885 | && t < grp_ptr->position[v2].v[0] |
||
886 | && t < grp_ptr->position[v3].v[0]) { |
||
1 | pmbaty | 887 | continue; |
888 | } |
||
889 | t = bnds->real_bounds.min.v[1]; |
||
18 | pmbaty | 890 | if (t > grp_ptr->position[v1].v[1] |
891 | && t > grp_ptr->position[v2].v[1] |
||
892 | && t > grp_ptr->position[v3].v[1]) { |
||
1 | pmbaty | 893 | continue; |
894 | } |
||
895 | t = bnds->real_bounds.max.v[1]; |
||
18 | pmbaty | 896 | if (t < grp_ptr->position[v1].v[1] |
897 | && t < grp_ptr->position[v2].v[1] |
||
898 | && t < grp_ptr->position[v3].v[1]) { |
||
1 | pmbaty | 899 | continue; |
900 | } |
||
901 | t = bnds->real_bounds.min.v[2]; |
||
18 | pmbaty | 902 | if (t > grp_ptr->position[v1].v[2] |
903 | && t > grp_ptr->position[v2].v[2] |
||
904 | && t > grp_ptr->position[v3].v[2]) { |
||
1 | pmbaty | 905 | continue; |
906 | } |
||
907 | t = bnds->real_bounds.max.v[2]; |
||
18 | pmbaty | 908 | if (t < grp_ptr->position[v1].v[2] |
909 | && t < grp_ptr->position[v2].v[2] |
||
910 | && t < grp_ptr->position[v3].v[2]) { |
||
1 | pmbaty | 911 | continue; |
912 | } |
||
18 | pmbaty | 913 | BrVector3Sub(&polygon[1], &grp_ptr->position[v1], (br_vector3*)bnds->mat->m[3]); |
914 | BrVector3Sub(&polygon[2], &grp_ptr->position[v2], (br_vector3*)bnds->mat->m[3]); |
||
915 | BrVector3Sub(&polygon[3], &grp_ptr->position[v3], (br_vector3*)bnds->mat->m[3]); |
||
1 | pmbaty | 916 | BrMatrix34TApplyV(&polygon[0], &polygon[1], bnds->mat); |
917 | BrMatrix34TApplyV(&polygon[1], &polygon[2], bnds->mat); |
||
918 | BrMatrix34TApplyV(&polygon[2], &polygon[3], bnds->mat); |
||
919 | n = 3; |
||
920 | for (i = 0; i < 3; i++) { |
||
921 | ClipToPlaneGE(&polygon[0], &n, i, bnds->original_bounds.min.v[i]); |
||
922 | if (n < 3) { |
||
923 | break; |
||
924 | } |
||
925 | ClipToPlaneLE(&polygon[0], &n, i, bnds->original_bounds.max.v[i]); |
||
926 | if (n < 3) { |
||
927 | break; |
||
928 | } |
||
929 | } |
||
930 | if (n >= 3) { |
||
931 | if (pMat != NULL) { |
||
18 | pmbaty | 932 | BrMatrix34ApplyP(&face_list->v[0], &grp_ptr->position[v1], pMat); |
933 | BrMatrix34ApplyP(&face_list->v[1], &grp_ptr->position[v2], pMat); |
||
934 | BrMatrix34ApplyP(&face_list->v[2], &grp_ptr->position[v3], pMat); |
||
935 | BrVector3Copy(&tv, (br_vector3*)&grp_ptr->eqn[f]); |
||
1 | pmbaty | 936 | BrMatrix34ApplyV(&face_list->normal, &tv, pMat); |
937 | } else { |
||
18 | pmbaty | 938 | BrVector3Copy(&face_list->v[0], &grp_ptr->position[v1]); |
939 | BrVector3Copy(&face_list->v[1], &grp_ptr->position[v2]); |
||
940 | BrVector3Copy(&face_list->v[2], &grp_ptr->position[v3]); |
||
941 | BrVector3Copy(&face_list->normal, (br_vector3*)&grp_ptr->eqn[f]); |
||
1 | pmbaty | 942 | } |
18 | pmbaty | 943 | if (prepared->groups[group].user != NULL) { |
944 | face_list->material = prepared->groups[group].user; |
||
1 | pmbaty | 945 | } else { |
946 | face_list->material = model_material; |
||
947 | } |
||
948 | face_list->flags = 0; |
||
949 | if (face_list->material != NULL && (face_list->material->flags & (BR_MATF_TWO_SIDED | BR_MATF_ALWAYS_VISIBLE)) == 0) { |
||
950 | face_list->flags |= (v1 < v2) | (v2 < v3) << 1 | (v3 < v1) << 2; |
||
951 | } |
||
952 | if (pMat != NULL) { |
||
953 | face_list->d = BrVector3LengthSquared(&face_list->v[0]); |
||
954 | } else { |
||
18 | pmbaty | 955 | face_list->d = grp_ptr->eqn[f].v[3]; |
1 | pmbaty | 956 | } |
18 | pmbaty | 957 | face_list->map[0] = &grp_ptr->map[v1]; |
958 | face_list->map[1] = &grp_ptr->map[v2]; |
||
959 | face_list->map[2] = &grp_ptr->map[v3]; |
||
960 | if (face_list->material != NULL |
||
1 | pmbaty | 961 | && face_list->material->identifier != NULL |
962 | && face_list->material->identifier[0] == '!') { |
||
963 | gPling_face = face_list; |
||
964 | } |
||
965 | face_list++; |
||
966 | max_face--; |
||
967 | if (max_face == 0) { |
||
968 | break; |
||
969 | } |
||
970 | } |
||
971 | } |
||
972 | if (max_face == 0) { |
||
973 | break; |
||
974 | } |
||
975 | } |
||
976 | return max_face; |
||
977 | } |
||
978 | |||
979 | // IDA: void __usercall ClipToPlaneGE(br_vector3 *p@<EAX>, int *nv@<EDX>, int i@<EBX>, br_scalar limit) |
||
980 | void ClipToPlaneGE(br_vector3* p, int* nv, int i, br_scalar limit) { |
||
981 | int last_vertex; |
||
982 | int j; |
||
983 | int vertex; |
||
984 | int k; |
||
985 | br_vector3 p2[12]; |
||
986 | LOG_TRACE("(%p, %p, %d, %f)", p, nv, i, limit); |
||
987 | |||
988 | last_vertex = *nv - 1; |
||
989 | j = 0; |
||
990 | for (vertex = 0; *nv > vertex; ++vertex) { |
||
991 | if ((p[last_vertex].v[i] > limit) != (p[vertex].v[i] > limit)) { |
||
992 | for (k = 0; k < 3; ++k) { |
||
993 | if (i != k) { |
||
994 | p2[j].v[k] = (p[vertex].v[k] - p[last_vertex].v[k]) |
||
995 | * (limit - p[last_vertex].v[i]) |
||
996 | / (p[vertex].v[i] - p[last_vertex].v[i]) |
||
997 | + p[last_vertex].v[k]; |
||
998 | } |
||
999 | } |
||
1000 | p2[j++].v[i] = limit; |
||
1001 | } |
||
1002 | if (p[vertex].v[i] >= limit) { |
||
1003 | BrVector3Copy(&p2[j], &p[vertex]); |
||
1004 | j++; |
||
1005 | } |
||
1006 | last_vertex = vertex; |
||
1007 | } |
||
1008 | *nv = j; |
||
1009 | for (k = 0; k < j; k++) { |
||
1010 | BrVector3Copy(&p[k], &p2[k]); |
||
1011 | } |
||
1012 | } |
||
1013 | |||
1014 | // IDA: void __usercall ClipToPlaneLE(br_vector3 *p@<EAX>, int *nv@<EDX>, int i@<EBX>, br_scalar limit) |
||
1015 | void ClipToPlaneLE(br_vector3* p, int* nv, int i, br_scalar limit) { |
||
1016 | int last_vertex; |
||
1017 | int j; |
||
1018 | int vertex; |
||
1019 | int k; |
||
1020 | br_vector3 p2[12]; |
||
1021 | LOG_TRACE("(%p, %p, %d, %f)", p, nv, i, limit); |
||
1022 | |||
1023 | last_vertex = *nv - 1; |
||
1024 | j = 0; |
||
1025 | for (vertex = 0; *nv > vertex; ++vertex) { |
||
1026 | if ((p[vertex].v[i] > limit) != (p[last_vertex].v[i] > limit)) { |
||
1027 | for (k = 0; k < 3; ++k) { |
||
1028 | if (k != i) { |
||
1029 | p2[j].v[k] = (p[vertex].v[k] - p[last_vertex].v[k]) |
||
1030 | * (limit - p[last_vertex].v[i]) |
||
1031 | / (p[vertex].v[i] - p[last_vertex].v[i]) |
||
1032 | + p[last_vertex].v[k]; |
||
1033 | } |
||
1034 | } |
||
1035 | p2[j++].v[i] = limit; |
||
1036 | } |
||
1037 | if (p[vertex].v[i] <= (double)limit) { |
||
1038 | BrVector3Copy(&p2[j], &p[vertex]); |
||
1039 | j++; |
||
1040 | } |
||
1041 | last_vertex = vertex; |
||
1042 | } |
||
1043 | *nv = j; |
||
1044 | for (k = 0; k < j; k++) { |
||
1045 | BrVector3Copy(&p[k], &p2[k]); |
||
1046 | } |
||
1047 | } |
||
1048 | |||
1049 | // IDA: int __usercall BoundsOverlapTest@<EAX>(br_bounds *b1@<EAX>, br_bounds *b2@<EDX>) |
||
1050 | // Suffix added to avoid duplicate symbol |
||
1051 | int BoundsOverlapTest__finteray(br_bounds* b1, br_bounds* b2) { |
||
1052 | LOG_TRACE("(%p, %p)", b1, b2); |
||
1053 | |||
1054 | return b1->min.v[0] <= b2->max.v[0] |
||
1055 | && b2->min.v[0] <= b1->max.v[0] |
||
1056 | && b1->min.v[1] <= b2->max.v[1] |
||
1057 | && b2->min.v[1] <= b1->max.v[1] |
||
1058 | && b1->min.v[2] <= b2->max.v[2] |
||
1059 | && b2->min.v[2] <= b1->max.v[2]; |
||
1060 | } |
||
1061 | |||
1062 | // IDA: int __usercall BoundsTransformTest@<EAX>(br_bounds *b1@<EAX>, br_bounds *b2@<EDX>, br_matrix34 *M@<EBX>) |
||
1063 | int BoundsTransformTest(br_bounds* b1, br_bounds* b2, br_matrix34* M) { |
||
1064 | br_scalar val; |
||
1065 | br_vector3 o; |
||
1066 | LOG_TRACE("(%p, %p, %p)", b1, b2, M); |
||
1067 | |||
1068 | BrVector3Sub(&o, &b1->max, &b1->min); |
||
1069 | val = M->m[0][0] * b1->min.v[0] + M->m[1][0] * b1->min.v[1] + M->m[2][0] * b1->min.v[2] + M->m[3][0]; |
||
1070 | |||
1071 | if ((M->m[0][0] <= 0.0f ? 0.0f : M->m[0][0] * o.v[0]) |
||
1072 | + (M->m[1][0] <= 0.0f ? 0.0f : M->m[1][0] * o.v[1]) |
||
1073 | + (M->m[2][0] <= 0.0f ? 0.0f : M->m[2][0] * o.v[2]) |
||
1074 | + val |
||
1075 | < b2->min.v[0]) { |
||
1076 | return 0; |
||
1077 | } |
||
1078 | if ((M->m[0][0] < 0.0f ? M->m[0][0] * o.v[0] : 0.0f) |
||
1079 | + (M->m[1][0] < 0.0f ? M->m[1][0] * o.v[1] : 0.0f) |
||
1080 | + (M->m[2][0] < 0.0f ? M->m[2][0] * o.v[2] : 0.0f) |
||
1081 | + val |
||
1082 | > b2->max.v[0]) { |
||
1083 | return 0; |
||
1084 | } |
||
1085 | |||
1086 | val = M->m[0][2] * b1->min.v[0] + M->m[1][2] * b1->min.v[1] + M->m[2][2] * b1->min.v[2] + M->m[3][2]; |
||
1087 | if ((M->m[0][2] <= 0.0f ? 0.0f : M->m[0][2] * o.v[0]) |
||
1088 | + (M->m[1][2] <= 0.0f ? 0.0f : M->m[1][2] * o.v[1]) |
||
1089 | + (M->m[2][2] <= 0.0f ? 0.0f : M->m[2][2] * o.v[2]) |
||
1090 | + val |
||
1091 | < b2->min.v[2]) { |
||
1092 | return 0; |
||
1093 | } |
||
1094 | if ((M->m[0][2] < 0.0f ? M->m[0][2] * o.v[0] : 0.0f) |
||
1095 | + (M->m[1][2] < 0.0f ? M->m[1][2] * o.v[1] : 0.0f) |
||
1096 | + (M->m[2][2] < 0.0f ? M->m[2][2] * o.v[2] : 0.0f) |
||
1097 | + val |
||
1098 | > b2->max.v[2]) { |
||
1099 | return 0; |
||
1100 | } |
||
1101 | |||
1102 | val = M->m[0][1] * b1->min.v[0] + M->m[1][1] * b1->min.v[1] + M->m[2][1] * b1->min.v[2] + M->m[3][1]; |
||
1103 | if ((M->m[0][1] <= 0.0f ? 0.0f : M->m[0][1] * o.v[0]) |
||
1104 | + (M->m[1][1] <= 0.0f ? 0.0f : M->m[1][1] * o.v[1]) |
||
1105 | + (M->m[2][1] <= 0.0f ? 0.0f : M->m[2][1] * o.v[2]) |
||
1106 | + val |
||
1107 | < b2->min.v[1]) { |
||
1108 | return 0; |
||
1109 | } |
||
1110 | if ((M->m[0][1] < 0.0 ? M->m[0][1] * o.v[0] : 0.0) |
||
1111 | + (M->m[1][1] < 0.0 ? M->m[1][1] * o.v[1] : 0.0) |
||
1112 | + (M->m[2][1] < 0.0 ? M->m[2][1] * o.v[2] : 0.0) |
||
1113 | + val |
||
1114 | > b2->max.v[1]) { |
||
1115 | return 0; |
||
1116 | } |
||
1117 | |||
1118 | return 1; |
||
1119 | } |
||
1120 | |||
1121 | // IDA: int __usercall LineBoxColl@<EAX>(br_vector3 *o@<EAX>, br_vector3 *p@<EDX>, br_bounds *pB@<EBX>, br_vector3 *pHit_point@<ECX>) |
||
1122 | int LineBoxColl(br_vector3* o, br_vector3* p, br_bounds* pB, br_vector3* pHit_point) { |
||
1123 | br_vector3 dir; |
||
1124 | int inside; |
||
1125 | int quad[3]; |
||
1126 | int i; |
||
1127 | int which_plane; |
||
1128 | br_scalar max_t[3]; |
||
1129 | br_scalar cp[3]; |
||
1130 | LOG_TRACE("(%p, %p, %p, %p)", o, p, pB, pHit_point); |
||
1131 | |||
1132 | inside = 1; |
||
1133 | BrVector3Sub(&dir, p, o); |
||
1134 | for (i = 0; i < 3; ++i) { |
||
1135 | if (pB->min.v[i] <= o->v[i]) { |
||
1136 | if (pB->max.v[i] >= o->v[i]) { |
||
1137 | quad[i] = 2; |
||
1138 | } else { |
||
1139 | quad[i] = 0; |
||
1140 | max_t[i] = pB->max.v[i]; |
||
1141 | inside = 0; |
||
1142 | } |
||
1143 | } else { |
||
1144 | quad[i] = 1; |
||
1145 | max_t[i] = pB->min.v[i]; |
||
1146 | inside = 0; |
||
1147 | } |
||
1148 | } |
||
1149 | if (inside) { |
||
1150 | BrVector3Copy(pHit_point, o); |
||
1151 | return 8; |
||
1152 | } else { |
||
1153 | for (i = 0; i < 3; ++i) { |
||
1154 | if (quad[i] == 2 || dir.v[i] == 0.0) { |
||
1155 | cp[i] = -1.0; |
||
1156 | } else { |
||
1157 | cp[i] = (max_t[i] - o->v[i]) / dir.v[i]; |
||
1158 | } |
||
1159 | } |
||
1160 | which_plane = 0; |
||
1161 | for (i = 1; i < 3; ++i) { |
||
1162 | if (cp[which_plane] < cp[i]) { |
||
1163 | which_plane = i; |
||
1164 | } |
||
1165 | } |
||
1166 | if (cp[which_plane] >= 0.0 && cp[which_plane] <= 1.0) { |
||
1167 | for (i = 0; i < 3; ++i) { |
||
1168 | if (which_plane == i) { |
||
1169 | pHit_point->v[i] = max_t[i]; |
||
1170 | } else { |
||
1171 | pHit_point->v[i] = dir.v[i] * cp[which_plane] + o->v[i]; |
||
1172 | if (pHit_point->v[i] < pB->min.v[i] || pB->max.v[i] < pHit_point->v[i]) { |
||
1173 | return 0; |
||
1174 | } |
||
1175 | } |
||
1176 | } |
||
1177 | return which_plane + 4 * quad[which_plane] + 1; |
||
1178 | } else { |
||
1179 | return 0; |
||
1180 | } |
||
1181 | } |
||
1182 | } |
||
1183 | |||
1184 | // IDA: int __usercall SphereBoxIntersection@<EAX>(br_bounds *pB@<EAX>, br_vector3 *pC@<EDX>, br_scalar pR_squared, br_vector3 *pHit_point) |
||
1185 | int SphereBoxIntersection(br_bounds* pB, br_vector3* pC, br_scalar pR_squared, br_vector3* pHit_point) { |
||
1186 | int i; |
||
1187 | br_scalar d; |
||
1188 | LOG_TRACE("(%p, %p, %f, %p)", pB, pC, pR_squared, pHit_point); |
||
1189 | |||
1190 | d = 0.f; |
||
1191 | for (i = 0; i < 3; i++) { |
||
1192 | if (pC->v[i] <= pB->min.v[i]) { |
||
1193 | pHit_point->v[i] = pB->min.v[i]; |
||
1194 | } else if (pC->v[i] > pB->max.v[i]) { |
||
1195 | pHit_point->v[i] = pB->max.v[i]; |
||
1196 | } else { |
||
1197 | pHit_point->v[i] = pC->v[i]; |
||
1198 | } |
||
1199 | d += (pC->v[i] - pHit_point->v[i]) * (pC->v[i] - pHit_point->v[i]); |
||
1200 | } |
||
1201 | return d <= pR_squared; |
||
1202 | } |
||
1203 | |||
1204 | // IDA: int __usercall LineBoxCollWithSphere@<EAX>(br_vector3 *o@<EAX>, br_vector3 *p@<EDX>, br_bounds *pB@<EBX>, br_vector3 *pHit_point@<ECX>) |
||
1205 | int LineBoxCollWithSphere(br_vector3* o, br_vector3* p, br_bounds* pB, br_vector3* pHit_point) { |
||
1206 | int i; |
||
1207 | int plane; |
||
1208 | LOG_TRACE("(%p, %p, %p, %p)", o, p, pB, pHit_point); |
||
1209 | |||
1210 | plane = LineBoxColl(o, p, pB, pHit_point); |
||
1211 | |||
1212 | if (plane != 0) { |
||
1213 | return plane; |
||
1214 | } |
||
1215 | if (!SphereBoxIntersection(pB, p, 2.5e-5f, pHit_point)) { |
||
1216 | return 0; |
||
1217 | } |
||
1218 | for (i = 0; i < 3; i++) { |
||
1219 | if (pB->max.v[i] == pHit_point->v[i] && p->v[i] <= o->v[i]) { |
||
1220 | return i + 1; |
||
1221 | } |
||
1222 | if (pHit_point->v[i] == pB->min.v[i] && p->v[i] >= o->v[i]) { |
||
1223 | return i + 5; |
||
1224 | } |
||
1225 | } |
||
1226 | return 0; |
||
1227 | } |
||
1228 | |||
1229 | // IDA: int __usercall CompVert@<EAX>(int v1@<EAX>, int v2@<EDX>) |
||
1230 | int CompVert(int v1, int v2) { |
||
18 | pmbaty | 1231 | br_vertex* vl; |
1232 | br_vector3 tv; |
||
1233 | br_vector2 tv2; |
||
1 | pmbaty | 1234 | LOG_TRACE("(%d, %d)", v1, v2); |
18 | pmbaty | 1235 | |
1236 | if (v1 == v2) { |
||
1237 | return 1; |
||
1238 | } |
||
1239 | vl = gSelected_model->vertices; |
||
1240 | BrVector3Sub(&tv, &vl[v1].p, &vl[v2].p); |
||
1241 | if (BrVector3LengthSquared(&tv) > 1e-5f) { |
||
1242 | return 0; |
||
1243 | } |
||
1244 | BrVector2Sub(&tv2, &vl[v1].map, &vl[v2].map); |
||
1245 | if (BrVector2LengthSquared(&tv2) > 1e-5f) { |
||
1246 | return 0; |
||
1247 | } |
||
1248 | return 1; |
||
1 | pmbaty | 1249 | } |
1250 | |||
1251 | // IDA: void __usercall SetFacesGroup(int pFace@<EAX>) |
||
1252 | void SetFacesGroup(int pFace) { |
||
1253 | //int f; // Pierre-Marie Baty -- unused variable |
||
1254 | //int v; // Pierre-Marie Baty -- unused variable |
||
1255 | //int i; // Pierre-Marie Baty -- unused variable |
||
1256 | LOG_TRACE("(%d)", pFace); |
||
1257 | NOT_IMPLEMENTED(); |
||
1258 | } |
||
1259 | |||
1260 | // IDA: void __usercall SelectFace(br_vector3 *pDir@<EAX>) |
||
1261 | void SelectFace(br_vector3* pDir) { |
||
1262 | //tCar_spec* c; // Pierre-Marie Baty -- unused variable |
||
1263 | //br_vector3 dir; // Pierre-Marie Baty -- unused variable |
||
1264 | //br_vector3 normal; // Pierre-Marie Baty -- unused variable |
||
1265 | //br_scalar t; // Pierre-Marie Baty -- unused variable |
||
1266 | //br_model* old_model; // Pierre-Marie Baty -- unused variable |
||
1267 | //int i; // Pierre-Marie Baty -- unused variable |
||
1268 | LOG_TRACE("(%p)", pDir); |
||
1269 | NOT_IMPLEMENTED(); |
||
1270 | } |
||
1271 | |||
1272 | // IDA: void __usercall GetTilingLimits(br_vector2 *min@<EAX>, br_vector2 *max@<EDX>) |
||
1273 | void GetTilingLimits(br_vector2* min, br_vector2* max) { |
||
18 | pmbaty | 1274 | int f; |
1275 | int i; |
||
1276 | int j; |
||
1277 | br_vertex* verts; |
||
1278 | br_face* faces; |
||
1 | pmbaty | 1279 | LOG_TRACE("(%p, %p)", min, max); |
18 | pmbaty | 1280 | |
1281 | verts = gSelected_model->vertices; |
||
1282 | faces = gSelected_model->faces; |
||
1283 | BrVector2Set(min, 32000.f, 32000.f); |
||
1284 | BrVector2Set(max, -32000.f, -32000.f); |
||
1285 | for (f = 0; f < gSelected_model->nfaces; f++) { |
||
1286 | if (faces[f].material == gSub_material) { |
||
1287 | for (i = 0; i < 3; i++) { |
||
1288 | for (j = 0; j < 3; j++) { |
||
1289 | if (verts[faces[f].vertices[i]].map.v[j] < min->v[j]) { |
||
1290 | min->v[j] = verts[faces[f].vertices[i]].map.v[j]; |
||
1291 | } |
||
1292 | if (verts[faces[f].vertices[i]].map.v[j] > max->v[j]) { |
||
1293 | max->v[j] = verts[faces[f].vertices[i]].map.v[j]; |
||
1294 | } |
||
1295 | } |
||
1296 | } |
||
1297 | } |
||
1298 | } |
||
1 | pmbaty | 1299 | } |
1300 | |||
1301 | // IDA: void __usercall Scale(int pD@<EAX>, int factor@<EDX>) |
||
1302 | void Scale(int pD, int factor) { |
||
18 | pmbaty | 1303 | br_vector2 min; |
1304 | br_vector2 max; |
||
1305 | int f; |
||
1306 | int v; |
||
1307 | br_scalar d; |
||
1308 | br_vertex* verts; |
||
1309 | br_face* faces; |
||
1 | pmbaty | 1310 | LOG_TRACE("(%d, %d)", pD, factor); |
18 | pmbaty | 1311 | |
1312 | if (gSelected_model == NULL) { |
||
1313 | return; |
||
1314 | } |
||
1315 | if (gSelected_model->nfaces != gNfaces) { |
||
1316 | return; |
||
1317 | } |
||
1318 | verts = gSelected_model->vertices; |
||
1319 | faces = gSelected_model->faces; |
||
1320 | GetTilingLimits(&min, &max); |
||
1321 | d = max.v[pD] - min.v[pD]; |
||
1322 | if (d <= 0.f || factor + d <= 0.f) { |
||
1323 | return; |
||
1324 | } |
||
1325 | for (v = 0; v < gSelected_model->nvertices; v++) { |
||
1326 | for (f = 0; f < gSelected_model->nfaces; f++) { |
||
1327 | if (faces[f].material == gSub_material |
||
1328 | && (faces[f].vertices[0] == v || faces[f].vertices[1] == v || faces[f].vertices[2] == v)) { |
||
1329 | verts[v].map.v[pD] = (factor + d) / d * verts[v].map.v[pD]; |
||
1330 | break; |
||
1331 | } |
||
1332 | } |
||
1333 | } |
||
1334 | BrModelUpdate(gSelected_model, BR_MODU_ALL); |
||
1 | pmbaty | 1335 | } |
1336 | |||
1337 | // IDA: void __cdecl ScaleUpX() |
||
1338 | void ScaleUpX(void) { |
||
1339 | LOG_TRACE("()"); |
||
18 | pmbaty | 1340 | |
1341 | Scale(0, 1); |
||
1 | pmbaty | 1342 | } |
1343 | |||
1344 | // IDA: void __cdecl ScaleDnX() |
||
1345 | void ScaleDnX(void) { |
||
1346 | LOG_TRACE("()"); |
||
18 | pmbaty | 1347 | |
1348 | Scale(0, -1); |
||
1 | pmbaty | 1349 | } |
1350 | |||
1351 | // IDA: void __cdecl ScaleUpY() |
||
1352 | void ScaleUpY(void) { |
||
1353 | LOG_TRACE("()"); |
||
18 | pmbaty | 1354 | |
1355 | Scale(1, 1); |
||
1 | pmbaty | 1356 | } |
1357 | |||
1358 | // IDA: void __cdecl ScaleDnY() |
||
1359 | void ScaleDnY(void) { |
||
1360 | LOG_TRACE("()"); |
||
18 | pmbaty | 1361 | |
1362 | Scale(1, -1); |
||
1 | pmbaty | 1363 | } |
1364 | |||
1365 | // IDA: void __cdecl SelectFaceForward() |
||
1366 | void SelectFaceForward(void) { |
||
18 | pmbaty | 1367 | br_vector3 dir; |
1 | pmbaty | 1368 | LOG_TRACE("()"); |
18 | pmbaty | 1369 | |
1370 | BrVector3Scale(&dir, (br_vector3*)&gProgram_state.current_car.car_master_actor->t.t.mat.m[2], -2.f); |
||
1371 | SelectFace(&dir); |
||
1 | pmbaty | 1372 | } |
1373 | |||
1374 | // IDA: void __cdecl SelectFaceDown() |
||
1375 | void SelectFaceDown(void) { |
||
18 | pmbaty | 1376 | br_vector3 dir; |
1 | pmbaty | 1377 | LOG_TRACE("()"); |
18 | pmbaty | 1378 | |
1379 | BrVector3Scale(&dir, (br_vector3*)&gProgram_state.current_car.car_master_actor->t.t.look_up.up, -2.f); |
||
1380 | SelectFace(&dir); |
||
1 | pmbaty | 1381 | } |