2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/nebedit/NebEdit.cpp $
15 * Program to edit nebulas in 2d
18 * Revision 1.3 2002/06/09 04:41:23 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:47 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:10 root
28 * 7 7/15/99 3:07p Dave
29 * 32 bit detection support. Mouse coord commandline.
31 * 6 5/19/99 4:07p Dave
32 * Moved versioning code into a nice isolated common place. Fixed up
33 * updating code on the pxo screen. Fixed several stub problems.
35 * 5 1/08/99 2:06p Dave
36 * Fixed pfoview for software mode.
38 * 4 12/18/98 1:14a Dave
39 * Rough 1024x768 support for Direct3D. Proper detection and usage through
42 * 3 11/13/98 2:32p Dave
43 * Improved commandline parsing for exe pathname.
45 * 2 10/24/98 9:51p Dave
47 * 1 10/24/98 9:39p Dave
49 * 13 4/13/98 10:11a John
50 * Made timer functions thread safe. Made timer_init be called in all
53 * 12 3/23/98 1:35p Sandeep
55 * 11 3/05/98 11:15p Hoffoss
56 * Changed non-game key checking to use game_check_key() instead of
59 * 10 12/29/97 5:10p Allender
60 * fixed problems with speed not being reported properly in multiplayer
61 * games. Made read_flying_controls take frametime as a parameter. More
62 * ship/weapon select stuff
64 * 9 12/04/97 3:47p John
65 * Made joystick move mouse cursor
67 * 8 11/21/97 11:32a John
68 * Added nebulas. Fixed some warpout bugs.
70 * 7 11/19/97 10:15p Adam
71 * upped maxtris to 200
73 * 6 11/19/97 4:28p Sandeep
74 * added poly/vert counter
76 * 5 11/19/97 1:59p Sandeep
77 * Added multiple vertex editing mode
79 * 4 11/16/97 2:29p John
80 * added versioning to nebulas; put nebula code into freespace.
82 * 3 11/13/97 12:04p Sandeep
83 * Added face editing support, deletion support, and a saving and loading
86 * 2 11/10/97 9:59p John
89 * 1 11/10/97 9:42p John
111 #include "floating.h"
114 #include "linklist.h"
115 #include "lighting.h"
131 physics_info ViewerPhysics;
132 float ViewerZoom = 1.0f;
135 int Fred_running = 0;
136 int Pofview_running = 0;
137 float flFrametime = 0.0f;
143 vector Global_light_world = { 0.208758f, -0.688253f, -0.694782f };
150 #define MAX_POINTS 300
152 int neb_w = 0, neb_h = 0;
154 int nebula_inited = 0;
157 int x[MAX_POINTS], y[MAX_POINTS], l[MAX_POINTS];
158 float scale_factor = 1.0f;
161 int tri[MAX_TRIS][3];
165 int Mouse_x, Mouse_y;
167 BOOL Selected[MAX_POINTS];
168 BOOL Sel_mode = 0; // 0 = 1 point at a time, 1 = select multiple points
171 int View_mode = 0; // 0 = 2d editor, 1 = 3d viewer
173 int Vert_mode = 0; // 0 = Move vertices/Add vertices, 2 = Move face/Add face
175 int Which_vert = 0; // Current vertex of the faceadd
181 BOOL Draw_sel_box = FALSE;
185 int Nebedit_running = 1;
187 extern void project_2d_onto_sphere(vector *, float, float);
190 void create_default_neb()
195 num_pts = neb_w*neb_h;
197 for (j=0; j<neb_h; j++ ) {
198 for (i=0; i<neb_w; i++ ) {
199 x[i+j*neb_w] = ((i+1)*SCREEN_W)/(neb_w+2);
200 y[i+j*neb_w] = ((j+3)*SCREEN_H)/(neb_h+6);
201 if ( (j==0) || (j==neb_h-1)) {
211 for (j=0; j<neb_h-1; j++ ) {
212 for (i=0; i<neb_w-1; i++ ) {
213 tri[num_tris][0] = i+neb_w*j;
214 tri[num_tris][1] = i+neb_w*j+1;
215 tri[num_tris][2] = i+neb_w*(j+1)+1;
218 tri[num_tris][0] = i+neb_w*j;
219 tri[num_tris][1] = i+neb_w*(j+1)+1;
220 tri[num_tris][2] = i+neb_w*(j+1);
228 #define NEBULA_FILE_ID "NEBU"
229 #define NEBULA_MAJOR_VERSION 1 // Can be 1-?
230 #define NEBULA_MINOR_VERSION 0 // Can be 0-99
232 void save_nebula_sub(const char *filename)
240 fp = fopen(filename, "wb");
243 fwrite( "NEBU", 4, 1, fp );
244 version = NEBULA_MAJOR_VERSION*100+NEBULA_MINOR_VERSION;
245 tmp = INTEL_INT(version);
246 fwrite( &tmp, sizeof(int), 1, fp );
247 tmp = INTEL_INT(num_pts);
248 fwrite( &tmp, sizeof(int), 1, fp );
249 tmp = INTEL_INT(num_tris);
250 fwrite( &tmp, sizeof(int), 1, fp );
253 for (i=0; i<num_pts; i++ ) {
254 xf = INTEL_FLOAT(float(x[i])/640.0f);
255 yf = INTEL_FLOAT(float(y[i])/480.0f);
256 fwrite( &xf, sizeof(float), 1, fp );
257 fwrite( &yf, sizeof(float), 1, fp );
258 tmp = INTEL_INT(l[i]);
259 fwrite( &tmp, sizeof(int), 1, fp );
262 for (i=0; i<num_tris; i++ ) {
263 tmp = INTEL_INT(tri[i][0]);
264 fwrite( &tmp, sizeof(int), 1, fp );
265 tmp = INTEL_INT(tri[i][1]);
266 fwrite( &tmp, sizeof(int), 1, fp );
267 tmp = INTEL_INT(tri[i][2]);
268 fwrite( &tmp, sizeof(int), 1, fp );
274 // returns 0 if failed
275 int load_nebula_sub(const char *filename)
279 int version, major, minor;
281 fp = fopen(filename, "rb");
288 fread( id, 4, 1, fp );
289 if ( strncmp( id, NEBULA_FILE_ID, 4)) {
290 mprintf(( "Not a valid nebula file.\n" ));
294 fread( &version, sizeof(int), 1, fp );
295 version = INTEL_INT(version);
296 major = version / 100;
297 minor = version % 100;
299 if ( (major != NEBULA_MAJOR_VERSION) && (minor != NEBULA_MINOR_VERSION) ) {
300 mprintf(( "An out of date nebula file.\n" ));
304 fread( &num_pts, sizeof(int), 1, fp );
305 num_pts = INTEL_INT(num_pts);
306 SDL_assert( num_pts < MAX_POINTS );
307 fread( &num_tris, sizeof(int), 1, fp );
308 num_tris = INTEL_INT(num_tris);
309 SDL_assert( num_tris < MAX_TRIS );
311 for (int i=0; i<num_pts; i++ ) {
315 fread( &xf, sizeof(float), 1, fp );
316 fread( &yf, sizeof(float), 1, fp );
317 fread( &li, sizeof(int), 1, fp );
319 xf = INTEL_FLOAT(xf);
320 yf = INTEL_FLOAT(yf);
323 x[i] = (int)(xf*640.0f);
324 y[i] = (int)(yf*480.0f);
328 for (int i=0; i<num_tris; i++ ) {
329 fread( &tri[i][0], sizeof(int), 1, fp );
330 fread( &tri[i][1], sizeof(int), 1, fp );
331 fread( &tri[i][2], sizeof(int), 1, fp );
332 tri[i][0] = INTEL_INT(tri[i][0]);
333 tri[i][1] = INTEL_INT(tri[i][1]);
334 tri[i][2] = INTEL_INT(tri[i][2]);
344 save_nebula_sub( "autosaved.neb" );
352 char filename[255] = "\0";
353 //char filter[255] = "Nebula Files\0
355 memset(&o,0,sizeof(o));
356 o.lStructSize = sizeof(o);
357 //o.hwndOwner = GetActiveWindow();
358 o.lpstrFilter = "Nebula Files\0*.NEB\0\0";
359 o.lpstrFile = filename;
361 o.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
362 o.lpstrDefExt = "*.NEB";
363 if (!GetSaveFileName(&o)) return;
365 save_nebula_sub(filename);
374 int create_default = 0;
376 if ( !load_nebula_sub("nebula01.neb")) {
380 if ( create_default ) {
381 create_default_neb();
386 char filename[255] = "\0";
388 memset(&o,0,sizeof(o));
389 o.lStructSize = sizeof(OPENFILENAME);
390 //o.hwndOwner = GetActiveWindow();
391 o.lpstrFilter = "Nebula Files\0*.NEB\0\0";
392 o.lpstrFile = filename;
394 o.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
395 o.lpstrDefExt = "*.NEB";
397 int create_default = 0;
398 if (!GetOpenFileName(&o)) {
401 if ( !load_nebula_sub(filename)) {
406 if ( create_default ) {
407 create_default_neb();
416 if ( nebula_inited ) return;
417 memset(Selected, 0, sizeof(BOOL)*MAX_POINTS);
420 create_default_neb();
421 gr_init_alphacolor( &nebula_color, 0, 255, 0, 255, AC_TYPE_HUD );
426 void draw_tri_2d( int i, int j, int k )
435 vertex * verts[3] = { &va, &vb, &vc };
436 // gr_zbuffering = 0;
437 for (int v=0; v<3; v++ ) {
438 verts[v]->sx = i2fl(x[index[v]]);
439 verts[v]->sy = i2fl(y[index[v]]);
443 verts[v]->b = (ubyte)(i2fl(l[index[v]]*255)/31.0f);
446 // gr_set_color( 0, 0, 0 );
447 gr_tmapper(3, verts, TMAP_FLAG_RAMP | TMAP_FLAG_GOURAUD | TMAP_FLAG_NEBULA );
449 if ( !key_pressed(SDLK_LSHIFT) ) {
450 gr_set_color(100,100,100);
451 gr_line( x[i], y[i], x[j], y[j] );
452 gr_line( x[j], y[j], x[k], y[k] );
453 gr_line( x[k], y[k], x[i], y[i] );
457 void nebula_draw_2d()
461 for (i=0; i<num_tris; i++ ) {
462 draw_tri_2d( tri[i][0], tri[i][1], tri[i][2] );
465 gr_set_color(100,0,0);
466 for (i=0; i<num_pts; i++ ) {
467 gr_circle( x[i], y[i], 4 );
469 if ((Sel_mode==1)) { // multiple selection
471 gr_set_color(200,0,200);
472 gr_line(Orig_pos_x, Orig_pos_y, Orig_pos_x, End_pos_y);
473 gr_line(Orig_pos_x, End_pos_y, End_pos_x, End_pos_y);
474 gr_line(End_pos_x, Orig_pos_y, End_pos_x, End_pos_y);
475 gr_line(End_pos_x, Orig_pos_y, Orig_pos_x, Orig_pos_y);
477 gr_set_color(0,100,0);
478 for (int i=0;i<num_pts;i++)
479 if (Selected[i]) gr_circle( x[i], y[i], 5);
481 } else if ((Vert_mode==0)&&(Current_point>-1)) {
482 gr_set_color(0,100,0);
483 gr_circle( x[Current_point], y[Current_point], 5);
484 } else if (Vert_mode == 1) {
485 for (i=0;i<Which_vert;i++) {
486 gr_set_color(0,0,100);
487 gr_circle( x[tri[num_tris][i]], y[tri[num_tris][i]], 6);
489 gr_set_color(200,200,0);
490 if (Current_face>-1) {
491 gr_line(x[tri[Current_face][0]], y[tri[Current_face][0]],
492 x[tri[Current_face][1]], y[tri[Current_face][1]]);
493 gr_line(x[tri[Current_face][1]], y[tri[Current_face][1]],
494 x[tri[Current_face][2]], y[tri[Current_face][2]]);
495 gr_line(x[tri[Current_face][2]], y[tri[Current_face][2]],
496 x[tri[Current_face][0]], y[tri[Current_face][0]]);
502 void draw_tri_3d( int i, int j, int k )
511 vertex * verts[3] = { &va, &vb, &vc };
513 for (int v=0; v<3; v++ ) {
516 project_2d_onto_sphere( &tmp, 1.0f - i2fl(x[index[v]])/640.0f, i2fl(y[index[v]])/480.0f );
518 vm_vec_scale( &tmp, 10.0f );
520 g3_rotate_faraway_vertex( verts[v], &tmp );
521 //g3_rotate_vertex( verts[v], &tmp );
522 g3_project_vertex( verts[v] );
524 verts[v]->b = (ubyte)(i2fl(l[index[v]]*255)/31.0f);
528 //gr_set_color_fast( &nebula_color );
529 //gr_set_color( 0, 0, 0 );
530 g3_draw_poly(3, verts, TMAP_FLAG_RAMP | TMAP_FLAG_GOURAUD | TMAP_FLAG_NEBULA );
533 void nebula_draw_3d()
536 for (i=0; i<num_tris; i++ ) {
537 draw_tri_3d( tri[i][0], tri[i][1], tri[i][2] );
545 gr_set_color(0,0,0); // set color to black
546 gr_rect(0,0,SCREEN_W,SCREEN_H); // clear screen
549 light_add_directional( &Global_light_world, 0.1f, 1.0f, 1.0f, 1.0f );
553 g3_set_view_matrix(&ViewerPos, &ViewerOrient,ViewerZoom);
555 if ( View_mode == 0 ) {
559 gr_set_color_fast( &color_green );
560 gr_printf(10,10,"Nebula Editor. Mode :");
562 gr_printf(180, 10, "Multiple Vertex Selection Editing");
563 } else if (Vert_mode ==0 ) {
564 gr_printf(180,10,"Vertex Editing");
565 if(Current_point >= 0){
566 gr_printf(180, 20, "Current vertex intensity : %d\n", l[Current_point]);
568 } else if (Vert_mode ==1) {
569 gr_printf(180,10,"Face Editing");
572 gr_printf(20,30,"# Points:");
573 gr_printf(100,30, SDL_itoa(num_pts, blah, 10));
574 gr_printf(220,30,"# Polys:");
575 gr_printf(300,30, SDL_itoa(num_tris, blah, 10));
578 model_render( test_model, &ModelOrient, &ModelPos );
586 int get_closest(int mx, int my)
588 int i, closest = -1, cval = 100000;
590 for (i=0; i<num_pts; i++ ) {
597 dist = fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
608 int get_closest_face(int mx, int my)
610 int i, closest = -1, cval = 100000;
612 for (i=0; i<num_tris; i++ ) {
616 dx = x[tri[i][0]] - mx;
617 dy = y[tri[i][0]] - my;
619 dx += x[tri[i][1]] - mx;
620 dy += y[tri[i][1]] - my;
622 dx += x[tri[i][2]] - mx;
623 dy += y[tri[i][2]] - my;
625 dist = fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
627 dist += fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
629 dx = x[tri[i][2]] - mx;
630 dy = y[tri[i][2]] - my;
631 dist += fl2i(fl_sqrt( i2fl((dx*dx)+(dy*dy)) ));
643 void delete_face(int i)
645 for (int j=i;j<num_tris;j++) {
646 memcpy(tri[j], tri[j+1], sizeof(int)*3);
651 void delete_vert(int i)
655 for (j=0;j<num_tris;j++) {
656 if ((tri[j][0]==i)||(tri[j][1]==i)||(tri[j][2]==i)) {
661 for (j=0;j<num_tris;j++) {
662 if (tri[j][0]>i) tri[j][0]--;
663 if (tri[j][1]>i) tri[j][1]--;
664 if (tri[j][2]>i) tri[j][2]--;
666 for (j=i;j<num_pts;j++) {
674 int add_vert(int mx, int my)
676 SDL_assert(num_pts<300);
684 void select_by_box(int x1, int y1, int x2, int y2)
696 for (int i=0;i<num_pts;i++) {
697 if ((x[i]<=x2) && (x[i]>=x1) &&
698 (y[i]<=y2) && (y[i]>=y1)) {
704 void sphericalize_nebula()
707 int px = SCREEN_W / (neb_w - 1);
708 int py = SCREEN_H / (neb_h - 1);
710 // flatten out the nebula so that it covers the entire sphere evenly
711 for(idx1=0; idx1<neb_w; idx1++){
712 for(idx2=0; idx2<neb_h; idx2++){
713 x[idx1+idx2*neb_w] = px * idx1;
714 y[idx1+idx2*neb_w] = py * idx2;
719 void controls_read_all(control_info * ci, float sim_time )
724 float temp = ci->heading;
725 float temp1 = ci->pitch;
726 memset( ci, 0, sizeof(control_info) );
732 kh = (key_down_timef(SDLK_KP_6) - key_down_timef(SDLK_KP_4))/8.0f;
735 else if (kh > 0.0f) {
736 if (ci->heading < 0.0f)
739 if (ci->heading > 0.0f)
743 kh = (key_down_timef(SDLK_KP_8) - key_down_timef(SDLK_KP_2))/8.0f;
746 else if (kh > 0.0f) {
747 if (ci->pitch < 0.0f)
750 if (ci->pitch > 0.0f)
754 ci->bank = (key_down_timef(SDLK_KP_7) - key_down_timef(SDLK_KP_9))*.75f;
755 ci->forward = key_down_timef(SDLK_a) - key_down_timef(SDLK_z);
756 ci->sideways = key_down_timef(SDLK_KP_3) - key_down_timef(SDLK_KP_1);
757 ci->vertical = key_down_timef(SDLK_KP_PLUS) - key_down_timef(SDLK_KP_ENTER);
764 while( (k = key_inkey()) != 0 ) {
765 //mprintf(( "Key = %x\n", k ));
766 if ( k == SDLK_ESCAPE ) {
773 Vert_mode = !Vert_mode;
779 if (Vert_mode==1) delete_face(Current_face);
780 else if (Vert_mode==0) {
781 delete_vert(Current_point);
786 scale_factor -= 0.05f;
787 mprintf(( "Scale = %.1f\n", scale_factor ));
792 scale_factor += 0.05f;
793 mprintf(( "Scale = %.1f\n", scale_factor ));
797 Sel_mode = !Sel_mode;
801 View_mode = !View_mode;
807 for (i=0;i<num_pts;i++) if (Selected[i]) {
812 } else if (Vert_mode==0) {
813 if ( Current_point > -1 ) {
814 if ( l[Current_point] > 0 ) {
818 } else if (Vert_mode ==1) {
819 if ( l[tri[Current_face][0]] > 0 ) {
820 l[tri[Current_face][0]]--;
822 if ( l[tri[Current_face][1]] > 0 ) {
823 l[tri[Current_face][1]]--;
825 if ( l[tri[Current_face][2]] > 0 ) {
826 l[tri[Current_face][2]]--;
834 for (i=0;i<num_pts;i++) if (Selected[i]) {
839 } else if (Vert_mode==0) {
840 if ( Current_point > -1 ) {
841 if ( l[Current_point] < 31 ) {
845 } else if (Vert_mode ==1) {
846 if ( l[tri[Current_face][0]] <31 ) {
847 l[tri[Current_face][0]]++;
849 if ( l[tri[Current_face][1]] <31) {
850 l[tri[Current_face][1]]++;
852 if ( l[tri[Current_face][2]] <31 ) {
853 l[tri[Current_face][2]]++;
867 sphericalize_nebula();
883 int main(int argc, char *argv[])
888 float speed = 20.0f; // how fast viewer moves
890 // setup the fred exe directory so CFILE can init properly
892 char *c = GetCommandLine();
893 SDL_assert(c != NULL);
894 char *tok = strtok(c, " ");
895 SDL_assert(tok != NULL);
898 Cmdline_window = 1; // always windowed
903 os_init( "NebEdit", "NebEdit" ); //SCREEN_W, SCREEN_H );
904 os_set_title("NebEdit");
905 gr_init(GR_640, GR_OPENGL, 16);
906 palette_load_table( "gamepalette1-01.pcx" );
910 Font1 = gr_init_font( "font01.vf" );
911 gr_init_alphacolor( &color_green, 0,255,0,255,AC_TYPE_HUD );
913 test_model = model_load( "fighter01.pof", 0, NULL );
915 physics_init( &ViewerPhysics );
916 ViewerPhysics.flags |= PF_ACCELERATES | PF_SLIDE_ENABLED;
918 ViewerPhysics.max_vel.xyz.x = 2.0f*speed; //sideways
919 ViewerPhysics.max_vel.xyz.y = 2.0f*speed; //up/down
920 ViewerPhysics.max_vel.xyz.z = 2.0f*speed; //forward
921 ViewerPhysics.max_rear_vel = 2.0f*speed; //backward -- controlled seperately
923 memset( &ci, 0, sizeof(control_info) );
925 ModelOrient = vmd_identity_matrix;
926 ModelPos.xyz.x=0.0f; ModelPos.xyz.y = 0.0f; ModelPos.xyz.z = 0.0f;
928 ViewerOrient = vmd_identity_matrix;
929 ViewerPos.xyz.x=0.0f; ViewerPos.xyz.y = 0.0f; ViewerPos.xyz.z = -50.0f;
931 flFrametime = 0.033f;
933 t1 = timer_get_fixed_seconds();
937 int some_selected = 0;
942 some_selected = FALSE;
944 for (i=0;i<num_pts;i++) {
946 some_selected = TRUE;
952 mouse_get_pos( &Mouse_x, &Mouse_y );
954 if (Current_face==-1) {
955 Current_face = get_closest_face(Mouse_x, Mouse_y);
963 // Special mouse handlers for multiple selmode
964 if (mouse_down_count(LOWEST_MOUSE_BUTTON)) {
965 Orig_pos_x = Mouse_x;
966 Orig_pos_y = Mouse_y;
968 if (mouse_down(LOWEST_MOUSE_BUTTON)) {
969 for (i=0;i<num_pts;i++) {
971 x[i]+=Mouse_x - Orig_pos_x;
972 y[i]+=Mouse_y - Orig_pos_y;
975 Orig_pos_x = Mouse_x;
976 Orig_pos_y = Mouse_y;
978 if (mouse_down_count(MOUSE_RIGHT_BUTTON)) {
979 Orig_pos_x = Mouse_x;
980 Orig_pos_y = Mouse_y;
981 for (i=0;i<num_pts;i++) {
985 if (mouse_down(MOUSE_RIGHT_BUTTON)) {
990 if (mouse_up_count(MOUSE_RIGHT_BUTTON)) {
991 Draw_sel_box = FALSE;
994 select_by_box(Orig_pos_x, Orig_pos_y, End_pos_x, End_pos_y);
999 if ( mouse_down(LOWEST_MOUSE_BUTTON) ) {
1002 x[Current_point] = Mouse_x;
1003 y[Current_point] = Mouse_y;
1004 } else if (Vert_mode==1) {
1005 x[tri[Current_face][0]] += Mouse_x - Orig_pos_x;
1006 y[tri[Current_face][0]] += Mouse_y - Orig_pos_y;
1007 x[tri[Current_face][1]] += Mouse_x - Orig_pos_x;
1008 y[tri[Current_face][1]] += Mouse_y - Orig_pos_y;
1009 x[tri[Current_face][2]] += Mouse_x - Orig_pos_x;
1010 y[tri[Current_face][2]] += Mouse_y - Orig_pos_y;
1011 Orig_pos_x = Mouse_x;
1012 Orig_pos_y = Mouse_y;
1015 if (Vert_mode == 1) {
1016 Current_face = get_closest_face(Mouse_x, Mouse_y);
1017 Orig_pos_x = Mouse_x;
1018 Orig_pos_y = Mouse_y;
1021 Current_point = get_closest(Mouse_x, Mouse_y);
1022 mouse_set_pos(x[Current_point], y[Current_point]);
1027 if ( mouse_up_count(LOWEST_MOUSE_BUTTON)) {
1028 //Current_point = -1;
1029 //Current_face = -1;
1033 if ( mouse_up_count(MOUSE_RIGHT_BUTTON) ) {
1035 Current_point = add_vert(Mouse_x, Mouse_y);
1036 } else if (Vert_mode==1) {
1037 if ((num_tris<MAX_TRIS-1)) {
1038 tri[num_tris][Which_vert] = get_closest(Mouse_x, Mouse_y);
1048 controls_read_all(&ci, flFrametime );
1049 physics_read_flying_controls( &ViewerOrient, &ViewerPhysics, &ci, flFrametime );
1050 physics_sim(&ViewerPos, &ViewerOrient, &ViewerPhysics, flFrametime );
1054 t2 = timer_get_fixed_seconds();
1056 flFrametime = f2fl(t2 - t1);
1069 // Stub functions and variables.
1070 // These do nothing but are needed to prevent link errors.
1071 void demo_set_playback_filter() {}
1073 void freespace_menu_background()
1079 int game_check_key()
1090 vector Dead_player_last_vel;