render.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903
  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. #include "render.hh"
  9. #include "error/error.hh"
  10. #include "time/timedev.hh"
  11. #include "math/pi.hh"
  12. #include "window/win_evt.hh"
  13. #include "window/colorwin.hh"
  14. #include "max_object.hh"
  15. #include "gui/button.hh"
  16. #include "gui/text.hh"
  17. #include "loaders/load.hh"
  18. #include "device/keys.hh"
  19. #include "image/color.hh"
  20. #include "error/alert.hh"
  21. #include "obj3d.hh"
  22. #include "tmanage.hh"
  23. #include "loaders/dir_load.hh"
  24. #include "saver_id.hh"
  25. #include "r1_clip.hh"
  26. #include "r1_win.hh"
  27. #include "m1_info.hh"
  28. #include "st_edit.hh"
  29. #include "app/app.hh"
  30. #include "window/wmanager.hh"
  31. #include "lisp/lisp.hh"
  32. #include "max_load.hh"
  33. #include <stdio.h>
  34. /* render.cc
  35. Defines a window which will display an object made of polygons.
  36. Right now it just shows it wireframe
  37. */
  38. #include "id.hh"
  39. #include "g1_tint.hh"
  40. i4_image_class *background_bitmap=0;
  41. i4_event_handler_reference_class<m1_utility_window_class> m1_render_window;
  42. i4_float m1_utility_state_class::center_x() const { return m1_render_window->center_x; }
  43. i4_float m1_utility_state_class::center_y() const { return m1_render_window->center_y; }
  44. i4_float m1_utility_state_class::scale_x() const { return m1_render_window->scale_x; }
  45. i4_float m1_utility_state_class::scale_y() const { return m1_render_window->scale_y; }
  46. int m1_utility_state_class::width() const { return m1_render_window->width(); }
  47. int m1_utility_state_class::height() const { return m1_render_window->height(); }
  48. int m1_utility_state_class::mouse_x() const { return m1_render_window->mouse_x; }
  49. int m1_utility_state_class::mouse_y() const { return m1_render_window->mouse_y; }
  50. int m1_utility_state_class::last_x() const { return m1_render_window->last_x; }
  51. int m1_utility_state_class::last_y() const { return m1_render_window->last_y; }
  52. int m1_utility_state_class::buttons() const { return m1_render_window->grab; }
  53. inline i4_float m1_near_clip_z() { return r1_near_clip_z+0.1; }
  54. void m1_utility_window_class::init()
  55. {
  56. calc_params();
  57. }
  58. void m1_utility_window_class::set_object(const i4_const_str &filename)
  59. {
  60. m1_info.obj=m1_load_model(filename, api->get_tmanager());
  61. if (m1_st_edit.get())
  62. m1_st_edit->edit_poly_changed();
  63. if (get_obj())
  64. i4_alert(i4gets("model_stats"),200, &filename, get_obj()->num_quad, get_obj()->num_vertex);
  65. request_redraw(i4_F);
  66. }
  67. m1_utility_window_class::m1_utility_window_class(w16 window_width,
  68. w16 window_height,
  69. r1_render_api_class *api,
  70. i4_window_manager_class *wm,
  71. i4_float theta,
  72. i4_float phi,
  73. i4_float dist)
  74. : i4_parent_window_class(window_width,window_height),
  75. api(api),
  76. wm(wm),
  77. theta(theta),
  78. phi(phi),
  79. dist(dist),
  80. grab(0),
  81. state(0),
  82. animating(0)
  83. {
  84. pan_x=pan_y=pan_z=0;
  85. draws_needed=0;
  86. recalc_view();
  87. restore_state();
  88. }
  89. void m1_utility_window_class::recenter()
  90. {
  91. theta=0;
  92. phi=0;
  93. dist=40;
  94. request_redraw(i4_F);
  95. }
  96. void m1_utility_window_class::recalc_view()
  97. {
  98. i4_transform_class tmp,tmp2,tmptmp;
  99. i4_float greaterdimension;
  100. transform.identity();
  101. tmp.translate(pan_x,pan_y,pan_z);
  102. transform.multiply(tmp);
  103. tmp.translate(0,0,dist);
  104. transform.multiply(tmp);
  105. tmp.rotate_x(i4_pi() - phi);
  106. transform.multiply(tmp);
  107. tmp.rotate_z(theta);
  108. transform.multiply(tmp);
  109. // calc_params();
  110. }
  111. void m1_utility_window_class::pan(i4_float x, i4_float y)
  112. {
  113. request_redraw(i4_F);
  114. pan_x-=x*dist;
  115. pan_y-=y*dist;
  116. recalc_view();
  117. }
  118. void m1_utility_window_class::select_poly(int poly_num)
  119. {
  120. if (!m1_info.obj) return;
  121. if (poly_num==-1)
  122. return;
  123. g1_quad_class *q = &m1_info.obj->quad[poly_num];
  124. q->set_flags(g1_quad_class::SELECTED, ~q->get_flags(g1_quad_class::SELECTED));
  125. m1_st_edit->edit_poly_changed();
  126. request_redraw(i4_F);
  127. }
  128. void m1_utility_window_class::drop_files(int t_files, i4_str **filenames)
  129. {
  130. int i;
  131. i4_array<i4_str *> gmods(0,32);
  132. // check to see if any of the files dropped are gmods
  133. for (i=0; i<t_files; i++)
  134. {
  135. i4_filename_struct fn;
  136. i4_split_path(*filenames[i], fn);
  137. if (strcmp(fn.extension,"gmod")==0)
  138. gmods.add(filenames[i]);
  139. }
  140. if (gmods.size())
  141. {
  142. for (i=0; i<m1_info.models.size(); i++)
  143. delete m1_info.models[i];
  144. m1_info.models.clear();
  145. for (i=0; i<gmods.size(); i++)
  146. m1_info.models.add(new i4_str(*gmods[i]));
  147. set_object(*m1_info.models[0]);
  148. }
  149. }
  150. void m1_utility_window_class::receive_event(i4_event *ev)
  151. //{{{
  152. {
  153. int pre_grab = grab;
  154. switch (ev->type())
  155. {
  156. case i4_event::WINDOW_MESSAGE:
  157. {
  158. CAST_PTR(wev, i4_window_message_class, ev);
  159. if (wev->sub_type==i4_window_message_class::GOT_DROP)
  160. {
  161. CAST_PTR(dev, i4_window_got_drop_class, ev);
  162. if (dev->drag_info.drag_object_type==i4_drag_info_struct::FILENAMES)
  163. drop_files(dev->drag_info.t_filenames, dev->drag_info.filenames);
  164. }
  165. } break;
  166. case i4_event::MOUSE_BUTTON_DOWN:
  167. {
  168. CAST_PTR(bev, i4_mouse_button_down_event_class, ev);
  169. if (bev->but == i4_mouse_button_down_event_class::LEFT)
  170. grab |= LEFT_BUTTON;
  171. if (bev->but == i4_mouse_button_down_event_class::RIGHT)
  172. grab |= RIGHT_BUTTON;
  173. if (bev->but == i4_mouse_button_down_event_class::CENTER)
  174. grab |= MIDDLE_BUTTON;
  175. i4_window_request_key_grab_class kgrab(this);
  176. i4_kernel.send_event(parent, &kgrab);
  177. state->mouse_down();
  178. } break;
  179. case i4_event::MOUSE_BUTTON_UP:
  180. {
  181. CAST_PTR(bev, i4_mouse_button_up_event_class, ev);
  182. if (bev->but == i4_mouse_button_down_event_class::LEFT)
  183. grab &= ~LEFT_BUTTON;
  184. if (bev->but == i4_mouse_button_down_event_class::RIGHT)
  185. grab &= ~RIGHT_BUTTON;
  186. if (bev->but == i4_mouse_button_down_event_class::CENTER)
  187. grab &= ~MIDDLE_BUTTON;
  188. state->mouse_up();
  189. } break;
  190. case i4_event::MOUSE_MOVE:
  191. {
  192. i4_window_class::receive_event(ev);
  193. int do_redraw = 0;
  194. if (!grab)
  195. {
  196. do_redraw = find_hit(mouse_x,mouse_y);
  197. if (do_redraw)
  198. m1_st_edit->change_current_verts();
  199. }
  200. else
  201. do_redraw = state->mouse_drag();
  202. if (do_redraw)
  203. {
  204. recalc_view();
  205. request_redraw(i4_F);
  206. wm->root_draw();
  207. }
  208. last_x = mouse_x;
  209. last_y = mouse_y;
  210. } break;
  211. case i4_event::KEY_PRESS:
  212. {
  213. CAST_PTR(kev, i4_key_press_event_class, ev);
  214. switch (kev->key)
  215. {
  216. case I4_LEFT : pan(-0.05,0); break;
  217. case I4_RIGHT : pan(0.05,0); break;
  218. case I4_UP : pan(0,-0.05); break;
  219. case I4_DOWN : pan(0,0.05); break;
  220. case 'z':
  221. case 'Z': grab |= LEFT_KEY; state->mouse_down(); break;
  222. case 'x':
  223. case 'X': grab |= MIDDLE_KEY; state->mouse_down(); break;
  224. case 'c':
  225. case 'C': grab |= RIGHT_KEY; state->mouse_down(); break;
  226. }
  227. } break;
  228. case i4_event::KEY_RELEASE:
  229. {
  230. CAST_PTR(kev, i4_key_release_event_class, ev);
  231. switch (kev->key)
  232. {
  233. case 'z':
  234. case 'Z': grab &= ~LEFT_KEY; state->mouse_up(); break;
  235. case 'x':
  236. case 'X': grab &= ~MIDDLE_KEY; state->mouse_up(); break;
  237. case 'c':
  238. case 'C': grab &= ~RIGHT_KEY; state->mouse_up(); break;
  239. }
  240. } break;
  241. }
  242. if (!pre_grab && grab)
  243. {
  244. i4_window_request_mouse_grab_class grab_ev(this);
  245. i4_kernel.send_event(parent,&grab_ev);
  246. }
  247. if (pre_grab && !grab)
  248. {
  249. i4_window_request_mouse_ungrab_class grab_ev(this);
  250. i4_kernel.send_event(parent,&grab_ev);
  251. }
  252. i4_parent_window_class::receive_event(ev);
  253. }
  254. //}}}
  255. i4_bool m1_utility_window_class::project_point(const i4_3d_point_class &p, r1_vert &v)
  256. //{{{
  257. {
  258. i4_3d_vector &temp_v = (i4_3d_vector &)v.v;
  259. transform.transform(p,temp_v);
  260. v.v.x *= scale_x;
  261. v.v.y *= scale_y;
  262. if (v.v.z>0.001)
  263. {
  264. float ooz = r1_ooz(v.v.z);
  265. v.px = v.v.x * ooz * center_x + center_x;
  266. v.py = v.v.y * ooz * center_y + center_y;
  267. v.w = ooz;
  268. return i4_T;
  269. }
  270. return i4_F;
  271. }
  272. //}}}
  273. void m1_utility_window_class::draw_3d_text(i4_3d_point_class p,
  274. const i4_const_str &str,
  275. w32 color,
  276. i4_draw_context_class &context)
  277. {
  278. r1_vert v;
  279. if (project_point(p, v))
  280. {
  281. int x=(int)(v.px-m1_info.r_font->width(str)/2);
  282. m1_info.r_api->set_constant_color(0);
  283. m1_info.r_font->set_color(0);
  284. m1_info.r_font->put_string(local_image, x+1, v.py+1, str, context);
  285. m1_info.r_api->set_constant_color(0xffffff);
  286. m1_info.r_font->set_color(color);
  287. m1_info.r_font->put_string(local_image, x, v.py, str, context);
  288. }
  289. }
  290. void m1_utility_window_class::draw_3d_line(i4_3d_point_class p1,
  291. i4_3d_point_class p2,
  292. i4_color color,
  293. i4_bool on_top)
  294. //{{{
  295. {
  296. r1_vert v[2];
  297. project_point(p1, v[0]);
  298. project_point(p2, v[1]);
  299. api->set_shading_mode(R1_CONSTANT_SHADING);
  300. api->set_constant_color(color);
  301. api->set_alpha_mode(R1_ALPHA_DISABLED);
  302. api->disable_texture();
  303. r1_clip_render_lines(1, v, center_x, center_y, api);
  304. api->set_constant_color(0xffffff);
  305. }
  306. //}}}
  307. void m1_utility_window_class::draw_3d_point(i4_3d_point_class p, i4_color color, i4_bool on_top)
  308. //{{{
  309. {
  310. r1_vert v;
  311. project_point(p, v);
  312. int ix = int(v.px),iy = int(v.py);
  313. if (ix>0 && iy>0 && ix<center_x*2-1 && iy<center_y*2-1)
  314. {
  315. api->set_alpha_mode(R1_ALPHA_DISABLED);
  316. api->disable_texture();
  317. api->r1_render_api_class::clear_area(ix-1,iy-1,ix+1,iy+1,color,
  318. on_top ? v.v.z : m1_near_clip_z());
  319. }
  320. }
  321. //}}}
  322. void m1_utility_window_class::draw_plane(const i4_3d_vector &u, const i4_3d_vector &v, w8 color)
  323. //{{{
  324. {
  325. if (color>0x10)
  326. {
  327. w32 col = color*0x010101;
  328. i4_3d_point_class zero(0,0,0), t1, t2, s1, s2;
  329. t1 = u;
  330. t1 += v;
  331. t1 *= -10;
  332. t2 = u;
  333. t2 -= v;
  334. t2 *= -10;
  335. s1 = t1;
  336. s2 = t2;
  337. s2.reverse();
  338. for (int x=-10; x<=10; x++)
  339. {
  340. draw_3d_line(t1, x?t2:zero, col);
  341. draw_3d_line(s1, x?s2:zero, col);
  342. s1 += v;
  343. s2 += v;
  344. t1 += u;
  345. t2 += u;
  346. }
  347. }
  348. }
  349. //}}}
  350. static r1_vert t_vertices[3000], clip_buf_1[3000], clip_buf_2[3000];
  351. static int src_quad[4], dst1[3000], dst2[3000];
  352. void m1_utility_window_class::update_object(i4_float time)
  353. //{{{
  354. {
  355. get_obj()->update(m1_info.time);
  356. }
  357. //}}}
  358. void m1_utility_window_class::render_object(i4_draw_context_class &context)
  359. //{{{
  360. {
  361. g1_quad_object_class *obj = get_obj();
  362. int i,j,k,num_vertices;
  363. num_vertices = obj->num_vertex;
  364. r1_vert *v = t_vertices;
  365. g1_vert_class *src_vert = obj->get_verts(m1_info.current_animation,
  366. m1_info.current_frame);
  367. w8 ANDCODE = 0xFF;
  368. w8 ORCODE = 0;
  369. //api->disable_texture();
  370. //api->set_shading_mode(R1_CONSTANT_SHADING);
  371. //api->set_alpha_mode(R1_ALPHA_CONSTANT);
  372. //api->set_constant_color(0x7F000000);
  373. //api->set_write_mode(R1_COMPARE_W | R1_WRITE_COLOR);
  374. api->set_shading_mode(R1_COLORED_SHADING);
  375. if (!m1_info.get_flags(M1_WIREFRAME))
  376. {
  377. i4_3d_vector cam_in_object_space;
  378. transform.inverse_transform(i4_3d_vector(0,0,0),cam_in_object_space);
  379. i4_3d_vector light=i4_3d_vector(0,0.2, 0.9), light_dir;
  380. light.normalize();
  381. transform.transform_3x3(light, light_dir);
  382. for (i=0; i<num_vertices; i++, v++)
  383. {
  384. i4_3d_vector &temp_v = (i4_3d_vector &)v->v;
  385. transform.transform(src_vert[i].v, temp_v);
  386. v->v.x *= scale_x;
  387. v->v.y *= scale_y;
  388. if (m1_info.get_flags(M1_SHADING))
  389. {
  390. i4_float intensity = 0.5 * src_vert[i].normal.dot(light_dir) + 0.5;
  391. if (intensity<0) intensity=0;
  392. if (intensity>1) intensity=1;
  393. v->r = intensity;
  394. v->g = intensity;
  395. v->b = intensity;
  396. v->a = intensity;
  397. }
  398. else
  399. {
  400. v->r = 1;
  401. v->g = 1;
  402. v->b = 1;
  403. v->a = 1;
  404. }
  405. w8 code = r1_calc_outcode(v);
  406. ANDCODE &= code;
  407. ORCODE |= code;
  408. }
  409. if (ANDCODE) return;
  410. api->set_constant_color(0xffffff);
  411. api->set_shading_mode(R1_WHITE_SHADING);
  412. g1_quad_class *q = obj->quad;
  413. for (i=0; i<obj->num_quad; i++, q++)
  414. {
  415. sw32 num_poly_verts = q->num_verts();
  416. i4_3d_vector cam_to_pt = src_vert[q->vertex_ref[0]].v;
  417. cam_to_pt -= cam_in_object_space;
  418. float dot = cam_to_pt.dot(q->normal);
  419. if (dot<0)
  420. {
  421. // copy in the texture coordinates
  422. for (j=0; j<num_poly_verts; j++)
  423. {
  424. int ref=q->vertex_ref[j];
  425. src_quad[j]=ref;
  426. v = &t_vertices[ref];
  427. v->s = q->u[j];
  428. v->t = q->v[j];
  429. }
  430. if (q->get_flags(g1_quad_class::TINT) && m1_info.current_team!=100)
  431. api->set_color_tint(g1_player_tint_handles[m1_info.current_team]);
  432. else
  433. api->set_color_tint(0);
  434. if (ORCODE==0)
  435. {
  436. float nearest_w = 0;
  437. for (j=0; j<num_poly_verts; j++)
  438. {
  439. r1_vert *temp_vert = &t_vertices[q->vertex_ref[j]];
  440. float ooz = r1_ooz(temp_vert->v.z);
  441. if (ooz > nearest_w)
  442. nearest_w=ooz;
  443. temp_vert->px = temp_vert->v.x * ooz * center_x + center_x;
  444. temp_vert->py = temp_vert->v.y * ooz * center_y + center_y;
  445. temp_vert->w = ooz;
  446. }
  447. i4_float twidth = nearest_w * q->texture_scale * center_x * 2;
  448. api->use_texture(q->material_ref, i4_f_to_i(twidth), m1_info.current_frame);
  449. api->render_poly(num_poly_verts,t_vertices,q->vertex_ref);
  450. }
  451. else
  452. {
  453. r1_vert temp_buf_1[64];
  454. r1_vert temp_buf_2[64];
  455. r1_vert *clipped_poly = api->clip_poly(&num_poly_verts,
  456. t_vertices,
  457. q->vertex_ref,
  458. temp_buf_1,
  459. temp_buf_2,
  460. R1_CLIP_NO_CALC_OUTCODE);
  461. if (clipped_poly && num_poly_verts>=3)
  462. {
  463. float nearest_w = 0;
  464. for (j=0; j<num_poly_verts; j++)
  465. {
  466. float ooz = r1_ooz(clipped_poly[j].v.z);
  467. if (ooz > nearest_w)
  468. nearest_w=ooz;
  469. clipped_poly[j].px = clipped_poly[j].v.x * ooz * center_x + center_x;
  470. clipped_poly[j].py = clipped_poly[j].v.y * ooz * center_y + center_y;
  471. clipped_poly[j].w = ooz;
  472. }
  473. i4_float twidth = nearest_w * q->texture_scale * center_x * 2;
  474. api->use_texture(q->material_ref, i4_f_to_i(twidth), m1_info.current_frame);
  475. api->render_poly(num_poly_verts,clipped_poly);
  476. }
  477. }
  478. }
  479. }
  480. }
  481. // Axis display
  482. if (m1_info.get_flags(M1_SHOW_AXIS))
  483. {
  484. draw_3d_line (i4_3d_point_class(0,0,0), i4_3d_point_class(100,0,0), 0xd0d000);
  485. draw_3d_line (i4_3d_point_class(0,0,0), i4_3d_point_class(0,100,0), 0xd0d0d0);
  486. draw_3d_line (i4_3d_point_class(0,0,0), i4_3d_point_class(0,0,100), 0xd0d0d0);
  487. int x,y;
  488. const i4_float axis_range=0.5;
  489. w32 col;
  490. if (dist>4)
  491. {
  492. col = w32(transform.z.z*transform.z.z*0x80);
  493. draw_plane(i4_3d_vector(10,0,0), i4_3d_vector(0,10,0), col);
  494. col = w32(transform.y.z*transform.y.z*0x60);
  495. draw_plane(i4_3d_vector(10,0,0), i4_3d_vector(0,0,10), col);
  496. col = w32(transform.x.z*transform.x.z*0x60);
  497. draw_plane(i4_3d_vector(0,10,0), i4_3d_vector(0,0,10), col);
  498. }
  499. if (dist<15)
  500. {
  501. i4_float fade = (15 - dist)*0.2;
  502. fade = fade>1.0? 1.0 : fade;
  503. col = w32(fade*transform.z.z*transform.z.z*0x80);
  504. draw_plane(i4_3d_vector(1,0,0), i4_3d_vector(0,1,0), col);
  505. col = w32(fade*transform.y.z*transform.y.z*0x60);
  506. draw_plane(i4_3d_vector(1,0,0), i4_3d_vector(0,0,1), col);
  507. col = w32(fade*transform.x.z*transform.x.z*0x60);
  508. draw_plane(i4_3d_vector(0,1,0), i4_3d_vector(0,0,1), col);
  509. }
  510. }
  511. api->set_write_mode(R1_WRITE_COLOR);
  512. // draw wire stuff
  513. w32 color=0xffffff;
  514. int q;
  515. for (q=0; q<obj->num_quad; q++)
  516. {
  517. if (m1_info.get_flags(M1_WIREFRAME) ||
  518. obj->quad[q].get_flags(g1_quad_class::SELECTED |
  519. m1_poly_object_class::INVALID_QUAD))
  520. {
  521. if (obj->quad[q].get_flags(g1_quad_class::SELECTED))
  522. color=0xffff00;
  523. else if (obj->quad[q].get_flags(m1_poly_object_class::INVALID_QUAD))
  524. color=0xff0000;
  525. else
  526. color=0x404040;
  527. i4_3d_point_class p1,p2;
  528. p2=src_vert[obj->quad[q].vertex_ref[0]].v;
  529. for (i=obj->quad[q].num_verts()-1; i>=0; i--)
  530. {
  531. p1=src_vert[obj->quad[q].vertex_ref[i]].v;
  532. draw_3d_line(p1, p2, color, i4_T);
  533. p2 = p1;
  534. }
  535. }
  536. }
  537. // preselections
  538. api->set_color_tint(0);
  539. if (m1_info.preselect_poly>=0)
  540. {
  541. i4_3d_point_class p1,p2;
  542. g1_quad_class *q = &obj->quad[m1_info.preselect_poly];
  543. p2=src_vert[q->vertex_ref[0]].v;
  544. color=0x0000ff;
  545. for (i=q->num_verts()-1; i>=0; i--)
  546. {
  547. p1=src_vert[q->vertex_ref[i]].v;
  548. draw_3d_line(p1, p2, color, i4_T);
  549. p2 = p1;
  550. }
  551. }
  552. if (m1_info.preselect_point>=0)
  553. draw_3d_point(src_vert[m1_info.preselect_point].v, 0xff00ff, i4_T);
  554. // mount points
  555. for (i=0; i<obj->num_mounts; i++)
  556. draw_3d_point(obj->mount[i], 0x006060, i4_T);
  557. for (i=0; i<obj->num_mounts; i++)
  558. draw_3d_point(obj->mount[i], 0x00ffff);
  559. if (m1_info.flags & (M1_SHOW_FACE_NUMBERS | M1_SHOW_FACE_NAMES))
  560. {
  561. for (q=0; q<obj->num_quad; q++)
  562. {
  563. if (obj->quad[q].get_flags(g1_quad_class::SELECTED))
  564. {
  565. int t_verts=obj->quad[q].num_verts();
  566. i4_3d_vector sum=i4_3d_vector(0,0,0);
  567. for (i=0; i<t_verts; i++)
  568. sum+=src_vert[obj->quad[q].vertex_ref[i]].v;
  569. sum/=(float)t_verts;
  570. char buf[150];
  571. buf[0]=0;
  572. if (m1_info.flags & M1_SHOW_FACE_NUMBERS)
  573. sprintf(buf, "%d ", q);
  574. if ((m1_info.flags & M1_SHOW_FACE_NAMES) && m1_info.obj->texture_names[q])
  575. i4_os_string(*m1_info.obj->texture_names[q], buf+strlen(buf), 100);
  576. draw_3d_text(sum, buf, 0xffffff, context);
  577. }
  578. }
  579. }
  580. if (m1_info.flags & (M1_SHOW_VERT_NUMBERS))
  581. {
  582. for (int v=0; v<obj->num_vertex; v++)
  583. {
  584. int used=0;
  585. for (q=0; q<obj->num_quad; q++)
  586. if (obj->quad[q].get_flags(g1_quad_class::SELECTED))
  587. {
  588. int t_verts=obj->quad[q].num_verts();
  589. for (int qv=0; qv<t_verts; qv++)
  590. if (obj->quad[q].vertex_ref[qv]==v)
  591. used=1;
  592. }
  593. if (used)
  594. {
  595. char buf[100];
  596. sprintf(buf,"%d", v);
  597. draw_3d_text(src_vert[v].v, buf, 0x00ffff, context);
  598. }
  599. }
  600. }
  601. }
  602. //}}}
  603. void m1_utility_window_class::parent_draw(i4_draw_context_class &context)
  604. //{{{
  605. {
  606. if (m1_info.recalcing_textures)
  607. {
  608. local_image->clear(0, context);
  609. return;
  610. }
  611. if (background_bitmap)
  612. {
  613. for (w32 y=0; y<height(); y+=background_bitmap->height())
  614. for (w32 x=0; x<width(); x+=background_bitmap->width())
  615. background_bitmap->put_image(local_image, x,y, context);
  616. }
  617. // else
  618. // local_image->clear(15,context);
  619. //local_image->add_dirty(0,0,width()-1,height()-1, context);
  620. // recalc_view();
  621. ((r1_render_window_class *)parent)->begin_render();
  622. m1_poly_object_class *obj=get_obj();
  623. if (obj)
  624. {
  625. obj->calc_vert_normals();
  626. api->default_state();
  627. api->set_z_range(0.01, 1000);
  628. //r1_far_clip_z = 1000;
  629. api->clear_area(0,0, width()-1, height()-1, m1_info.bg_color, 1000-1);
  630. api->set_filter_mode(R1_BILINEAR_FILTERING);
  631. if (animating)
  632. {
  633. i4_time_class now;
  634. m1_info.time += i4_float(now.milli_diff(last_time)) / 100.0;
  635. last_time = now;
  636. update_object(m1_info.time);
  637. request_redraw();
  638. }
  639. render_object(context);
  640. }
  641. else
  642. local_image->clear(0,context);
  643. i4_window_class::draw(context);
  644. ((r1_render_window_class *)parent)->end_render();
  645. // i4_time_dev.request_event(this,new i4_user_message_event_class(0),100);
  646. // request_redraw(i4_F);
  647. }
  648. //}}}
  649. i4_bool m1_utility_window_class::find_hit(int mx, int my)
  650. //{{{
  651. {
  652. i4_bool ret=i4_F;
  653. g1_quad_object_class *obj=get_obj();
  654. // select point
  655. if (obj)
  656. {
  657. g1_vert_class *src_vert = obj->get_verts(m1_info.current_animation, m1_info.current_frame);
  658. r1_vert tmp_v;
  659. i4_float left = mx-3,right = mx+3, top=my-3, bottom=my+3;
  660. int p=-1, np=m1_info.preselect_point;
  661. for (int j=0; j<obj->num_quad; j++)
  662. {
  663. if (obj->quad[j].get_flags(g1_quad_class::SELECTED))
  664. for (int i=0; i<obj->quad[j].num_verts(); i++)
  665. {
  666. int v = obj->quad[j].vertex_ref[i];
  667. project_point(src_vert[v].v, tmp_v);
  668. if (tmp_v.px>=left && tmp_v.px<=right && tmp_v.py>top && tmp_v.py<bottom)
  669. p = v;
  670. }
  671. }
  672. m1_info.preselect_point = p;
  673. if (p!=np)
  674. ret = i4_T;
  675. }
  676. int p, np=m1_info.preselect_poly;
  677. if (m1_info.preselect_point<0)
  678. {
  679. // find ray in camera space
  680. i4_float px = (i4_float(mx)-center_x)/(center_x*scale_x);
  681. i4_float py = (i4_float(my)-center_y)/(center_y*scale_y);
  682. i4_3d_vector point,ray;
  683. transform.inverse_transform(i4_3d_vector(0,0,0), point);
  684. transform.inverse_transform(i4_3d_vector(px,py,1.0), ray);
  685. ray -= point;
  686. ray *= 10000;
  687. // select poly
  688. if (!obj || !obj->intersect(point, ray,
  689. m1_info.current_animation, m1_info.current_frame,
  690. 0, &p))
  691. p=-1;
  692. }
  693. else
  694. p = -1;
  695. m1_info.preselect_poly=p;
  696. if (np!=m1_info.preselect_poly)
  697. ret = i4_T;
  698. return ret;
  699. }
  700. //}}}
  701. extern m1_utility_state_class *m1_default_state;
  702. void m1_utility_window_class::restore_state()
  703. //{{{
  704. {
  705. state = m1_default_state;
  706. }
  707. //}}}
  708. //{{{ Emacs Locals
  709. // Local Variables:
  710. // folded-file: t
  711. // End:
  712. //}}}