static void handle_tick(game_context_s *context, void *data, const nothing_s *n) { input_handler_s *input_handler = data; // process the callback-based events target_context = context; glfwPollEvents(); target_context = NULL; // process joysticks for(int i = 0; i < MAX_JOYSTICKS; i++) { if(glfwGetJoystickParam(i, GLFW_PRESENT) == GL_TRUE) { joystick_event_s *joystick = &input_handler->joysticks[i]; int axis_count = glfwGetJoystickParam(i, GLFW_AXES); array_set_length(joystick->axes, axis_count); glfwGetJoystickPos(i, array_get_ptr(joystick->axes), axis_count); int button_count = glfwGetJoystickParam(i, GLFW_BUTTONS); array_set_length(joystick->buttons, button_count); glfwGetJoystickButtons(i, array_get_ptr(joystick->buttons), button_count); broadcast_input_handler_joystick_event(context, *joystick); } } }
/** Updated joystick info */ static void orxFASTCALL orxJoystick_GLFW_UpdateInfo(orxU32 _u32ID) { /* Checks */ orxASSERT(_u32ID <= GLFW_JOYSTICK_LAST); /* Needs update? */ if(sstJoystick.astJoyInfoList[_u32ID].fTimeStamp != sstJoystick.pstClockInfo->fTime) { /* Is connected? */ if(glfwGetJoystickParam((int)_u32ID, GLFW_PRESENT) != GL_FALSE) { /* Gets axes values */ glfwGetJoystickPos((int)_u32ID, sstJoystick.astJoyInfoList[_u32ID].afAxisInfoList, orxJOYSTICK_AXIS_SINGLE_NUMBER); /* Updates connection status */ sstJoystick.astJoyInfoList[_u32ID].bIsConnected = orxTRUE; /* Gets button values */ glfwGetJoystickButtons((int)_u32ID, sstJoystick.astJoyInfoList[_u32ID].au8ButtonInfoList, orxJOYSTICK_BUTTON_SINGLE_NUMBER); } else { /* Clears info */ orxMemory_Zero(&sstJoystick.astJoyInfoList[_u32ID], sizeof(orxJOYSTICK_INFO)); } /* Updates time stamp */ sstJoystick.astJoyInfoList[_u32ID].fTimeStamp = sstJoystick.pstClockInfo->fTime; } /* Done! */ return; }
//Clumbsily abstracts glfw's ability to grab joysticks, I can only test it with an xbox controller so this won't have good support unless some other programmer really wants it. void NInput::GetJoyStick(unsigned int ID, float* Floats, unsigned int NumAxes) { switch (ID) { case 1: { glfwGetJoystickPos(GLFW_JOYSTICK_1,Floats,NumAxes); break; } case 2: { glfwGetJoystickPos(GLFW_JOYSTICK_2,Floats,NumAxes); break; } default: { glfwGetJoystickPos(GLFW_JOYSTICK_1,Floats,NumAxes); } } }
//SGenum SG_EXPORT sgmCoreJoystickAxisSetPosition(void* joystick, float* position); SGenum SG_EXPORT sgmCoreJoystickAxisGetPosition(void* joystick, float* position) { if(joystick == NULL) return SG_OK; // SG_INVALID_VALUE Joystick* cjoystick = (Joystick*)joystick; glfwGetJoystickPos(cjoystick->id, cjoystick->axis, cjoystick->numaxis); position = memcpy(position, cjoystick->axis, cjoystick->numaxis * sizeof(float)); return SG_OK; }
/*======================================================================== * Retrieve joystick states *========================================================================*/ static void updateJoysticksState(void) { int joy; for (joy = GLFW_JOYSTICK_1; joy < GLFW_JOYSTICK_LAST + 1; joy++) { printf("Updating information for joystick %d\n", joy); states[joy].present = glfwGetJoystickParam(joy, GLFW_PRESENT); if (states[joy].present == GL_TRUE) { states[joy].num_axes = glfwGetJoystickPos(joy, states[joy].axes, MAX_AXES); states[joy].num_buttons = glfwGetJoystickButtons(joy, states[joy].buttons, MAX_BUTTONS); } } }
void CApplication::ProcessJoystickInput() { if (g_aJoysticks.size() != MAX_JOYSTICKS) return; for (size_t i = 0; i < MAX_JOYSTICKS; i++) { CJoystick& oJoystick = g_aJoysticks[i]; if (!oJoystick.m_bPresent) continue; static tvector<float> aflAxis; aflAxis.resize(oJoystick.m_aflAxis.size()); glfwGetJoystickPos(i, &aflAxis[0], oJoystick.m_aflAxis.size()); for (size_t j = 0; j < oJoystick.m_aflAxis.size(); j++) { if (aflAxis[j] != oJoystick.m_aflAxis[j]) JoystickAxis(i, j, aflAxis[j], aflAxis[j]-oJoystick.m_aflAxis[j]); } oJoystick.m_aflAxis = aflAxis; static tvector<unsigned char> aiButtons; aiButtons.resize(oJoystick.m_iButtons); glfwGetJoystickButtons(i, &aiButtons[0], oJoystick.m_iButtons); for (size_t j = 0; j < oJoystick.m_iButtons; j++) { unsigned long long iButtonMask = (1<<j); if (aiButtons[j] == GLFW_PRESS && !(oJoystick.m_aiButtonStates&iButtonMask)) JoystickButtonPress(i, MapJoystickKey(j)); else if (aiButtons[j] == GLFW_RELEASE && (oJoystick.m_aiButtonStates&iButtonMask)) JoystickButtonRelease(i, MapJoystickKey(j)); if (aiButtons[j] == GLFW_PRESS) oJoystick.m_aiButtonStates |= iButtonMask; else oJoystick.m_aiButtonStates &= ~iButtonMask; } } }
int Canvas::_flush(lua_State *l) { if (!lua_istable(l, 1)) return luaL_error(l, "canvas expected as first argument"); // clear key events keys_down.clear(); keys_up.clear(); glfwSwapBuffers(); glfwSleep(0.005); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // if (!_canvas->view.is2d) glLoadIdentity(); // set the game time double time = glfwGetTime(); lua_getfield(l, 1, "time"); double old = luaL_checknumber(l, -1); lua_pop(l, 1); setnumber("time" , time); setnumber("dt" , time - old); int x, y; double cx, cy; // canvas mouse coordinates glfwGetMousePos(&x, &y); Viewport &view = _canvas->view; if (view.is2d) { double vwidth = view.right - view.left; double vheight = view.bottom - view.top; cx = view.left + (x * vwidth / _canvas->width()); cy = view.top + (y * vheight / _canvas->height()); } else { cx = (double)x; cy = (double)y; } // update the mouse point lua_getfield(l, 1, "mouse"); setnumber("x", cx); setnumber("y", cy); setbool("left", glfwGetMouseButton(GLFW_MOUSE_BUTTON_LEFT)); setbool("right", glfwGetMouseButton(GLFW_MOUSE_BUTTON_RIGHT)); lua_getfield(l, 1, "input"); float axis[2]; glfwGetJoystickPos(GLFW_JOYSTICK_1, axis, 2); setnumber("xaxis", axis[0]); setnumber("yaxis", axis[1]); setbool("left", glfwGetKey(GLFW_KEY_LEFT)); setbool("right", glfwGetKey(GLFW_KEY_RIGHT)); setbool("up", glfwGetKey(GLFW_KEY_UP)); setbool("down", glfwGetKey(GLFW_KEY_DOWN)); setbool("a", glfwGetKey('Q')); setbool("b", glfwGetKey('W')); lua_pushboolean(l, glfwGetWindowParam(GLFW_OPENED) > 0); return 1; }
// common run state void RunState() { #if defined(USE_SDL) // last ticks unsigned int ticks = SDL_GetTicks(); #elif defined(USE_SFML) // timer sf::Clock timer; // start timer timer.Reset(); #elif defined(USE_GLFW) double prevtime = glfwGetTime(); #endif // input logging TiXmlDocument inputlog(RECORD_CONFIG.c_str()); TiXmlElement *inputlogroot; TiXmlElement *inputlognext; if (playback) { if (!inputlog.LoadFile()) DebugPrint("error loading recording file \"%s\": %s\n", RECORD_CONFIG.c_str(), inputlog.ErrorDesc()); inputlogroot = inputlog.RootElement(); inputlognext = inputlogroot->FirstChildElement(); } else if (record) { inputlogroot = inputlog.LinkEndChild(new TiXmlElement("journal"))->ToElement(); inputlognext = NULL; } else { inputlogroot = NULL; inputlognext = NULL; } #ifdef GET_PERFORMANCE_DETAILS PerfTimer::Init(); PerfTimer control_timer; PerfTimer simulate_timer; PerfTimer collide_timer; PerfTimer update_timer; PerfTimer render_timer; PerfTimer overlay_timer; PerfTimer display_timer; PerfTimer total_timer; total_timer.Stamp(); #endif #ifdef COLLECT_DEBUG_DRAW // create a new draw list GLuint debugdraw = glGenLists(1); #endif // wait for user exit do { #ifdef GET_PERFORMANCE_DETAILS PerfTimer::Next(); control_timer.Clear(); simulate_timer.Clear(); collide_timer.Clear(); update_timer.Clear(); render_timer.Clear(); overlay_timer.Clear(); display_timer.Clear(); total_timer.Clear(); #endif // INPUT PHASE #if defined(USE_SDL) // event handler SDL_Event event; // process events while( SDL_PollEvent( &event ) ) { /* Give the console first dibs on event processing */ if (OGLCONSOLE_SDLEvent(&event)) continue; switch (event.type) { case SDL_KEYDOWN: input.OnPress( Input::TYPE_KEYBOARD, event.key.which, event.key.keysym.sym ); switch (event.key.keysym.sym) { case SDLK_F4: if (event.key.keysym.mod & KMOD_ALT) setgamestate = STATE_QUIT; break; case SDLK_RETURN: if (event.key.keysym.mod & KMOD_ALT) { CloseWindow(); SCREEN_FULLSCREEN = !SCREEN_FULLSCREEN; OpenWindow(); } break; case SDLK_ESCAPE: if (curgamestate == STATE_PLAY) { if (escape) EscapeMenuExit(); else EscapeMenuEnter(); } break; case SDLK_PAUSE: if (event.key.keysym.mod & KMOD_SHIFT) { paused = true; singlestep = true; } else { paused = !paused; } if (paused) Pause(); else Resume(); break; case SDLK_PRINT: Screenshot(); break; } break; case SDL_KEYUP: input.OnRelease( Input::TYPE_KEYBOARD, event.key.which, event.key.keysym.sym ); break; case SDL_MOUSEMOTION: input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 0, float(event.motion.x * 2 - SCREEN_WIDTH) / float(SCREEN_HEIGHT) ); input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 1, float(event.motion.y * 2 - SCREEN_HEIGHT) / float(SCREEN_HEIGHT) ); input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 2, event.motion.xrel / 32.0f ); input.OnAxis( Input::TYPE_MOUSE_AXIS, event.motion.which, 3, event.motion.yrel / 32.0f ); break; case SDL_MOUSEBUTTONDOWN: input.OnPress( Input::TYPE_MOUSE_BUTTON, event.button.which, event.button.button ); break; case SDL_MOUSEBUTTONUP: input.OnRelease( Input::TYPE_MOUSE_BUTTON, event.button.which, event.button.button ); break; case SDL_JOYAXISMOTION: input.OnAxis( Input::TYPE_JOYSTICK_AXIS, event.jaxis.which, event.jaxis.axis, event.jaxis.value / 32767.0f ); break; case SDL_JOYBUTTONDOWN: input.OnPress( Input::TYPE_JOYSTICK_BUTTON, event.jaxis.which, event.jbutton.button ); break; case SDL_JOYBUTTONUP: input.OnRelease( Input::TYPE_JOYSTICK_BUTTON, event.jbutton.which, event.jbutton.button ); break; case SDL_QUIT: setgamestate = STATE_QUIT; break; } } // get loop time in ticks unsigned int nextticks = SDL_GetTicks(); float delta = (nextticks - ticks) / 1000.0f; ticks = nextticks; #elif defined(USE_SFML) sf::Event event; while (window.GetEvent(event)) { /* Give the console first dibs on event processing */ if (OGLCONSOLE_SFMLEvent(&event)) continue; // Some code for stopping application on close or when escape is pressed... switch (event.Type) { case sf::Event::Resized: glViewport(0, 0, event.Size.Width, event.Size.Height); break; case sf::Event::KeyPressed: input.OnPress( Input::TYPE_KEYBOARD, 0, event.Key.Code ); switch(event.Key.Code) { case sf::Key::F4: if (event.Key.Alt) setgamestate = STATE_QUIT; break; case sf::Key::Return: if (event.Key.Alt) { CloseWindow(); SCREEN_FULLSCREEN = !SCREEN_FULLSCREEN; OpenWindow(); } break; case sf::Key::Escape: if (curgamestate == STATE_PLAY) { if (escape) EscapeMenuExit(); else EscapeMenuEnter(); } break; case sf::Key::Pause: if (event.Key.Shift) { paused = true; singlestep = true; } else { paused = !paused; } if (paused) Pause(); else Resume(); break; } break; case sf::Event::KeyReleased: input.OnRelease( Input::TYPE_KEYBOARD, 0, event.Key.Code ); break; case sf::Event::MouseMoved: input.OnAxis( Input::TYPE_MOUSE_AXIS, 0, 0, float(int(event.MouseMove.X) * 2 - SCREEN_WIDTH) / float(SCREEN_HEIGHT) ); input.OnAxis( Input::TYPE_MOUSE_AXIS, 0, 1, float(int(event.MouseMove.Y) * 2 - SCREEN_HEIGHT) / float(SCREEN_HEIGHT) ); break; case sf::Event::MouseButtonPressed: input.OnPress( Input::TYPE_MOUSE_BUTTON, 0, event.MouseButton.Button ); break; case sf::Event::MouseButtonReleased: input.OnRelease( Input::TYPE_MOUSE_BUTTON, 0, event.MouseButton.Button ); break; case sf::Event::JoyMoved: input.OnAxis( Input::TYPE_JOYSTICK_AXIS, event.JoyMove.JoystickId, event.JoyMove.Axis, event.JoyMove.Position / 100.0f ); break; case sf::Event::JoyButtonPressed: input.OnPress( Input::TYPE_JOYSTICK_BUTTON, event.JoyButton.JoystickId, event.JoyButton.Button ); break; case sf::Event::JoyButtonReleased: input.OnRelease( Input::TYPE_JOYSTICK_BUTTON, event.JoyButton.JoystickId, event.JoyButton.Button ); break; case sf::Event::Closed: setgamestate = STATE_QUIT; break; } } // get loop time in ticks float delta = timer.GetElapsedTime(); timer.Reset(); //ticks += delta; #elif defined(USE_GLFW) if (glfwGetJoystickParam(0, GLFW_PRESENT)) { // get joystick axis positions int axiscount = glfwGetJoystickParam(0, GLFW_AXES); float *axis = static_cast<float *>(_alloca(axiscount * sizeof(float))); axiscount = glfwGetJoystickPos(0, axis, axiscount); for (int i = 0; i < axiscount; ++i) input.OnAxis(Input::TYPE_JOYSTICK_AXIS, 0, i, axis[i]); // get joystick button states int buttoncount = glfwGetJoystickParam(0, GLFW_BUTTONS); unsigned char *button = static_cast<unsigned char *>(_alloca(buttoncount * sizeof(unsigned char))); buttoncount = glfwGetJoystickButtons(0, button, buttoncount); for (int i = 0; i < buttoncount; ++i) input.OnAxis(Input::TYPE_JOYSTICK_BUTTON, 0, i, button[i]); } double nexttime = glfwGetTime(); float delta = float(nexttime - prevtime); prevtime = nexttime; #endif // clamp ticks to something sensible // (while debugging, for example) if (delta > 0.1f) delta = 0.1f; // frame time and turns if (singlestep) { // advance 1/60th of a second frame_time = TIME_SCALE / 60.0f; frame_turns = frame_time * sim_rate; } else if (paused || escape) { // freeze time frame_time = 0.0f; frame_turns = 0.0f; } else if (FIXED_STEP) { // advance one simulation step frame_time = TIME_SCALE * sim_step; frame_turns = TIME_SCALE; } else { // advance by frame time frame_time = delta * TIME_SCALE; frame_turns = frame_time * sim_rate; } // turns per motion-blur step float step_turns = std::min(TIME_SCALE * MOTIONBLUR_TIME * sim_rate, 1.0f) / MOTIONBLUR_STEPS; // advance to beginning of motion blur steps sim_fraction += frame_turns; sim_fraction -= MOTIONBLUR_STEPS * step_turns; // for each motion-blur step for (int blur = 0; blur < MOTIONBLUR_STEPS; ++blur) { // clear the screen glClear( GL_COLOR_BUFFER_BIT #ifdef ENABLE_DEPTH_TEST | GL_DEPTH_BUFFER_BIT #endif ); // set projection glMatrixMode( GL_PROJECTION ); glLoadIdentity(); glFrustum( -0.5*VIEW_SIZE*SCREEN_WIDTH/SCREEN_HEIGHT, 0.5*VIEW_SIZE*SCREEN_WIDTH/SCREEN_HEIGHT, 0.5f*VIEW_SIZE, -0.5f*VIEW_SIZE, 256.0f*1.0f, 256.0f*5.0f ); // set base modelview matrix glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); glTranslatef( 0.0f, 0.0f, -256.0f ); glScalef( -1.0f, -1.0f, -1.0f ); // advance the sim timer sim_fraction += step_turns; if (escape) { input.Update(); input.Step(); } // while simulation turns to run... else while ((singlestep || !paused) && sim_fraction >= 1.0f) { // deduct a turn sim_fraction -= 1.0f; // advance the turn counter ++sim_turn; // save original fraction float save_fraction = sim_fraction; // switch fraction to simulation mode sim_fraction = 0.0f; #ifdef COLLECT_DEBUG_DRAW // collect any debug draw glNewList(debugdraw, GL_COMPILE); #endif // seed the random number generator Random::Seed(0x92D68CA2 ^ sim_turn); (void)Random::Int(); // update database Database::Update(); if (curgamestate == STATE_PLAY) { if (playback) { // quit if out of turns if (!inputlognext) { setgamestate = STATE_SHELL; break; } // get the next turn value int turn = -1; inputlognext->QueryIntAttribute("turn", &turn); // if the turn matches the simulation turn... if ((unsigned int)turn == sim_turn) { // update the control values input.Playback(inputlognext); // go to the next entry inputlognext = inputlognext->NextSiblingElement(); } } else if (record) { // save original input values float prev[Input::NUM_LOGICAL]; memcpy(prev, input.output, sizeof(prev)); // update input values input.Update(); // if any controls have changed... bool changed = false; for (int i = 0; i < Input::NUM_LOGICAL; ++i) { if (input.output[i] != prev[i]) { changed = true; break; } } if (changed) { // create an input turn entry TiXmlElement item( "input" ); item.SetAttribute( "turn", sim_turn ); // add changed control values input.Record(&item, prev); // add the new input entry inputlogroot->InsertEndChild(item); } } else { // update input values input.Update(); } } // do any pending turn actions DoTurn(); // CONTROL PHASE #ifdef GET_PERFORMANCE_DETAILS control_timer.Start(); #endif // control all entities Controller::ControlAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS control_timer.Stop(); simulate_timer.Start(); #endif // SIMULATION PHASE // (generate forces) Simulatable::SimulateAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS simulate_timer.Stop(); collide_timer.Start(); #endif // COLLISION PHASE // (apply forces and update positions) Collidable::CollideAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS collide_timer.Stop(); update_timer.Start(); #endif // UPDATE PHASE // (use updated positions) Updatable::UpdateAll(sim_step); #ifdef GET_PERFORMANCE_DETAILS update_timer.Stop(); #endif // step inputs for next turn input.Step(); #ifdef COLLECT_DEBUG_DRAW // finish the draw list glEndList(); #endif // restore original fraction sim_fraction = save_fraction; } // clear single-step singlestep = false; // seed the random number generator FloatInt floatint; floatint.f = sim_fraction; Random::Seed(0x92D68CA2 ^ sim_turn ^ floatint.u); (void)Random::Int(); #ifdef PRINT_SIMULATION_TIMER DebugPrint("delta=%f ticks=%d sim_t=%f\n", delta, ticks, sim_fraction); #endif #ifdef GET_PERFORMANCE_DETAILS render_timer.Start(); #endif // RENDERING PHASE // push camera transform glPushMatrix(); // get interpolated track position Vector2 viewpos(Lerp(camerapos[0], camerapos[1], sim_fraction)); // set view position glTranslatef( -viewpos.x, -viewpos.y, 0 ); // calculate view area AlignedBox2 view; view.min.x = viewpos.x - VIEW_SIZE * 0.5f * SCREEN_WIDTH / SCREEN_HEIGHT; view.max.x = viewpos.x + VIEW_SIZE * 0.5f * SCREEN_WIDTH / SCREEN_HEIGHT; view.min.y = viewpos.y - VIEW_SIZE * 0.5f; view.max.y = viewpos.y + VIEW_SIZE * 0.5f; // render all entities // (send interpolation ratio and offset from simulation time) Renderable::RenderAll(view); // reset camera transform glPopMatrix(); // if performing motion blur... if (MOTIONBLUR_STEPS > 1) { // accumulate the image glAccum(blur ? GL_ACCUM : GL_LOAD, 1.0f / float(MOTIONBLUR_STEPS)); } #ifdef GET_PERFORMANCE_DETAILS render_timer.Stop(); #endif } #ifdef GET_PERFORMANCE_DETAILS render_timer.Start(); #endif // if performing motion blur... if (MOTIONBLUR_STEPS > 1) { // return the accumulated image glAccum(GL_RETURN, 1); } // switch blend mode glPushAttrib(GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); #ifdef GET_PERFORMANCE_DETAILS render_timer.Stop(); overlay_timer.Start(); #endif #ifdef COLLECT_DEBUG_DRAW if (DEBUG_DRAW) { // push camera transform glPushMatrix(); // get interpolated track position Vector2 viewpos(Lerp(camerapos[0], camerapos[1], sim_fraction)); // set camera to track position glTranslatef( -viewpos.x, -viewpos.y, 0 ); // debug draw glCallList(debugdraw); // pop camera transform glPopMatrix(); } #endif // push projection transform glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 640, 480, 0, -1, 1); // use 640x480 screen coordinates glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // render all overlays Overlay::RenderAll(); #ifdef GET_PERFORMANCE_DETAILS overlay_timer.Stop(); if (!OPENGL_SWAPCONTROL) { display_timer.Start(); // wait for rendering to finish glFinish(); display_timer.Stop(); } #ifdef DRAW_PERFORMANCE_DETAILS if (PROFILER_OUTPUTSCREEN) { struct BandInfo { const LONGLONG * time; float r; float g; float b; float a; }; static BandInfo band_info[] = { { control_timer.mHistory, 1.0f, 0.0f, 0.0f, 0.5f }, { simulate_timer.mHistory, 1.0f, 1.0f, 0.0f, 0.5f }, { collide_timer.mHistory, 0.0f, 1.0f, 0.0f, 0.5f }, { update_timer.mHistory, 0.0f, 0.5f, 1.0f, 0.5f }, { render_timer.mHistory, 1.0f, 0.0f, 1.0f, 0.5f }, { overlay_timer.mHistory, 1.0f, 0.5f, 0.0f, 0.5f }, { display_timer.mHistory, 0.5f, 0.5f, 0.5f, 0.5f }, }; // generate y samples float sample_y[SDL_arraysize(band_info)+1][PerfTimer::NUM_SAMPLES]; int index = PerfTimer::mIndex; for (int i = 0; i < PerfTimer::NUM_SAMPLES; ++i) { float y = 480.0f; sample_y[0][i] = y; for (int band = 0; band < SDL_arraysize(band_info); ++band) { y -= 60.0f * 480.0f * band_info[band].time[index] / PerfTimer::mFrequency; sample_y[band+1][i] = y; } if (++index >= PerfTimer::NUM_SAMPLES) index = 0; } glBegin(GL_QUADS); for (int band = 0; band < SDL_arraysize(band_info); ++band) { glColor4fv(&band_info[band].r); float x = 0; float dx = 640.0f / PerfTimer::NUM_SAMPLES; for (int i = 0; i < PerfTimer::NUM_SAMPLES; i++) { glVertex3f(x, sample_y[band][i], 0); glVertex3f(x+dx, sample_y[band][i], 0); glVertex3f(x+dx, sample_y[band+1][i], 0); glVertex3f(x, sample_y[band+1][i], 0); x += dx; } } glEnd(); } #endif #ifdef PRINT_PERFORMANCE_DETAILS if (PROFILER_OUTPUTPRINT) { DebugPrint("C=%d S=%d P=%d U=%d R=%d O=%d D=%d\n", control_timer.Microseconds(), simulate_timer.Microseconds(), collide_timer.Microseconds(), update_timer.Microseconds(), render_timer.Microseconds(), overlay_timer.Microseconds(), display_timer.Microseconds()); } #endif // update frame timer total_timer.Stamp(); #if defined(PRINT_PERFORMANCE_FRAMERATE) || defined(DRAW_PERFORMANCE_FRAMERATE) if (FRAMERATE_OUTPUTSCREEN || FRAMERATE_OUTPUTPRINT) { // compute minimum, maximum, and average frame times over the past second LONGLONG total_min = LLONG_MAX; LONGLONG total_max = LLONG_MIN; LONGLONG total_sum = 0; LONGLONG total_samples = 0; int i = PerfTimer::mIndex; do { total_min = std::min(total_min, total_timer.mHistory[i]); total_max = std::max(total_max, total_timer.mHistory[i]); total_sum += total_timer.mHistory[i]; ++total_samples; i = (i > 0) ? i - 1 : PerfTimer::NUM_SAMPLES - 1; } while (total_sum <= PerfTimer::mFrequency && i != PerfTimer::mIndex && total_samples != PerfTimer::mCount); total_sum /= total_samples; // compute frame rates double rate_max = (double)PerfTimer::mFrequency / total_min; double rate_avg = (double)PerfTimer::mFrequency / total_sum; double rate_min = (double)PerfTimer::mFrequency / total_max; #if defined(DRAW_PERFORMANCE_FRAMERATE) if (FRAMERATE_OUTPUTSCREEN) { // draw frame rate indicator glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, OGLCONSOLE_glFontHandle); glBegin(GL_QUADS); char fps[16]; sprintf(fps, "%.2f max", rate_max); glColor4f(0.5f, 0.5f, 0.5f, 1.0f); OGLCONSOLE_DrawString(fps, 640 - 16 - 8 * strlen(fps), 16, 8, -8, 0); sprintf(fps, "%.2f avg", rate_avg); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); OGLCONSOLE_DrawString(fps, 640 - 16 - 8 * strlen(fps), 24, 8, -8, 0); sprintf(fps, "%.2f min", rate_min); glColor4f(0.5f, 0.5f, 0.5f, 1.0f); OGLCONSOLE_DrawString(fps, 640 - 16 - 8 * strlen(fps), 32, 8, -8, 0); glEnd(); glDisable(GL_TEXTURE_2D); } #endif #if defined(PRINT_PERFORMANCE_FRAMERATE) if (FRAMERATE_OUTPUTPRINT) { DebugPrint("%.2f<%.2f<%.2f\n", rate_min, rate_avg, rate_max); } #endif } #endif #endif // reset camera transform glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); // restore blend mode glPopAttrib(); /* Render our console */ OGLCONSOLE_Draw(); // show the back buffer Platform::Present(); #if 0 #ifdef GET_PERFORMANCE_DETAILS if (OPENGL_SWAPCONTROL) #endif // wait for rendering to finish glFinish(); #endif // clear device reset flag wasreset = false; } while( setgamestate == curgamestate ); if (record) { // save input log inputlog.SaveFile(); } }
int main(int argc, char *argv[]) { char *shader = "mandelbrot (copy).frag"; if (argc > 1) { shader = argv[1]; } glfwInit(); /*int major, minor, rev; glfwGetGLVersion(&major, &minor, &rev); printf("using openGL %d.%d.%d\n", major, minor, rev);*/ GLFWvidmode mode; glfwGetDesktopMode( &mode ); window_width = mode.Width; window_height = mode.Height; printf("%dx%d\n", window_width, window_height); //glfwOpenWindow(window_width, window_height, 5, 6, 5, 0, 8, 0, GLFW_FULLSCREEN); glfwOpenWindow(mode.Width, mode.Height, mode.RedBits, mode.GreenBits, mode.BlueBits, 0, 0, 0, GLFW_FULLSCREEN); // setup opengl perspective stuff. glMatrixMode(GL_PROJECTION); float aspect_ratio = ((float)window_height) / window_width; glFrustum(.5, -.5, -.5 * aspect_ratio, .5 * aspect_ratio, 1, 50); glDisable( GL_DEPTH_TEST ); glTranslatef(0.0, 0.0, -1.00); glClearColor(0.0, 1.0, 1.0, 0.0); // will create and set shader program. GLhandleARB program = SetupFragmentShader(shader); // get the location of all the uniforms prepareUniforms(program); // must call use program before setting uniforms values glUseProgram(program); uint param_i = 0; parameters[WIDTH] = createParameter1i(program, "wW", window_width ); parameters[HEIGHT] = createParameter1i(program, "wH", window_height ); parameters[TIME] = createParameter1f(program, "time", 0.0 ); parameters[MINX] = createParameter1f(program, "minx", -2.0); parameters[MINY] = createParameter1f(program, "miny", 1.0); parameters[DELTA] = createParameter1f(program, "deltax", 3.0); parameters[THETA] = createParameter1f(program, "theta", 1.0); //synchParameters ( parameters ); /*for ( param_i = 0; param_i < NPARAMS; param_i++ ) { Parameter *param = ¶meters[param_i]; switch ( param->utype ) { case INT: glUniform1i(param->loc, param->u.ival); break; case FLOAT: glUniform1f(param->loc, param->u.fval); break; default: break; } }*/ // set the dimension, must be after program is used. //glUniform1i(wWLoc, window_width ); //glUniform1i(wHLoc, window_height ); printInstructions(); double frame_start = glfwGetTime(); double frame_time = 0.0; double temp_time = 0.0; //bool need_draw = true; bool need_view_synch = true; int mouseWheel = 0; int mouseWheelDelta = 0; double fIterations = (double)(iterations); int mouseX, mouseY, curMouseX, curMouseY; mouseX = mouseY = 0; bool joystickPresent = glfwGetJoystickParam( GLFW_JOYSTICK_1, GLFW_PRESENT ); if(joystickPresent) { printf("Joystick present. Can be used to navigate in addition to mouse.\n"); }else { printf("no joystick present.\n"); } // set up fonts FTGLfont *font = NULL; //font = ftglCreateBufferFont("/usr/share/fonts/truetype/freefont/FreeMono.ttf"); font = ftglCreatePixmapFont("/usr/share/fonts/truetype/freefont/FreeMono.ttf"); if( !font ) { printf("failed to load font."); } ftglSetFontFaceSize(font, 50, 50); //printf("%d\n", ftglGetFontError(font)); //ftglSetFontCharMap(font, ft_encoding_unicode); //printf("%d\n", ftglGetFontError(font)); bool show_fps = true; char text[256]; // keep on rendering the frame until escape is pressed. while(glfwGetKey(GLFW_KEY_ESC) != GLFW_PRESS) { temp_time = glfwGetTime(); frame_time = temp_time - frame_start; frame_start = temp_time; // process input if(glfwGetKey('E') == GLFW_PRESS) { printf("minx: %.31f\n", minx); printf("miny: %.31f\n", miny); printf("deltax: %.31f\n",deltax); printf("deltay: %.31f\n",deltay); printf("====================================\n"); }else if(glfwGetKey('P') == GLFW_PRESS) { saveFrameBuffer(); }else if(glfwGetKey('R') == GLFW_PRESS) { minx = -2.0; miny = -1.0; deltax = 3.0; deltay = 2.0; need_view_synch = true; }else if(glfwGetKey('F') == GLFW_PRESS) { show_fps=~show_fps; //printf("fps display toggled to: %d\n", show_fps); } else if(glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS) { fIterations += 5*(60*frame_time); iterations = floor(fIterations); need_view_synch = true; }else if(glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS) { if(iterations>1) { fIterations -= 5*(60*frame_time); } iterations = floor(fIterations); need_view_synch = true; } // zooming using the arrow keys if(glfwGetKey(GLFW_KEY_UP) == GLFW_PRESS) { zoomIn(2.0*zoom_factor*(frame_time*60.0)); need_view_synch = true; }else if(glfwGetKey(GLFW_KEY_DOWN) == GLFW_PRESS) { zoomIn(-2.0*zoom_factor*(frame_time*60.0)); need_view_synch = true; } //changing the julia set constant if(glfwGetKey('W') == GLFW_PRESS) { realc += .0025*frame_time*60.0; need_view_synch = true; }else if(glfwGetKey('S') == GLFW_PRESS) { realc -= .0025*frame_time*60.0; need_view_synch = true; } if(glfwGetKey('A') == GLFW_PRESS) { imagc += .0025*frame_time*60.0; need_view_synch = true; }else if(glfwGetKey('D') == GLFW_PRESS) { imagc -= .0025*frame_time*60.0; need_view_synch = true; } // changing the area visible (panning left and right) glfwGetMousePos(&curMouseX, &curMouseY); int mouseDeltax = curMouseX - mouseX; int mouseDeltay = curMouseY - mouseY; if(mouseDeltax||mouseDeltay)//if one of them is different { //printf("delta coordinates: (%d, %d)\n", mouseDeltax, mouseDeltay); mouseX=curMouseX; mouseY=curMouseY; //printf("new mouse coordinates: (%d, %d)\n", x, y); pan(zoom_factor*deltax*mouseDeltax/20.0, -1*zoom_factor*deltay*mouseDeltay/20.0); need_view_synch = true; } if(joystickPresent) { float pos[4]; glfwGetJoystickPos(GLFW_JOYSTICK_1, pos, 4); //the above function gives us bad results for my particular joystick :(, must fiddle around with numbers to get correct answer. float xJoyPos = pos[0];//(pos[0]*32767)/128.0 - 1.0; float yJoyPos = pos[1];//(pos[1]*32767)/128.0 + 1.0; float zJoyPos = -1*pos[2];//-1*((pos[2]*32767)/128.0 - 1.0); float rJoyPos = pos[3]; float temp = 0.0; //printf("%f\n", xJoyPos); if(xJoyPos>.02||xJoyPos<-.02) { temp = zoom_factor*xJoyPos*deltax*1.0*frame_time*60.0; pan(temp, 0); need_view_synch = true; } if(yJoyPos>.02||yJoyPos<-.02) { temp = zoom_factor*yJoyPos*deltay*1.0*frame_time*60.0; pan(0, temp); need_view_synch = true; } if(zJoyPos>.04||zJoyPos<-.04) { zoomIn(zJoyPos*scroll_zoom_factor*(frame_time*10.0)); need_view_synch = true; } if(rJoyPos>.02 || rJoyPos<-.02) { rotate( rJoyPos/5.0*frame_time ); need_view_synch = true; } unsigned char buttons[5]; glfwGetJoystickButtons(GLFW_JOYSTICK_1, buttons, 4); if(buttons[0]==GLFW_PRESS) { saveFrameBuffer(); } if(buttons[1]==GLFW_PRESS) { rotate( 0.35*frame_time ); need_view_synch = true; }else if(buttons[2]==GLFW_PRESS) { rotate( -0.35*frame_time ); need_view_synch = true; } //printf("x:%f, y:%f\n", xJoyPos, yJoyPos); } // zooming using the mouse scroll mouseWheelDelta = glfwGetMouseWheel() - mouseWheel; mouseWheel = mouseWheel+mouseWheelDelta; if(mouseWheelDelta != 0) { zoomIn(mouseWheelDelta*scroll_zoom_factor*(frame_time*60.0)); need_view_synch = true; } //printf("mouse wheel: %d\n", mouseWheelDelta); if(need_view_synch) { synchVariableUniforms(); need_view_synch = false; } // update the time inside the shader for cool animations. parameters[2].val.fval = frame_start; parameters[2].needs_update = true; synchParameters ( parameters ); //glUniform1f(timeLoc, frame_start); // write fps and iterations to a string. sprintf(text, "FPS: %4.1d; ITER: %d; ZOOMX: %-10.1f", (int)(floor(1.0/frame_time)), iterations, (3.0/deltax)); //sprintf("fps %f\n", 1.0/frame_time); // clear the buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //since all calculations are being done in the fragment shader, all we draw is a surface. glUseProgram(program); glRects(-1, -1, 1, 1); // render font on top of this? if(show_fps != 0){ glUseProgram(0); glColor3f(0.0f, 0.0f, 0.0f); ftglRenderFont(font, text, FTGL_RENDER_ALL); glUseProgram(program); } // note: swap buffers also updates the input events for glfw glfwSwapBuffers(); } // clean up the font and exit. ftglDestroyFont(font); return 1; }
void PlayerControl( void ) { float joy1pos[ 2 ], joy2pos[ 2 ]; // Get joystick X & Y axis positions glfwGetJoystickPos( GLFW_JOYSTICK_1, joy1pos, 2 ); glfwGetJoystickPos( GLFW_JOYSTICK_2, joy2pos, 2 ); // Player 1 control if( glfwGetKey( 'A' ) || joy1pos[ 1 ] > 0.2f ) { player1.yspeed += dt * ACCELERATION; if( player1.yspeed > MAX_SPEED ) { player1.yspeed = MAX_SPEED; } } else if( glfwGetKey( 'Z' ) || joy1pos[ 1 ] < -0.2f ) { player1.yspeed -= dt * ACCELERATION; if( player1.yspeed < -MAX_SPEED ) { player1.yspeed = -MAX_SPEED; } } else { player1.yspeed /= exp( DECELERATION * dt ); } // Player 2 control if( glfwGetKey( 'K' ) || joy2pos[ 1 ] > 0.2f ) { player2.yspeed += dt * ACCELERATION; if( player2.yspeed > MAX_SPEED ) { player2.yspeed = MAX_SPEED; } } else if( glfwGetKey( 'M' ) || joy2pos[ 1 ] < -0.2f ) { player2.yspeed -= dt * ACCELERATION; if( player2.yspeed < -MAX_SPEED ) { player2.yspeed = -MAX_SPEED; } } else { player2.yspeed /= exp( DECELERATION * dt ); } // Update player 1 position player1.ypos += dt * player1.yspeed; if( player1.ypos > 1.0 - PLAYER_YSIZE ) { player1.ypos = 1.0 - PLAYER_YSIZE; player1.yspeed = 0.0; } else if( player1.ypos < -1.0 + PLAYER_YSIZE ) { player1.ypos = -1.0 + PLAYER_YSIZE; player1.yspeed = 0.0; } // Update player 2 position player2.ypos += dt * player2.yspeed; if( player2.ypos > 1.0 - PLAYER_YSIZE ) { player2.ypos = 1.0 - PLAYER_YSIZE; player2.yspeed = 0.0; } else if( player2.ypos < -1.0 + PLAYER_YSIZE ) { player2.ypos = -1.0 + PLAYER_YSIZE; player2.yspeed = 0.0; } }