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
15 #include "systemvars.h"
25 float flFrametime; // used by game lib; DO NOT REMOVE!!
27 extern bool in_dialog;
30 // Stuff for showing ship thrusters.
31 typedef struct thrust_anim {
34 float time; // in seconds
37 #define NUM_THRUST_ANIMS 4
39 #define THRUST_ANIM_NORMAL 0
40 #define THRUST_ANIM_AFTERBURNER 1
41 #define THRUST_ANIM_GLOW_NORMAL 2
42 #define THRUST_ANIM_GLOW_AFTERBURNER 3
44 static thrust_anim Thrust_anims[NUM_THRUST_ANIMS];
46 static char Thrust_anim_names[NUM_THRUST_ANIMS][MAX_FILENAME_LEN] = {
54 ///////////////////////////////////////////////////////////////////////////////
56 PofViewTimer::PofViewTimer(PofViewCanvas *canvas)
63 PofViewTimer::~PofViewTimer()
67 void PofViewTimer::Notify()
71 if (m_thrust_timer == -1) {
72 m_thrust_timer = timer_get_milliseconds();
75 int tmp_time = timer_get_milliseconds();
77 frame_time = ((float)(tmp_time-m_thrust_timer)) / 1000.0f;
78 flFrametime = frame_time;
80 m_thrust_timer = tmp_time;
82 m_canvas->DoThrusterFrame(frame_time);
83 m_canvas->MoveViewer(frame_time);
87 wxBEGIN_EVENT_TABLE(PofViewCanvas, wxGLCanvas)
88 EVT_SIZE(PofViewCanvas::OnSize)
89 EVT_PAINT(PofViewCanvas::OnPaint)
90 EVT_ERASE_BACKGROUND(PofViewCanvas::OnEraseBackground)
91 EVT_MOUSE_EVENTS(PofViewCanvas::OnMouse)
94 PofViewCanvas::PofViewCanvas(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name)
95 : wxGLCanvas(parent, id, NULL, pos, size, style | wxFULL_REPAINT_ON_RESIZE, name)
99 m_ViewerPos = vmd_zero_vector;
100 m_ViewerPos.xyz.z = -10.0f;
101 m_ViewerOrient = vmd_identity_matrix;
102 m_ObjectOrient = vmd_identity_matrix;
104 physics_init( &m_ViewerPhysics );
105 m_ViewerPhysics.flags |= PF_ACCELERATES | PF_SLIDE_ENABLED;
107 memset( &m_Viewer_ci, 0, sizeof(control_info) );
113 m_timer = new PofViewTimer(this);
114 m_timer->Start(1000/30);
116 thrust_anim_inited = false;
119 model_afterburner = 0;
121 shipp_thruster_bitmap = -1;
122 shipp_thruster_frame = 0.0f;
124 shipp_thruster_glow_bitmap = -1;
125 shipp_thruster_glow_frame = 0.0f;
126 shipp_thruster_glow_noise = 1.0f;
129 PofViewCanvas::~PofViewCanvas()
135 extern float Ambient_light;
136 extern void opengl1_tcache_frame();
138 static vector Global_light_world = { { { -0.208758f, -0.688253f, 0.694782f } } };
141 void PofViewCanvas::Render()
143 PofViewFrame *parent = (PofViewFrame *)GetParent();
145 int model_num = parent->GetModelnum();
151 polymodel *pm = model_get(model_num);
155 m_ViewerPos.xyz.z = -pm->rad * 1.5f;
161 GetClientSize(&w, &h);
164 gr_set_clip(0, 0, w, h);
166 gr_set_clear_color(0, 0, 0);
168 gr_set_color(127, 127, 127);
170 float saved_Ambient_light = Ambient_light;
174 if ( parent->LightingOn() ) {
175 light_add_directional(&Global_light_world, 1.0f, 1.0f, 1.0f, 1.0f);
177 Ambient_light = 0.0f;
182 g3_set_view_matrix(&m_ViewerPos, &m_ViewerOrient, m_ViewerZoom);
184 uint render_flags = 0;
186 if ( !parent->UseLighting() ) {
187 render_flags |= MR_NO_LIGHTING;
190 if ( parent->ShowOutline() ) {
191 render_flags |= MR_SHOW_OUTLINE;
192 model_set_outline_color(0,0,0);
195 if ( parent->ShowShields() ){
196 render_flags |= MR_SHOW_SHIELDS;
199 if ( parent->ShowInvisible() ) {
200 render_flags |= MR_SHOW_INVISIBLE_FACES;
203 if ( parent->ShowOverwrite() ) {
204 Tmap_show_layers = 1;
206 Tmap_show_layers = 0;
209 if ( parent->ShowPivots() ) {
210 render_flags |= MR_SHOW_PIVOTS;
213 if ( parent->ShowPaths() ) {
214 render_flags |= MR_SHOW_PATHS;
217 if ( parent->ShowRadius() ) {
218 render_flags |= MR_SHOW_RADIUS;
221 if ( !parent->UseSmoothing() ) {
222 render_flags |= MR_NO_SMOOTHING;
225 if ( !parent->UseTexturing() ) {
226 render_flags |= MR_NO_TEXTURING;
229 if ( parent->GetDetailLevel() > 0 ) {
230 render_flags |= MR_LOCK_DETAIL;
231 model_set_detail_level(parent->GetDetailLevel()-1);
234 if ( parent->ShowBayPaths() ) {
235 render_flags |= MR_BAY_PATHS;
238 if ( parent->UseAutocenter() ) {
239 render_flags |= MR_AUTOCENTER;
242 vector temp_pos = { { { 0.0f, 0.0f, 0.0f } } };
244 model_clear_instance( model_num );
246 model_show_damaged(model_num, parent->ShowDamaged() );
248 if ( model_afterburner ){
249 model_set_thrust( model_num, 1.0f, shipp_thruster_bitmap, shipp_thruster_glow_bitmap, shipp_thruster_glow_noise );
251 model_set_thrust( model_num, model_thrust, shipp_thruster_bitmap, shipp_thruster_glow_bitmap, shipp_thruster_glow_noise );
254 if ( parent->ShowThrusters() ) {
255 render_flags |= MR_SHOW_THRUSTERS;
258 static int whee = -1;
260 whee = bm_load("helvig.pcx");
263 model_set_insignia_bitmap(whee);
266 if ( parent->GetDetailLevel() > 0 ) {
267 model_render( model_num, &m_ObjectOrient, &temp_pos, render_flags );
269 for (int i = 0; i < pm->num_debris_objects; i++) {
270 vector tmp = { { { 0.0f, 0.0f, 0.0f } } };
271 vector tmp1 = pm->submodel[pm->debris_objects[i]].offset;
272 model_find_world_point(&tmp, &tmp1, model_num, -1,&m_ObjectOrient, &temp_pos );
273 submodel_render( model_num, pm->debris_objects[i],&m_ObjectOrient, &tmp, render_flags );
281 opengl1_tcache_frame();
283 Ambient_light = saved_Ambient_light;
286 // JAS - figure out which thruster bitmap will get rendered next
287 // time around. ship_render needs to have shipp_thruster_bitmap set to
288 // a valid bitmap number, or -1 if we shouldn't render thrusters.
289 void PofViewCanvas::DoThrusterFrame(float frame_time)
293 thrust_anim *the_anim;
295 if ( !thrust_anim_inited ) {
299 if (model_afterburner) {
300 the_anim = &Thrust_anims[THRUST_ANIM_AFTERBURNER];
301 rate = 1.2f; // go at 1.2x faster when afterburners on
303 the_anim = &Thrust_anims[THRUST_ANIM_NORMAL];
304 // If thrust at 0, go at half as fast, full thrust; full framerate
305 // so set rate from 0.5 to 1.0, depending on thrust from 0 to 1
306 rate = 0.5f + model_thrust / 2.0f;
309 shipp_thruster_frame += frame_time * rate;
312 if ( shipp_thruster_frame < 0.0f ) shipp_thruster_frame = 0.0f;
313 if ( shipp_thruster_frame > 100.0f ) shipp_thruster_frame = 0.0f;
315 if ( shipp_thruster_frame > the_anim->time ) {
316 shipp_thruster_frame -= the_anim->time;
318 framenum = fl2i( (shipp_thruster_frame*the_anim->num_frames) / the_anim->time );
319 if ( framenum < 0 ) framenum = 0;
320 if ( framenum >= the_anim->num_frames ) framenum = the_anim->num_frames-1;
322 // Get the bitmap for this frame
323 shipp_thruster_bitmap = the_anim->first_frame + framenum;
325 // mprintf(( "TF: %.2f\n", shipp_thruster_frame ));
330 if (model_afterburner) {
331 the_anim = &Thrust_anims[THRUST_ANIM_GLOW_AFTERBURNER];
332 rate = 1.2f; // go at 1.2x faster when afterburners on
334 the_anim = &Thrust_anims[THRUST_ANIM_GLOW_NORMAL];
335 // If thrust at 0, go at half as fast, full thrust; full framerate
336 // so set rate from 0.5 to 1.0, depending on thrust from 0 to 1
337 rate = 0.5f + model_thrust / 2.0f;
340 shipp_thruster_glow_frame += frame_time * rate;
343 if ( shipp_thruster_glow_frame < 0.0f ) shipp_thruster_glow_frame = 0.0f;
344 if ( shipp_thruster_glow_frame > 100.0f ) shipp_thruster_glow_frame = 0.0f;
346 while (shipp_thruster_glow_frame > the_anim->time) {
347 shipp_thruster_glow_frame -= the_anim->time;
349 framenum = fl2i( (shipp_thruster_glow_frame*the_anim->num_frames) / the_anim->time );
350 if ( framenum < 0 ) framenum = 0;
351 if ( framenum >= the_anim->num_frames ) framenum = the_anim->num_frames-1;
353 // Get the bitmap for this frame
354 shipp_thruster_glow_bitmap = the_anim->first_frame;
355 shipp_thruster_glow_noise = Noise[framenum];
357 // mprintf(( "TF: %.2f\n", shipp_thruster_frame ));
361 void PofViewCanvas::MoveViewer(float frame_time)
369 if ( wxGetKeyState(wxKeyCode('1')) ) {
371 } else if ( wxGetKeyState(wxKeyCode('2')) ) {
373 } else if ( wxGetKeyState(wxKeyCode('3')) ) {
375 } else if ( wxGetKeyState(wxKeyCode('4')) ) {
377 } else if ( wxGetKeyState(wxKeyCode('5')) ) {
379 } else if ( wxGetKeyState(wxKeyCode('6')) ) {
383 if (detail_lvl >= 0) {
384 ((PofViewFrame*)GetParent())->SetDetailLevel(detail_lvl);
387 if ( wxGetKeyState(wxKeyCode('-')) ) {
388 // Scales the engines thrusters by this much
389 model_thrust -= 0.1f;
391 if (model_thrust < 0.0f) {
394 } else if ( wxGetKeyState(wxKeyCode('=')) ) {
395 // Scales the engines thrusters by this much
396 model_thrust += 0.1f;
398 if (model_thrust > 1.0f) {
403 if ( wxGetKeyState(WXK_BACK) ) {
404 model_afterburner = 1;
406 model_afterburner = 0;
409 int model_num = ((PofViewFrame*)GetParent())->GetModelnum();
415 polymodel *pm = model_get(model_num);
421 control_info *ci = &m_Viewer_ci;
424 float c_scale = pm->core_radius; //1.0f;
426 // if (pm->core_radius < 200.0f) {
427 // c_scale = 1.0f / 6.0f;
430 float temp = ci->heading;
431 float temp1 = ci->pitch;
432 memset( ci, 0, sizeof(control_info) );
436 if ( wxGetKeyState(WXK_NUMPAD6) ) {
438 } else if ( wxGetKeyState(WXK_NUMPAD4) ) {
446 } else if (kh > 0.0f) {
447 if (ci->heading < 0.0f) {
451 if (ci->heading > 0.0f) {
458 if ( wxGetKeyState(WXK_NUMPAD8) ) {
460 } else if ( wxGetKeyState(WXK_NUMPAD2) ) {
468 } else if (kh > 0.0f) {
469 if (ci->pitch < 0.0f){
473 if (ci->pitch > 0.0f){
480 if ( wxGetKeyState(WXK_NUMPAD7) ) {
481 ci->bank = frame_time / 8.0f;
482 } else if ( wxGetKeyState(WXK_NUMPAD9) ) {
483 ci->bank = -frame_time / 8.0f;
486 if ( wxGetKeyState(wxKeyCode('A')) ) {
487 ci->forward = frame_time * c_scale;
488 } else if ( wxGetKeyState(wxKeyCode('Z')) ) {
489 ci->forward = -frame_time * c_scale;
492 if ( wxGetKeyState(WXK_NUMPAD3) ) {
493 ci->sideways = frame_time * c_scale;
494 } else if ( wxGetKeyState(WXK_NUMPAD1) ) {
495 ci->sideways = -frame_time * c_scale;
498 if ( wxGetKeyState(WXK_NUMPAD_SUBTRACT) ) {
499 ci->vertical = frame_time * c_scale;
500 } else if ( wxGetKeyState(WXK_NUMPAD_ADD) ) {
501 ci->vertical = -frame_time * c_scale;
504 physics_read_flying_controls( &m_ViewerOrient, &m_ViewerPhysics, &m_Viewer_ci, frame_time );
506 physics_sim(&m_ViewerPos, &m_ViewerOrient, &m_ViewerPhysics, frame_time * 6.0f );
509 void PofViewCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
516 void PofViewCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
518 if ( !this->IsShownOnScreen() ) {
522 int x = 640, y = 480;
524 this->GetClientSize(&x, &y);
526 gr_set_viewport(x, y);
529 void PofViewCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
531 // Do nothing, to avoid flashing on MSW
534 void PofViewCanvas::OnMouse(wxMouseEvent& event)
536 if ( event.Dragging() ) {
537 if (m_mouse_inited) {
538 m_mouse_dx = event.GetX() - m_mouse_x;
539 m_mouse_dy = event.GetY() - m_mouse_y;
544 m_mouse_x = event.GetX();
545 m_mouse_y = event.GetY();
547 matrix tempm, mousem;
549 if ( m_mouse_dx || m_mouse_dy ) {
550 vm_trackball( -m_mouse_dx, m_mouse_dy, &mousem );
551 vm_matrix_x_matrix(&tempm, &m_ObjectOrient, &mousem);
552 m_ObjectOrient = tempm;
554 m_mouse_dx = m_mouse_dy = 0;
561 // loads the animations for ship's afterburners
562 void PofViewCanvas::InitThrusters()
567 if (thrust_anim_inited)
570 for ( i = 0; i < NUM_THRUST_ANIMS; i++ ) {
571 ta = &Thrust_anims[i];
574 if (i < THRUST_ANIM_GLOW_NORMAL) {
575 ta->first_frame = bm_load_animation(Thrust_anim_names[i], &ta->num_frames, &fps, 1);
576 if ( ta->first_frame == -1 ) {
577 Error(LOCATION,"Error loading animation file: %s\n",Thrust_anim_names[i]);
580 SDL_assert(fps != 0);
581 ta->time = i2fl(ta->num_frames)/fps;
585 ta->num_frames = NOISE_NUM_FRAMES;
587 ta->first_frame = bm_load( Thrust_anim_names[i] );
588 if ( ta->first_frame == -1 ) {
589 Error(LOCATION,"Error loading bitmap file: %s\n",Thrust_anim_names[i]);
592 SDL_assert(fps != 0);
593 ta->time = i2fl(ta->num_frames)/fps;
597 thrust_anim_inited = true;