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 = { { { 0.0f, 0.0f, -10.0f } } };
100 m_ViewerOrient = IDENTITY_MATRIX;
101 m_ObjectOrient = IDENTITY_MATRIX;
103 physics_init( &m_ViewerPhysics );
104 m_ViewerPhysics.flags |= PF_ACCELERATES | PF_SLIDE_ENABLED;
106 memset( &m_Viewer_ci, 0, sizeof(control_info) );
112 m_timer = new PofViewTimer(this);
113 m_timer->Start(1000/30);
115 thrust_anim_inited = false;
118 model_afterburner = 0;
120 shipp_thruster_bitmap = -1;
121 shipp_thruster_frame = 0.0f;
123 shipp_thruster_glow_bitmap = -1;
124 shipp_thruster_glow_frame = 0.0f;
125 shipp_thruster_glow_noise = 1.0f;
128 PofViewCanvas::~PofViewCanvas()
134 extern float Ambient_light;
135 extern void opengl1_tcache_frame();
137 static vector Global_light_world = { { { -0.208758f, -0.688253f, 0.694782f } } };
140 void PofViewCanvas::Render()
142 PofViewFrame *parent = (PofViewFrame *)GetParent();
144 int model_num = parent->GetModelnum();
150 polymodel *pm = model_get(model_num);
154 m_ViewerPos.xyz.z = -pm->rad * 1.5f;
160 GetClientSize(&w, &h);
163 gr_set_clip(0, 0, w, h);
165 gr_set_clear_color(0, 0, 0);
167 gr_set_color(127, 127, 127);
169 float saved_Ambient_light = Ambient_light;
173 if ( parent->LightingOn() ) {
174 light_add_directional(&Global_light_world, 1.0f, 1.0f, 1.0f, 1.0f);
176 Ambient_light = 0.0f;
181 g3_set_view_matrix(&m_ViewerPos, &m_ViewerOrient, m_ViewerZoom);
183 uint render_flags = 0;
185 if ( !parent->UseLighting() ) {
186 render_flags |= MR_NO_LIGHTING;
189 if ( parent->ShowOutline() ) {
190 render_flags |= MR_SHOW_OUTLINE;
191 model_set_outline_color(0,0,0);
194 if ( parent->ShowShields() ){
195 render_flags |= MR_SHOW_SHIELDS;
198 if ( parent->ShowInvisible() ) {
199 render_flags |= MR_SHOW_INVISIBLE_FACES;
202 if ( parent->ShowOverwrite() ) {
203 Tmap_show_layers = 1;
205 Tmap_show_layers = 0;
208 if ( parent->ShowPivots() ) {
209 render_flags |= MR_SHOW_PIVOTS;
212 if ( parent->ShowPaths() ) {
213 render_flags |= MR_SHOW_PATHS;
216 if ( parent->ShowRadius() ) {
217 render_flags |= MR_SHOW_RADIUS;
220 if ( !parent->UseSmoothing() ) {
221 render_flags |= MR_NO_SMOOTHING;
224 if ( !parent->UseTexturing() ) {
225 render_flags |= MR_NO_TEXTURING;
228 if ( parent->GetDetailLevel() > 0 ) {
229 render_flags |= MR_LOCK_DETAIL;
230 model_set_detail_level(parent->GetDetailLevel()-1);
233 if ( parent->ShowBayPaths() ) {
234 render_flags |= MR_BAY_PATHS;
237 if ( parent->UseAutocenter() ) {
238 render_flags |= MR_AUTOCENTER;
241 vector temp_pos = { { { 0.0f, 0.0f, 0.0f } } };
243 model_clear_instance( model_num );
245 model_show_damaged(model_num, parent->ShowDamaged() );
247 if ( model_afterburner ){
248 model_set_thrust( model_num, 1.0f, shipp_thruster_bitmap, shipp_thruster_glow_bitmap, shipp_thruster_glow_noise );
250 model_set_thrust( model_num, model_thrust, shipp_thruster_bitmap, shipp_thruster_glow_bitmap, shipp_thruster_glow_noise );
253 if ( parent->ShowThrusters() ) {
254 render_flags |= MR_SHOW_THRUSTERS;
257 static int whee = -1;
259 whee = bm_load("helvig.pcx");
262 model_set_insignia_bitmap(whee);
265 if ( parent->GetDetailLevel() > 0 ) {
266 model_render( model_num, &m_ObjectOrient, &temp_pos, render_flags );
268 for (int i = 0; i < pm->num_debris_objects; i++) {
269 vector tmp = { { { 0.0f, 0.0f, 0.0f } } };
270 vector tmp1 = pm->submodel[pm->debris_objects[i]].offset;
271 model_find_world_point(&tmp, &tmp1, model_num, -1,&m_ObjectOrient, &temp_pos );
272 submodel_render( model_num, pm->debris_objects[i],&m_ObjectOrient, &tmp, render_flags );
280 opengl1_tcache_frame();
282 Ambient_light = saved_Ambient_light;
285 // JAS - figure out which thruster bitmap will get rendered next
286 // time around. ship_render needs to have shipp_thruster_bitmap set to
287 // a valid bitmap number, or -1 if we shouldn't render thrusters.
288 void PofViewCanvas::DoThrusterFrame(float frame_time)
292 thrust_anim *the_anim;
294 if ( !thrust_anim_inited ) {
298 if (model_afterburner) {
299 the_anim = &Thrust_anims[THRUST_ANIM_AFTERBURNER];
300 rate = 1.2f; // go at 1.2x faster when afterburners on
302 the_anim = &Thrust_anims[THRUST_ANIM_NORMAL];
303 // If thrust at 0, go at half as fast, full thrust; full framerate
304 // so set rate from 0.5 to 1.0, depending on thrust from 0 to 1
305 rate = 0.5f + model_thrust / 2.0f;
308 shipp_thruster_frame += frame_time * rate;
311 if ( shipp_thruster_frame < 0.0f ) shipp_thruster_frame = 0.0f;
312 if ( shipp_thruster_frame > 100.0f ) shipp_thruster_frame = 0.0f;
314 if ( shipp_thruster_frame > the_anim->time ) {
315 shipp_thruster_frame -= the_anim->time;
317 framenum = fl2i( (shipp_thruster_frame*the_anim->num_frames) / the_anim->time );
318 if ( framenum < 0 ) framenum = 0;
319 if ( framenum >= the_anim->num_frames ) framenum = the_anim->num_frames-1;
321 // Get the bitmap for this frame
322 shipp_thruster_bitmap = the_anim->first_frame + framenum;
324 // mprintf(( "TF: %.2f\n", shipp_thruster_frame ));
329 if (model_afterburner) {
330 the_anim = &Thrust_anims[THRUST_ANIM_GLOW_AFTERBURNER];
331 rate = 1.2f; // go at 1.2x faster when afterburners on
333 the_anim = &Thrust_anims[THRUST_ANIM_GLOW_NORMAL];
334 // If thrust at 0, go at half as fast, full thrust; full framerate
335 // so set rate from 0.5 to 1.0, depending on thrust from 0 to 1
336 rate = 0.5f + model_thrust / 2.0f;
339 shipp_thruster_glow_frame += frame_time * rate;
342 if ( shipp_thruster_glow_frame < 0.0f ) shipp_thruster_glow_frame = 0.0f;
343 if ( shipp_thruster_glow_frame > 100.0f ) shipp_thruster_glow_frame = 0.0f;
345 while (shipp_thruster_glow_frame > the_anim->time) {
346 shipp_thruster_glow_frame -= the_anim->time;
348 framenum = fl2i( (shipp_thruster_glow_frame*the_anim->num_frames) / the_anim->time );
349 if ( framenum < 0 ) framenum = 0;
350 if ( framenum >= the_anim->num_frames ) framenum = the_anim->num_frames-1;
352 // Get the bitmap for this frame
353 shipp_thruster_glow_bitmap = the_anim->first_frame;
354 shipp_thruster_glow_noise = Noise[framenum];
356 // mprintf(( "TF: %.2f\n", shipp_thruster_frame ));
360 void PofViewCanvas::MoveViewer(float frame_time)
368 if ( wxGetKeyState(wxKeyCode('1')) ) {
370 } else if ( wxGetKeyState(wxKeyCode('2')) ) {
372 } else if ( wxGetKeyState(wxKeyCode('3')) ) {
374 } else if ( wxGetKeyState(wxKeyCode('4')) ) {
376 } else if ( wxGetKeyState(wxKeyCode('5')) ) {
378 } else if ( wxGetKeyState(wxKeyCode('6')) ) {
382 if (detail_lvl >= 0) {
383 ((PofViewFrame*)GetParent())->SetDetailLevel(detail_lvl);
386 if ( wxGetKeyState(wxKeyCode('-')) ) {
387 // Scales the engines thrusters by this much
388 model_thrust -= 0.1f;
390 if (model_thrust < 0.0f) {
393 } else if ( wxGetKeyState(wxKeyCode('=')) ) {
394 // Scales the engines thrusters by this much
395 model_thrust += 0.1f;
397 if (model_thrust > 1.0f) {
402 if ( wxGetKeyState(WXK_BACK) ) {
403 model_afterburner = 1;
405 model_afterburner = 0;
408 int model_num = ((PofViewFrame*)GetParent())->GetModelnum();
414 polymodel *pm = model_get(model_num);
417 control_info *ci = &m_Viewer_ci;
420 float c_scale = pm->core_radius; //1.0f;
422 // if (pm->core_radius < 200.0f) {
423 // c_scale = 1.0f / 6.0f;
426 float temp = ci->heading;
427 float temp1 = ci->pitch;
428 memset( ci, 0, sizeof(control_info) );
432 if ( wxGetKeyState(WXK_NUMPAD6) ) {
434 } else if ( wxGetKeyState(WXK_NUMPAD4) ) {
442 } else if (kh > 0.0f) {
443 if (ci->heading < 0.0f) {
447 if (ci->heading > 0.0f) {
454 if ( wxGetKeyState(WXK_NUMPAD8) ) {
456 } else if ( wxGetKeyState(WXK_NUMPAD2) ) {
464 } else if (kh > 0.0f) {
465 if (ci->pitch < 0.0f){
469 if (ci->pitch > 0.0f){
476 if ( wxGetKeyState(WXK_NUMPAD7) ) {
477 ci->bank = frame_time / 8.0f;
478 } else if ( wxGetKeyState(WXK_NUMPAD9) ) {
479 ci->bank = -frame_time / 8.0f;
482 if ( wxGetKeyState(wxKeyCode('A')) ) {
483 ci->forward = frame_time * c_scale;
484 } else if ( wxGetKeyState(wxKeyCode('Z')) ) {
485 ci->forward = -frame_time * c_scale;
488 if ( wxGetKeyState(WXK_NUMPAD3) ) {
489 ci->sideways = frame_time * c_scale;
490 } else if ( wxGetKeyState(WXK_NUMPAD1) ) {
491 ci->sideways = -frame_time * c_scale;
494 if ( wxGetKeyState(WXK_NUMPAD_SUBTRACT) ) {
495 ci->vertical = frame_time * c_scale;
496 } else if ( wxGetKeyState(WXK_NUMPAD_ADD) ) {
497 ci->vertical = -frame_time * c_scale;
500 physics_read_flying_controls( &m_ViewerOrient, &m_ViewerPhysics, &m_Viewer_ci, frame_time );
502 physics_sim(&m_ViewerPos, &m_ViewerOrient, &m_ViewerPhysics, frame_time * 6.0f );
505 void PofViewCanvas::OnPaint( wxPaintEvent& WXUNUSED(event) )
512 void PofViewCanvas::OnSize(wxSizeEvent& WXUNUSED(event))
514 if ( !this->IsShownOnScreen() ) {
518 int x = 640, y = 480;
520 this->GetClientSize(&x, &y);
522 gr_set_viewport(x, y);
525 void PofViewCanvas::OnEraseBackground(wxEraseEvent& WXUNUSED(event))
527 // Do nothing, to avoid flashing on MSW
530 void PofViewCanvas::OnMouse(wxMouseEvent& event)
532 if ( event.Dragging() ) {
533 if (m_mouse_inited) {
534 m_mouse_dx = event.GetX() - m_mouse_x;
535 m_mouse_dy = event.GetY() - m_mouse_y;
540 m_mouse_x = event.GetX();
541 m_mouse_y = event.GetY();
543 matrix tempm, mousem;
545 if ( m_mouse_dx || m_mouse_dy ) {
546 vm_trackball( -m_mouse_dx, m_mouse_dy, &mousem );
547 vm_matrix_x_matrix(&tempm, &m_ObjectOrient, &mousem);
548 m_ObjectOrient = tempm;
550 m_mouse_dx = m_mouse_dy = 0;
557 // loads the animations for ship's afterburners
558 void PofViewCanvas::InitThrusters()
563 if (thrust_anim_inited)
566 for ( i = 0; i < NUM_THRUST_ANIMS; i++ ) {
567 ta = &Thrust_anims[i];
570 if (i < THRUST_ANIM_GLOW_NORMAL) {
571 ta->first_frame = bm_load_animation(Thrust_anim_names[i], &ta->num_frames, &fps, 1);
572 if ( ta->first_frame == -1 ) {
573 Error(LOCATION,"Error loading animation file: %s\n",Thrust_anim_names[i]);
576 SDL_assert(fps != 0);
577 ta->time = i2fl(ta->num_frames)/fps;
581 ta->num_frames = NOISE_NUM_FRAMES;
583 ta->first_frame = bm_load( Thrust_anim_names[i] );
584 if ( ta->first_frame == -1 ) {
585 Error(LOCATION,"Error loading bitmap file: %s\n",Thrust_anim_names[i]);
588 SDL_assert(fps != 0);
589 ta->time = i2fl(ta->num_frames)/fps;
593 thrust_anim_inited = true;