1 | /********************************************************************** <BR>
|
---|
2 | This file is part of Crack dot Com's free source code release of
|
---|
3 | Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
|
---|
4 | information about compiling & licensing issues visit this URL</a>
|
---|
5 | <PRE> If that doesn't help, contact Jonathan Clark at
|
---|
6 | golgotha_source@usa.net (Subject should have "GOLG" in it)
|
---|
7 | ***********************************************************************/
|
---|
8 |
|
---|
9 | #include "objs/explode_model.hh"
|
---|
10 | #include "objs/model_id.hh"
|
---|
11 | #include "math/pi.hh"
|
---|
12 | #include "math/trig.hh"
|
---|
13 | #include "math/angle.hh"
|
---|
14 | #include "g1_rand.hh"
|
---|
15 | #include "resources.hh"
|
---|
16 | #include "saver.hh"
|
---|
17 | #include "g1_render.hh"
|
---|
18 | #include "r1_clip.hh"
|
---|
19 | #include "r1_api.hh"
|
---|
20 | #include "g1_tint.hh"
|
---|
21 | #include "object_definer.hh"
|
---|
22 | #include "time/profile.hh"
|
---|
23 | #include "map_man.hh"
|
---|
24 | #include "map.hh"
|
---|
25 | #include "objs/particle_emitter.hh"
|
---|
26 | #include "tick_count.hh"
|
---|
27 | #include "draw_context.hh"
|
---|
28 |
|
---|
29 | i4_profile_class pf_exp_model_setup("explode_model setup");
|
---|
30 | i4_profile_class pf_exp_model_think("explode_model think");
|
---|
31 | i4_profile_class pf_exp_model_draw("explode_model draw");
|
---|
32 |
|
---|
33 | g1_object_definer<g1_explode_model_class>
|
---|
34 | g1_explode_model_def("explode_model");
|
---|
35 |
|
---|
36 | inline void check_on_map(const i4_3d_vector &v)
|
---|
37 | {
|
---|
38 | int vx=i4_f_to_i(v.x), vy=i4_f_to_i(v.y);
|
---|
39 | if (vx<0 || vy<0 || vx>=g1_get_map()->width() || vy>=g1_get_map()->height())
|
---|
40 | i4_error("off map");
|
---|
41 | }
|
---|
42 |
|
---|
43 |
|
---|
44 |
|
---|
45 | g1_explode_model_class::g1_explode_model_class(g1_object_type id,
|
---|
46 | g1_loader_class *fp)
|
---|
47 | : g1_object_class(id,fp)
|
---|
48 | {
|
---|
49 | //does not save or load. too complicated and not really necessary
|
---|
50 | vertices = 0;
|
---|
51 | num_vertices = 0;
|
---|
52 |
|
---|
53 | faces = 0;
|
---|
54 | num_faces = 0;
|
---|
55 | }
|
---|
56 |
|
---|
57 | void g1_explode_model_class::save(g1_saver_class *fp)
|
---|
58 | {
|
---|
59 | g1_object_class::save(fp);
|
---|
60 | }
|
---|
61 |
|
---|
62 | g1_explode_model_class::~g1_explode_model_class()
|
---|
63 | {
|
---|
64 | if (vertices)
|
---|
65 | i4_free(vertices);
|
---|
66 |
|
---|
67 | if (faces)
|
---|
68 | i4_free(faces);
|
---|
69 | }
|
---|
70 |
|
---|
71 |
|
---|
72 | void g1_explode_model_class::grab_model(g1_object_class *o, i4_3d_vector &obj_center)
|
---|
73 | {
|
---|
74 | g1_quad_object_class *base_m = o->draw_params.model;
|
---|
75 |
|
---|
76 | //face/vertex setup. count all the faces and vertices in base and sub-objects
|
---|
77 |
|
---|
78 | num_faces = base_m->num_quad;
|
---|
79 | num_vertices = 0;
|
---|
80 |
|
---|
81 | obj_center=i4_3d_vector(0,0,0);
|
---|
82 |
|
---|
83 | int i,j;
|
---|
84 | for (i=0; i<base_m->num_quad; i++)
|
---|
85 | num_vertices += base_m->quad[i].num_verts();
|
---|
86 |
|
---|
87 | //allocate space
|
---|
88 | faces = (g1_explode_face_class *) i4_malloc(sizeof(g1_explode_face_class) * num_faces,"");
|
---|
89 | vertices = (g1_explode_vertex_class *)i4_malloc(sizeof(g1_explode_vertex_class)*num_vertices,"");
|
---|
90 |
|
---|
91 | //copy information. this is ugly, has to use transforms
|
---|
92 | //to get everything into world space, etc..
|
---|
93 |
|
---|
94 | i4_transform_class base_transform,mini_transform,spare_transform,*cur_transform;
|
---|
95 |
|
---|
96 | //make sure there is a transform ready for the base model
|
---|
97 | o->calc_world_transform(g1_render.frame_ratio, &base_transform);
|
---|
98 |
|
---|
99 | cur_transform = &base_transform;
|
---|
100 |
|
---|
101 | g1_quad_object_class *m = base_m;
|
---|
102 | g1_explode_face_class *f = faces;
|
---|
103 | g1_explode_vertex_class *v = vertices;
|
---|
104 |
|
---|
105 | sw32 vertex_count = 0;
|
---|
106 | sw32 k = 0;
|
---|
107 |
|
---|
108 | sw32 total_face_count=0;
|
---|
109 |
|
---|
110 |
|
---|
111 | // while (m)
|
---|
112 | {
|
---|
113 | g1_vert_class *src_verts=m->get_verts(o->draw_params.animation, o->draw_params.frame);
|
---|
114 |
|
---|
115 | for (i=0; i<m->num_quad; i++, f++)
|
---|
116 | {
|
---|
117 | memcpy(f->indices, m->quad[i].vertex_ref, sizeof(f->indices));
|
---|
118 |
|
---|
119 | i4_3d_vector center(0,0,0);
|
---|
120 | int tv=f->num_verts();
|
---|
121 | for (j=0; j<tv; j++)
|
---|
122 | {
|
---|
123 | i4_3d_vector t_vert;
|
---|
124 | cur_transform->transform(src_verts[m->quad[i].vertex_ref[j]].v, t_vert);
|
---|
125 |
|
---|
126 | center += t_vert;
|
---|
127 | v[j].v = t_vert;
|
---|
128 | v[j].s = m->quad[i].u[j];
|
---|
129 | v[j].t = m->quad[i].v[j];
|
---|
130 |
|
---|
131 | f->indices[j] = vertex_count++;
|
---|
132 | }
|
---|
133 |
|
---|
134 | center/=(float)tv; // center is the average position of verts
|
---|
135 | f->pos = f->l_pos = center; // set 'position' of face to center location
|
---|
136 | for (j=0; j<tv; j++) // move points relative to center so they spind about it
|
---|
137 | v[j].v -= center;
|
---|
138 |
|
---|
139 | v+=tv;
|
---|
140 |
|
---|
141 | obj_center+=center;
|
---|
142 | }
|
---|
143 |
|
---|
144 | if (m->num_quad)
|
---|
145 | obj_center/=(float)m->num_quad;
|
---|
146 | }
|
---|
147 | }
|
---|
148 |
|
---|
149 | void g1_explode_model_class::setup(g1_object_class *source_obj,
|
---|
150 | const i4_3d_vector ¢er,
|
---|
151 | g1_explode_params &_params)
|
---|
152 | {
|
---|
153 | x=lx=center.x;
|
---|
154 | y=ly=center.y;
|
---|
155 | h=lh=center.z;
|
---|
156 |
|
---|
157 | if (x<0 || y<0 || x>=g1_get_map()->width() || y>=g1_get_map()->height())
|
---|
158 | request_remove();
|
---|
159 | else
|
---|
160 | {
|
---|
161 | i4_3d_vector c;
|
---|
162 | grab_model(source_obj, c);
|
---|
163 | params=_params;
|
---|
164 |
|
---|
165 | if (center.x==0)
|
---|
166 | {
|
---|
167 | x=lx=c.x;
|
---|
168 | y=ly=c.y;
|
---|
169 | h=lh=c.z;
|
---|
170 | }
|
---|
171 |
|
---|
172 |
|
---|
173 |
|
---|
174 | int i;
|
---|
175 | for (i=0; i<num_faces; i++)
|
---|
176 | {
|
---|
177 | faces[i].vel = params.initial_vel;
|
---|
178 | faces[i].angular_vel = faces[i].angles = faces[i].l_angles = i4_3d_vector(0,0,0);
|
---|
179 | }
|
---|
180 | occupy_location();
|
---|
181 | request_think();
|
---|
182 | }
|
---|
183 | }
|
---|
184 |
|
---|
185 | void g1_explode_model_class::think()
|
---|
186 | {
|
---|
187 | if (params.stages[params.current_stage].ticks<=0)
|
---|
188 | {
|
---|
189 | params.current_stage++;
|
---|
190 | if (params.current_stage>=params.t_stages)
|
---|
191 | {
|
---|
192 | unoccupy_location();
|
---|
193 | request_remove();
|
---|
194 | return ;
|
---|
195 | }
|
---|
196 | }
|
---|
197 |
|
---|
198 | params.stages[params.current_stage].ticks--;
|
---|
199 | float force=params.stages[params.current_stage].force;
|
---|
200 | float air_friction=params.stages[params.current_stage].air_friction;
|
---|
201 | float f;
|
---|
202 | i4_3d_vector d;
|
---|
203 |
|
---|
204 | for (int i=0; i<num_faces; i++)
|
---|
205 | {
|
---|
206 | g1_explode_face_class *face=faces+i;
|
---|
207 |
|
---|
208 |
|
---|
209 | if (params.stages[params.current_stage].type==G1_APPLY_SING || i==0)
|
---|
210 | {
|
---|
211 | d=i4_3d_vector(face->pos.x-x, face->pos.y-y, face->pos.z-h);
|
---|
212 | float d_len=d.length();
|
---|
213 | d/=d_len;
|
---|
214 |
|
---|
215 | f=force/(d_len*d_len);
|
---|
216 | d*=f;
|
---|
217 | d.z-=params.gravity;
|
---|
218 | }
|
---|
219 |
|
---|
220 | if (params.stages[params.current_stage].type==G1_APPLY_SING || (((g1_tick_counter+i)&31)==0))
|
---|
221 | {
|
---|
222 |
|
---|
223 | float xr=(g1_float_rand(9)-0.5) *0.2;
|
---|
224 | float yr=(g1_float_rand(3)-0.5) *0.2;
|
---|
225 | float zr=(g1_float_rand(4)-0.5) *0.2;
|
---|
226 |
|
---|
227 |
|
---|
228 |
|
---|
229 | faces[i].angular_vel.x = xr;
|
---|
230 | faces[i].angular_vel.y = yr;
|
---|
231 | faces[i].angular_vel.z = zr;
|
---|
232 | }
|
---|
233 |
|
---|
234 |
|
---|
235 | face->vel *= air_friction;
|
---|
236 | face->vel += d;
|
---|
237 | face->l_pos = face->pos;
|
---|
238 |
|
---|
239 | i4_3d_vector ray=face->vel;
|
---|
240 |
|
---|
241 | g1_object_class *hit;
|
---|
242 | // if (g1_get_map()->check_non_player_collision(0xff, face->pos, ray, hit))
|
---|
243 | // face->vel.z *=-0.5; // not accurate, but who cares :)
|
---|
244 |
|
---|
245 | face->pos += ray;
|
---|
246 |
|
---|
247 | face->l_angles = face->angles;
|
---|
248 | face->angles += face->angular_vel;
|
---|
249 | i4_normalize_angle(face->angles.x);
|
---|
250 | i4_normalize_angle(face->angles.y);
|
---|
251 | i4_normalize_angle(face->angles.z);
|
---|
252 | }
|
---|
253 | request_think();
|
---|
254 | }
|
---|
255 |
|
---|
256 |
|
---|
257 | i4_profile_class pf_exp_model_draw_transform("explode_model_draw::transform");
|
---|
258 | i4_profile_class pf_exp_model_draw_get_ambient("explode_model_draw::get_ambient");
|
---|
259 |
|
---|
260 | r1_texture_ref g1_burnt_texture("solid_black");
|
---|
261 |
|
---|
262 | void fast_transform(i4_transform_class *t, const i4_3d_vector &src, r1_3d_point_class &dst);
|
---|
263 |
|
---|
264 | void g1_explode_model_class::draw(g1_draw_context_class *context)
|
---|
265 | {
|
---|
266 | pf_exp_model_draw.start();
|
---|
267 |
|
---|
268 | pf_exp_model_draw_transform.start();
|
---|
269 |
|
---|
270 | i4_transform_class out,face_trans;
|
---|
271 |
|
---|
272 | int i,j,k;
|
---|
273 |
|
---|
274 | i4_float scale_x = g1_render.scale_x;
|
---|
275 | i4_float scale_y = g1_render.scale_y;
|
---|
276 |
|
---|
277 | r1_vert t_vertices[2048];
|
---|
278 | r1_vert clip_buf_1[64];
|
---|
279 | r1_vert clip_buf_2[64];
|
---|
280 |
|
---|
281 | g1_explode_vertex_class *src_v = vertices;
|
---|
282 | r1_vert *v = t_vertices;
|
---|
283 |
|
---|
284 | w8 ANDCODE = 0xFF;
|
---|
285 | w8 ORCODE = 0;
|
---|
286 |
|
---|
287 | g1_explode_face_class *f = faces;
|
---|
288 |
|
---|
289 | w8 vertex_count = 0;
|
---|
290 |
|
---|
291 |
|
---|
292 |
|
---|
293 | g1_render.r_api->use_texture(g1_burnt_texture.get(), 0, 0);
|
---|
294 |
|
---|
295 |
|
---|
296 | for (i=0; i<num_faces; i++,f++)
|
---|
297 | {
|
---|
298 | i4_3d_vector interp_rot;
|
---|
299 |
|
---|
300 | interp_rot.x = i4_interpolate_angle(f->l_angles.x, f->angles.x, g1_render.frame_ratio);
|
---|
301 | interp_rot.y = i4_interpolate_angle(f->l_angles.y, f->angles.y, g1_render.frame_ratio);
|
---|
302 | interp_rot.z = i4_interpolate_angle(f->l_angles.z, f->angles.z, g1_render.frame_ratio);
|
---|
303 |
|
---|
304 | face_trans.rotate_x_y_z(interp_rot.x,interp_rot.y,interp_rot.z,i4_T);
|
---|
305 |
|
---|
306 | face_trans.t.interpolate(f->l_pos, f->pos, g1_render.frame_ratio);
|
---|
307 |
|
---|
308 | out.multiply(*context->transform,face_trans);
|
---|
309 |
|
---|
310 | w8 face_and = 0xFF;
|
---|
311 | g1_explode_vertex_class *src_face_v = src_v;
|
---|
312 | r1_vert *face_v = v;
|
---|
313 |
|
---|
314 | int tv=faces[i].num_verts();
|
---|
315 | for (j=0; j<tv; j++,src_v++,v++)
|
---|
316 | {
|
---|
317 | fast_transform(&out, src_v->v, v->v);
|
---|
318 |
|
---|
319 | v->v.x *= scale_x;
|
---|
320 | v->v.y *= scale_y;
|
---|
321 |
|
---|
322 | w8 code = r1_calc_outcode(v);
|
---|
323 | ANDCODE &= code;
|
---|
324 | ORCODE |= code;
|
---|
325 |
|
---|
326 | face_and &= code;
|
---|
327 |
|
---|
328 | if (!code)
|
---|
329 | {
|
---|
330 | //valid point
|
---|
331 | i4_float ooz = 1.f / v->v.z;
|
---|
332 |
|
---|
333 | v->px = v->v.x * ooz * g1_render.center_x + g1_render.center_x;
|
---|
334 | v->py = v->v.y * ooz * g1_render.center_y + g1_render.center_y;
|
---|
335 | v->w = ooz;
|
---|
336 | }
|
---|
337 | }
|
---|
338 |
|
---|
339 | if (face_and==0)
|
---|
340 | {
|
---|
341 | for (j=0; j<tv; j++,src_face_v++,face_v++,vertex_count++)
|
---|
342 | {
|
---|
343 | face_v->r = 0;
|
---|
344 | face_v->g = 0;
|
---|
345 | face_v->b = 0;
|
---|
346 | face_v->a = 1.0;
|
---|
347 | face_v->s = 0;
|
---|
348 | face_v->t = 0;
|
---|
349 | }
|
---|
350 | }
|
---|
351 | else
|
---|
352 | vertex_count += tv;
|
---|
353 | }
|
---|
354 |
|
---|
355 | pf_exp_model_draw_transform.stop();
|
---|
356 |
|
---|
357 | if (ANDCODE)
|
---|
358 | {
|
---|
359 | pf_exp_model_draw.stop();
|
---|
360 | return;
|
---|
361 | }
|
---|
362 |
|
---|
363 | f = faces;
|
---|
364 |
|
---|
365 | for (i=0; i<num_faces; i++, f++)
|
---|
366 | {
|
---|
367 | int tv=f->num_verts();
|
---|
368 |
|
---|
369 | if (ORCODE==0)
|
---|
370 | {
|
---|
371 | float nearest_w = 0;
|
---|
372 |
|
---|
373 | for (j=0; j<tv; j++)
|
---|
374 | {
|
---|
375 | r1_vert *temp_vert = &t_vertices[f->indices[j]];
|
---|
376 |
|
---|
377 | float ooz = temp_vert->w;
|
---|
378 |
|
---|
379 | if (ooz > nearest_w)
|
---|
380 | nearest_w=ooz;
|
---|
381 | }
|
---|
382 |
|
---|
383 | g1_render.r_api->render_poly(tv, t_vertices+f->indices[0]);
|
---|
384 | }
|
---|
385 | else
|
---|
386 | {
|
---|
387 | sw32 num_poly_verts = tv;
|
---|
388 |
|
---|
389 | r1_vert temp_buf_1[64];
|
---|
390 | r1_vert temp_buf_2[64];
|
---|
391 | r1_vert *clipped_poly;
|
---|
392 |
|
---|
393 | clipped_poly = g1_render.r_api->clip_poly(&num_poly_verts,
|
---|
394 | t_vertices,
|
---|
395 | (w16 *)f->indices,
|
---|
396 | temp_buf_1,
|
---|
397 | temp_buf_2,
|
---|
398 | R1_CLIP_NO_CALC_OUTCODE);
|
---|
399 |
|
---|
400 | if (clipped_poly && num_poly_verts>=3)
|
---|
401 | {
|
---|
402 | float nearest_w = 0;
|
---|
403 |
|
---|
404 | r1_vert *temp_vert = clipped_poly;
|
---|
405 |
|
---|
406 | for (j=0; j<num_poly_verts; j++, temp_vert++)
|
---|
407 | {
|
---|
408 | i4_float ooz = 1 / temp_vert->v.z;
|
---|
409 |
|
---|
410 | temp_vert->w = ooz;
|
---|
411 | temp_vert->px = temp_vert->v.x * ooz * g1_render.center_x + g1_render.center_x;
|
---|
412 | temp_vert->py = temp_vert->v.y * ooz * g1_render.center_y + g1_render.center_y;
|
---|
413 |
|
---|
414 | if (ooz > nearest_w)
|
---|
415 | nearest_w=ooz;
|
---|
416 | }
|
---|
417 |
|
---|
418 |
|
---|
419 | g1_render.r_api->render_poly(num_poly_verts,clipped_poly);
|
---|
420 | }
|
---|
421 | }
|
---|
422 | }
|
---|
423 |
|
---|
424 |
|
---|
425 | pf_exp_model_draw.stop();
|
---|
426 | }
|
---|
427 |
|
---|
428 | g1_explode_params::g1_explode_params()
|
---|
429 | {
|
---|
430 | stages[0].setup(1,0.01, G1_APPLY_WHOLE); // apply force for 2 ticks
|
---|
431 | stages[1].setup(3, 0, G1_APPLY_WHOLE); // wait 20 ticks with no force to watch results
|
---|
432 | stages[2].setup(2, 1.0, G1_APPLY_SING); // wait 20 ticks with no force to watch results
|
---|
433 | stages[3].setup(10, 0, G1_APPLY_SING); // wait 20 ticks with no force to watch results
|
---|
434 | t_stages=4;
|
---|
435 | current_stage=0;
|
---|
436 | gravity=0.02;
|
---|
437 | initial_vel=i4_3d_vector(0,0,0);
|
---|
438 | }
|
---|