// Implement mouse-dragging for this movie. void root::do_mouse_drag() { character* draggingChar = m_drag_state.GetCharacter(); if (draggingChar == NULL) { return; } // handle if the character isn't valid anymore if (draggingChar->is_alive() == false) { // no longer valid m_drag_state.Reset(); return; } // get the current mouse int x, y, buttons; get_mouse_state( &x, &y, &buttons ); // ... in world coordinates (twips) point worldMouse( PIXELS_TO_TWIPS(x), PIXELS_TO_TWIPS(y) ); matrix parentWorldMat; if (draggingChar->m_parent != NULL) { parentWorldMat = draggingChar->m_parent->get_world_matrix(); } // if we're not locked to the center - adjust by the offset we started dragging by if(m_drag_state.IsLockCentered() == false) { worldMouse.m_x -= m_drag_state.OffsetX(); worldMouse.m_y -= m_drag_state.OffsetY(); } rect origBoundRect; if (m_drag_state.GetBounds(&origBoundRect)) { // bounds are in local coordinate space rect bounds; bounds.enclose_transformed_rect( parentWorldMat, origBoundRect ); // Clamp mouse coords within a defined rect. worldMouse.m_x = fclamp(worldMouse.m_x, bounds.m_x_min, bounds.m_x_max); worldMouse.m_y = fclamp(worldMouse.m_y, bounds.m_y_min, bounds.m_y_max); } point parentMouse; parentWorldMat.transform_by_inverse( &parentMouse, worldMouse ); // Place our origin so that it coincides with the mouse coords // in our parent frame. matrix local = draggingChar->get_matrix(); local.m_[0][2] = parentMouse.m_x;//set translation x local.m_[1][2] = parentMouse.m_y;//set translation y draggingChar->set_matrix( local ); }
void set_color(float voltage) // Set a color based on the voltage. { // Red --> Green --> Blue gradient float f = scurve(scurve(voltage)); // enhance contrast! glColor3f( fclamp(2 * (f - 0.5f), 0, 1), 1 - 2 * fabs(f - 0.5f), fclamp(2 * (0.5f - f), 0, 1)); }
rgba cxform::transform(const rgba in) const // Apply our transform to the given color; return the result. { rgba result; result.m_r = (Uint8) fclamp(in.m_r * m_[0][0] + m_[0][1], 0, 255); result.m_g = (Uint8) fclamp(in.m_g * m_[1][0] + m_[1][1], 0, 255); result.m_b = (Uint8) fclamp(in.m_b * m_[2][0] + m_[2][1], 0, 255); result.m_a = (Uint8) fclamp(in.m_a * m_[3][0] + m_[3][1], 0, 255); return result; }
void rotate_by_gyro(float dtheta) { const float drive_max = 0.7; const float drive_min = 0.2; const float angle_tolerance = 9; const float correct_hold_time = 300; float final = gyro_get_degrees() + dtheta; bool correct_timer_active = false; uint32_t correct_timer_start = 0; while(!correct_timer_active || get_time() < correct_timer_start + correct_hold_time) { float angdiff = ang_diff(final, gyro_get_degrees()); int direction = angdiff > 0 ? 1 : -1; float pow = fclamp(fabs(angdiff) / 90, drive_min, drive_max); set_wheel_pows( -direction * pow , direction * pow ); if (fabs(ang_diff(final, gyro_get_degrees())) < angle_tolerance) { if (!correct_timer_active) { correct_timer_start = get_time(); } correct_timer_active = true; } else { correct_timer_active = false; } printf("rotating by %.2f ", dtheta); printf("angdiff %.2f ", angdiff); printf("gyro %.2f %> %.2f ", gyro_get_degrees(), fmod(gyro_get_degrees(), 360)); printf("wpows [ %.2f , %.2f ] ", get_wheel_pows().l, get_wheel_pows().r); printf("timer:%i start:%i since:%i\n", correct_timer_active, correct_timer_start, get_time() - correct_timer_start); pause(2); }
void resample(SDL_Surface* dest, int out_x0, int out_y0, int out_x1, int out_y1, SDL_Surface* src, float in_x0, float in_y0, float in_x1, float in_y1) // Resample the specified rectangle of the src surface into the // specified rectangle of the destination surface. Output coords // are inclusive. { // Make sure output is within bounds. assert(out_x0 >= 0 && out_x0 < dest->w); assert(out_x1 > out_x0 && out_x1 < dest->w); assert(out_y0 >= 0 && out_y0 < dest->h); assert(out_y1 > out_y0 && out_y1 < dest->h); int dxo = (out_x1 - out_x0); int dyo = (out_y1 - out_y0); // @@ check input... float dxi = in_x1 - in_x0; float dyi = in_y1 - in_y0; assert(dxi > 0.001f); assert(dyi > 0.001f); float x_factor = dxi / dxo; float y_factor = dyi / dyo; // @@ not optimized. for (int j = 0; j <= dyo; j++) { for (int i = 0; i <= dxo; i++) { // @@ simple nearest-neighbor point-sample. float x = i * x_factor + in_x0; float y = j * y_factor + in_y0; x = fclamp(x, 0.f, float(src->w - 1)); y = fclamp(y, 0.f, float(src->h - 1)); Uint8* p = scanline(src, frnd(y)) + 3 * frnd(x); Uint8* q = scanline(dest, out_y0 + j) + 3 * (out_x0 + i); *q++ = *p++; // red *q++ = *p++; // green *q++ = *p++; // blue } } }
void cxform::clamp() // Force component values to be in legal range. { m_[0][0] = fclamp(m_[0][0], 0, 1); m_[1][0] = fclamp(m_[1][0], 0, 1); m_[2][0] = fclamp(m_[2][0], 0, 1); m_[3][0] = fclamp(m_[3][0], 0, 1); m_[0][1] = fclamp(m_[0][1], -255.0f, 255.0f); m_[1][1] = fclamp(m_[1][1], -255.0f, 255.0f); m_[2][1] = fclamp(m_[2][1], -255.0f, 255.0f); m_[3][1] = fclamp(m_[3][1], -255.0f, 255.0f); }
// public lineStyle(thickness:Number, rgb:Number, alpha:Number, pixelHinting:Boolean, // noScale:String, capsStyle:String, jointStyle:String, miterLimit:Number) : Void void sprite_line_style(const fn_call& fn) { sprite_instance* sprite = sprite_getptr(fn); canvas* canva = sprite->get_canvas(); assert(canva); // If a thickness is not specified, or if the parameter is undefined, a line is not drawn if (fn.nargs == 0) { canva->m_current_line = 0; canva->add_path(false); return; } Uint16 width = (Uint16) PIXELS_TO_TWIPS(fclamp(fn.arg(0).to_float(), 0, 255)); rgba color(0, 0, 0, 255); if (fn.nargs >= 2) { color.set(fn.arg(1).to_float()); if (fn.nargs >= 3) { float alpha = fclamp(fn.arg(2).to_float(), 0, 100); color.m_a = Uint8(255 * (alpha/100)); // capsStyle:String - Added in Flash Player 8. // A string that specifies the type of caps at the end of lines. // Valid values are: "round", "square", and "none". // If a value is not indicated, Flash uses round caps. if (fn.nargs >= 6) { //TODO } } } canva->set_line_style(width, color); }
CollData CollTest(const Circle &circle, const AABB &rect) { CollData cd{ false }; auto mm = rect.min(); auto mx = rect.max(); auto xc = fclamp(circle.position.x, mm.x, mx.x); auto yc = fclamp(circle.position.y, mm.y, mx.y); Vec2 point = { xc , yc }; const float dist = (point - circle.position).magnitude(); if (point.x == mm.x) { cd.normal.x = -1.0f; } else if (point.x == mx.x) { cd.normal.x == 1.0f; } if (point.y == mm.y) { cd.normal.y = -1.0f; } else if (point.y == mx.y) { cd.normal.y = 1.0f; } cd.depth = circle.radius - dist; cd.collision = (cd.depth >= 0.0f); return cd; }
CollData CollTest(const Circle &lhs, const Ray &rhs) { CollData cd = { false, 0, 0 }; float cD = dot(lhs.position, rhs.position); float clPoint = fclamp(cD, 0, rhs.length); Vec2 closePoint = rhs.position + rhs.direction * clPoint; float cTest = dot((lhs.position - closePoint), (lhs.position - closePoint)); if (cTest <= lhs.radius * lhs.radius) { //Need to determine Collision Normal and Penetration Depth. cd = { true, 0, 0 }; } return cd; }
//TODO: look at binary extension introduced in 2.1 version of hexy firmware to improve performance void HexySerial::move(qreal pos[], quint32 flags) { if(isConnected()) { for(quint32 i=0; i<SERVO_COUNT; ++i) { quint32 flag=(0x1<<i); if((flags & flag)>0) { const quint32 p=(quint32)(fclamp(pos[i],-1.0,1.0)*1000.0+1500.0); //Skip unecessary communication if value did not change if(lastPos[i]!=p) { lastPos[i]=p; dirtyMoveFlags|=flag; } } } //qDebug()<<"MOVE: flags="<< QString("%1").arg( flags, 16, 2, QChar('0'))<< ", dirtyMoveFlags="<<QString("%1").arg( dirtyMoveFlags, 16, 2, QChar('0')); if(dirtyMoveFlags>0 && 0==serial->bytesToWrite()) { syncMove(); } } else { qWarning()<<"ERROR: Trying to move servo with serial when not connected"; } }
void nuiAudioDevice_DS_OutputTh::Process(uint pos) { int16* pBuf1=NULL; int16* pBuf2=NULL; DWORD size1=0; DWORD size2=0; DWORD bufferBytes = mBufferSize * mNbChannels * sizeof(int16); bool isEmpty=false; if (!mpRingBuffer->GetReadable()) isEmpty=true; // // lock the output buffer if any, // and read data from ringbuffer and write to output buffer // if (mpDSOutputBuffer && FAILED(mpDSOutputBuffer->Lock(pos *bufferBytes /* offset */,bufferBytes /*size*/, (LPVOID*)&pBuf1, &size1, (LPVOID*)&pBuf2, &size2, 0))) { LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); //NGL_LOG(_T("nuiAudioDevice_DS_ProcessingTh"), NGL_LOG_ERROR, _T("ERROR : GetOutputBuffer()->Lock failed with error %d: %s"), dw, lpMsgBuf); LocalFree(lpMsgBuf); } else if (mpDSOutputBuffer) { if (!pBuf1 || !size1) { NGL_LOG(_T("nuiAudioDevice_DS_OutputTh"), NGL_LOG_ERROR, _T("Process error : could not lock any part of the input buffer\n")); NGL_ASSERT(0); return; } // check that we got the right size NGL_ASSERT((size1+size2) == bufferBytes); // no sound to play. silence please if (isEmpty) { memset(pBuf1, 0, size1); if (pBuf2) memset(pBuf2, 0, size2); } else { // copy ring buffer to local buffer uint32 nbRead = ReadFromRingBuf(mBufferSize, mFloatOutputBuf, mNbChannels); // clamp values of output buffer between -1 and 1 // convert and interlace local buffer from deinterlaced float to interlaced int16 for (uint32 ch=0; ch < mNbChannels; ch++) { float* pFloat = mFloatOutputBuf[ch]; for (uint32 s = 0; s < nbRead; s++) { (*pFloat) = fclamp(*pFloat, -1.0f, 1.0f); pFloat++; } nuiAudioConvert_DEfloatToINint16(mFloatOutputBuf[ch], mpLocalBuf, ch, mNbChannels, mBufferSize); } //#FIXME : here we can use pBuf1 and pBuf2 as the ouput buffer for DEfloatToINint16, instead of using a useless local buffer. // do that when you have the time to... :) // copy local buffer to output buffer memcpy(pBuf1, mpLocalBuf, size1); if (pBuf2) memcpy(pBuf2, mpLocalBuf+size1, size2); } // release DS input buffer mpDSOutputBuffer->Unlock(pBuf1, size1, pBuf2, size2); } }
int main(int argc, char *argv[]) { // Initialize the SDL subsystems we're using. if (SDL_Init(SDL_INIT_VIDEO /* | SDL_INIT_JOYSTICK | SDL_INIT_CDROM | SDL_INIT_AUDIO*/)) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); int width = 1000; int height = 1000; // Set the video mode. if (SDL_SetVideoMode(width, height, 16 /* 32 */, SDL_OPENGL) == 0) { fprintf(stderr, "SDL_SetVideoMode() failed."); exit(1); } ogl::open(); // Turn on alpha blending. glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_PROJECTION); glOrtho(0, 1000, 0, 1000, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); float lod_tweak = 1.0f; // Mouse state. int mouse_x = 0; int mouse_y = 0; int mouse_buttons = 0; bool paused = false; float speed_scale = 1.0f; Uint32 last_ticks = SDL_GetTicks(); for (;;) { Uint32 ticks = SDL_GetTicks(); int delta_ticks = ticks - last_ticks; float delta_t = delta_ticks / 1000.f; last_ticks = ticks; if (paused == true) { delta_t = 0.0f; } // Handle input. SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: { int key = event.key.keysym.sym; if (key == SDLK_q || key == SDLK_ESCAPE) { exit(0); } else if (key == SDLK_k) { lod_tweak = fclamp(lod_tweak + 0.1f, 0.1f, 3.0f); printf("lod_tweak = %f\n", lod_tweak); } else if (key == SDLK_j) { lod_tweak = fclamp(lod_tweak - 0.1f, 0.1f, 3.0f); printf("lod_tweak = %f\n", lod_tweak); } break; } case SDL_MOUSEMOTION: mouse_x = (int) (event.motion.x); mouse_y = (int) (event.motion.y); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { int mask = 1 << (event.button.button); if (event.button.state == SDL_PRESSED) { mouse_buttons |= mask; } else { mouse_buttons &= ~mask; } break; } case SDL_QUIT: exit(0); break; default: break; } } glDisable(GL_DEPTH_TEST); // Disable depth testing. glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); draw_stuff(float(mouse_x), 1000.0f - float(mouse_y), lod_tweak); SDL_GL_SwapBuffers(); SDL_Delay(10); } return 0; }
// S-curve, for enhancing contrast float scurve(float f) { // h2 Hermite basis f = fclamp(f, 0, 1); return -2 * f * f * f + 3 * f * f; }
// Main part of the coding, where everything works (or not) int main(void) { init(); // Main loop while (aptMainLoop()) { // Verify button presses hidScanInput(); // Unsigned variables for different types of button presses u32 kDown = hidKeysDown(); u32 kHeld = hidKeysHeld(); // u32 kUp = hidKeysUp(); // Exit homebrew if (kDown & KEY_START) { break; } // Activate first easter egg else if (kDown & KEY_SELECT) { easterEgg = !easterEgg; } // Change pages for the easterEgg/debug menu. else if (kDown & KEY_R) { if (++easterPage > MAX_PAGE) easterPage = 0; } else if (kDown & KEY_L) { if (--easterPage < 0) easterPage = MAX_PAGE; } timerStep(); // If no movement, set the sprite timer to 0 if (kDown & KEY_UP || kDown & KEY_DOWN || kDown & KEY_LEFT || kDown & KEY_RIGHT) { sprTimer = 0; } // Reset horizontal and vertical speeds vsp = 0; hsp = 0; // Player movement (pretty easy to understand) // TODO: Would it be possible to make this less... iffy? if (kHeld & KEY_UP) { if (!(kHeld & KEY_DOWN)) { vsp = -.5; // Vertical speed to negative .5 playerDir = BACK; // Player direction = back } } if (kHeld & KEY_DOWN) { vsp = .5; // Vertical speed to .5 playerDir = FORWARD; // Player direction = up } if (kHeld & KEY_LEFT) { if (!(kHeld & KEY_RIGHT)) { hsp = -.5; // Vertical speed to negative .5 playerDir = LEFT; // Player direction = left } } if (kHeld & KEY_RIGHT) { hsp = .5; // Vertical speed to .5 playerDir = RIGHT; // Player direction = right } // Diagonal movement speed fix if (vsp != 0) { if (hsp != 0) { vsp *= .8; hsp *= .8; } } // Movement calculation... AND proper room colision. // TODO: Consider a function for translating and/or clamping coordinates directly? player_pos.x = fclamp(player_pos.x + hsp * dt, rooms[room].collision[0].x, rooms[room].collision[1].x); player_pos.y = fclamp(player_pos.y + vsp * dt, rooms[room].collision[0].y, rooms[room].collision[1].y); // Scrolling calculation. // TODO: Make these constants better/customizable. if (player_pos.x - camera_pos.x >= 300) { camera_pos.x = player_pos.x - 300; } else if (player_pos.x - camera_pos.x <= 100) { camera_pos.x = player_pos.x - 100; } camera_pos.x = fclamp(camera_pos.x, 0, rooms[room].scroll_max.x); if (player_pos.y - camera_pos.y >= 200) { camera_pos.y = player_pos.y - 200; } else if (player_pos.y - camera_pos.y <= 50) { camera_pos.y = player_pos.y - 50; } camera_pos.y = fclamp(camera_pos.y, 0, rooms[room].scroll_max.y); // Player sprites if (hsp == 0 && vsp == 0) curr_tex = tex_arr_friskWalk[playerDir][0]; else curr_tex = tex_arr_friskWalk[playerDir][(int)floor(sprTimer)]; // Sprite animation timer // TODO: Why .15 * .03 * actual time? sprTimer += (.03 * dt); while (sprTimer >= 4) { sprTimer -= 4; } if (!next_exit){ if (roomTimer < 255) { roomTimer = fmin(roomTimer + (4 * dt), 255); } next_exit = exit_room(room, &player_pos); } else { roomTimer -= 4 * dt; if (roomTimer <= 0) { room = next_exit->room_id; player_pos = next_exit->entrance; next_exit = NULL; roomTimer = 0; } } render(); // Swap sf2d framebuffers and wait for VBlank sf2d_swapbuffers(); } // Free images/textures/fonts from memory for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { sf2d_free_texture(tex_arr_friskWalk[i][j]); } } for (int i = 0; i < 3; ++i) { sf2d_free_texture(rooms[i].bg.tex); } sftd_free_font(font); // Exit services sf2d_fini(); sftd_fini(); sound_stop(home); audio_stop(); hidExit(); aptExit(); srvExit(); return 0; }
void Update(const UpdateState& u) // Update for the camera. Compute the desired camera location and orientation based // on Motion and Aim modes and parameters. { if (Subject == NULL) return; // // Move the camera. // vec3 DesiredLoc = GetLocation(); bool NoSpeedLimit = false; float FlyFactor = 0; vec3 FlyDir = XAxis; switch (mmode) { default: case FOLLOW: { // Fix the camera position to the subject position. DesiredLoc = Subject->GetLocation(); NoSpeedLimit = true; break; } case CHASE: case FLY: { // Find desired location in relation to subject. vec3 v; Subject->GetMatrix().Apply(&v, ChaseOffset); vec3 tdir = Subject->GetDirection(); tdir.SetY(0); float DirFlatMag = tdir.magnitude(); if (DirFlatMag < 0.2) { tdir = GetDirection(); } else { tdir *= 1.0f / DirFlatMag; } tdir = Geometry::Rotate(ChaseAngle, YAxis, tdir); vec3 tveldir = XAxis /* tdir */; if (DynamicSubject) tveldir = DynamicSubject->GetVelocity(); tveldir.SetY(0); float FlatSpeed = tveldir.magnitude(); if (FlatSpeed < 1.0) { tveldir = GetDirection(); tveldir.SetY(0); tveldir.normalize(); } else { tveldir *= 1.0f / FlatSpeed; } tveldir = Geometry::Rotate(ChaseAngle, YAxis, tveldir); v += tdir * ChaseDirOffset; v += tveldir * ChaseVelDirOffset; v += Geometry::Rotate(ChaseAngle, YAxis, vec3(ChaseFixedDirOffset, 0, 0)); v.SetY(v.Y() + ChaseHeight); DesiredLoc = v; if (mmode == FLY) { // Accelerate towards desired location. vec3 loc = DesiredLoc; vec3 disp = loc - GetLocation(); FlyDir = disp; FlyDir.normalize(); disp.SetY(0); float dist = disp.magnitude(); disp.normalize(); float speed = fmin(10 + dist / 2, 1000.0f); DesiredLoc = GetLocation() + disp * fmin(dist, u.DeltaT * speed /*FlyMaxSpeed*/); FlyFactor = fclamp(0, dist / 50, 1); float c0 = expf(-u.DeltaT / 0.5f); float h = FlyAverageHeight * fclamp(0, sqrtf(dist) / 15, 1); float y = fmax(TerrainModel::GetHeight(DesiredLoc), TerrainModel::GetHeight(DesiredLoc + disp * 2.0f * speed)) + h; y = y * FlyFactor + loc.Y() * (1 - FlyFactor); y = GetLocation().Y() * c0 + y * (1 - c0); DesiredLoc.SetY(y); if (dist < 1) { DoneFlying = true; } } break; } case FIXED: { // Desired location is just where we happen to be right now. break; } } // Take care of actual motion, using speed limit and cut-threshold. vec3 NewLoc = GetLocation(); vec3 disp = DesiredLoc - GetLocation(); float dist = disp.magnitude(); if (NoSpeedLimit || dist > CUT_THRESHOLD_DISTANCE) { // Cut directly to the desired spot. NewLoc = DesiredLoc; } else { // Move towards the desired spot. float limit = CAMERA_MAX_SPEED * u.DeltaT; if (dist > limit) { disp *= (limit / dist); } NewLoc = GetLocation() + disp; } // Prevent camera from poking through the ground surface. if (mmode != FOLLOW) { float y = TerrainModel::GetHeight(NewLoc); y = fmax(y, TerrainModel::GetHeight(NewLoc + XAxis)); y = fmax(y, TerrainModel::GetHeight(NewLoc - XAxis)); y = fmax(y, TerrainModel::GetHeight(NewLoc + ZAxis)); y = fmax(y, TerrainModel::GetHeight(NewLoc - ZAxis)); y += 0.75; if (y > NewLoc.Y()) NewLoc.SetY(y); } SetLocation(NewLoc); // // Aim the camera. // switch (amode) { default: case LOOK_AT: { // Aim at the subject. vec3 dir = Subject->GetLocation() - GetLocation(); dir.normalize(); // Now set the orientation based on desired direction, etc. SetDirection(dir); vec3 right = dir.cross(YAxis); // Roll the right vec3 about DesiredDir...? vec3 up = right.cross(dir); up.normalize(); SetUp(up); break; } case LOOK_THROUGH: { // Use the Subject's view orientation. SetDirection(Subject->GetDirection()); SetUp(Subject->GetUp()); break; } case FIRST_PERSON: { // Align view with subject's velocity, except when the view dir is very different than // vel, in which case align with dir. vec3 dir = Subject->GetDirection(); vec3 vel = dir; float f = 0; MDynamic* d = dynamic_cast<MDynamic*>(Subject); if (d) { vel = d->GetVelocity(); float velmag = vel.magnitude(); vel /= fmax(1.0f, velmag); f = fclamp(0.0f, ((vel * dir) - 0.5f) * 2, 1.0f); } dir = dir * (1 - f) + vel * f; dir.normalize(); vec3 up = (Subject->GetUp() * (1.3f - f) + YAxis * (f + 0.3f)); up = dir.cross(up).cross(dir); up.normalize(); SetDirection(dir); SetUp(up); break; } case FLY_AIM: { // Aim at the subject. vec3 dir = Subject->GetLocation() - GetLocation(); dir.normalize(); // dir = FlyDir * FlyFactor + dir * (1 - FlyFactor); // dir.normalize(); // // Limit turn rate. // float c0 = exp(-u.DeltaT / 0.25); // dir = dir * (1 - c0) + GetDirection() * c0; // dir.normalize(); SetDirection(dir); vec3 right = dir.cross(YAxis); // Roll the right vec3 about DesiredDir...? vec3 up = right.cross(dir); up.normalize(); SetUp(up); break; } } }
int main(int argc, char *argv[]) { print_usage(); // Initialize the SDL subsystems we're using. if (SDL_Init(SDL_INIT_VIDEO /* | SDL_INIT_JOYSTICK | SDL_INIT_CDROM | SDL_INIT_AUDIO*/)) { fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); int width = 1000; int height = 1000; // Set the video mode. if (SDL_SetVideoMode(width, height, 16 /* 32 */, SDL_OPENGL) == 0) { fprintf(stderr, "SDL_SetVideoMode() failed."); exit(1); } ogl::open(); // Turn on alpha blending. glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glMatrixMode(GL_PROJECTION); glOrtho(0, 1000, 0, 1000, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(500, 500, 0); float density = 1.0f; // Add a couple occluders. s_occluders.push_back(occluder(vec3(0,0,0), 20)); s_occluders.push_back(occluder(vec3(100,50,0), 20)); s_occluders.push_back(occluder(vec3(-100,50,0), 20)); // Mouse state. controls c; // int mouse_x = 0; // int mouse_y = 0; // int mouse_buttons = 0; bool paused = false; float speed_scale = 1.0f; Uint32 last_ticks = SDL_GetTicks(); for (;;) { Uint32 ticks = SDL_GetTicks(); int delta_ticks = ticks - last_ticks; float delta_t = delta_ticks / 1000.f; last_ticks = ticks; if (paused == true) { delta_t = 0.0f; } // Handle input. c.m_mouse_left_click = false; c.m_mouse_right_click = false; SDL_Event event; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_KEYDOWN: { int key = event.key.keysym.sym; if (key == SDLK_q || key == SDLK_ESCAPE) { exit(0); } else if (key == SDLK_k) { density = fclamp(density + 0.1f, 0.1f, 3.0f); printf("density = %f\n", density); } else if (key == SDLK_j) { density = fclamp(density - 0.1f, 0.1f, 3.0f); printf("density = %f\n", density); } else if (key == SDLK_LCTRL || key == SDLK_RCTRL) { c.m_ctl = true; } else if (key == SDLK_LSHIFT || key == SDLK_RSHIFT) { c.m_shift = true; } else if (key == SDLK_LALT || key == SDLK_RALT) { c.m_alt = true; } break; } case SDL_KEYUP: { int key = event.key.keysym.sym; if (key == SDLK_LCTRL || key == SDLK_RCTRL) { c.m_ctl = false; } else if (key == SDLK_LSHIFT || key == SDLK_RSHIFT) { c.m_shift = false; } else if (key == SDLK_LALT || key == SDLK_RALT) { c.m_alt = false; } break; } case SDL_MOUSEMOTION: c.m_mouse_x = float((int) (event.motion.x)); c.m_mouse_y = float((int) (event.motion.y)); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { int mask = 1 << (event.button.button); bool down = (event.button.state == SDL_PRESSED); bool clicked = (event.type == SDL_MOUSEBUTTONDOWN); if (event.button.button == 1) { c.m_mouse_left = down; c.m_mouse_left_click = clicked; } if (event.button.button == 3) { c.m_mouse_right = down; c.m_mouse_right_click = clicked; } break; } case SDL_QUIT: exit(0); break; default: break; } } glDisable(GL_DEPTH_TEST); // Disable depth testing. glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT); draw_stuff(c, density); SDL_GL_SwapBuffers(); SDL_Delay(10); } return 0; }