Ejemplo n.º 1
0
	// 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 );
	}
Ejemplo n.º 2
0
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));
}
Ejemplo n.º 3
0
	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;
	}
Ejemplo n.º 4
0
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);
  }
Ejemplo n.º 5
0
	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
			}
		}
	}
Ejemplo n.º 6
0
	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);
	}
Ejemplo n.º 8
0
	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;
	}
Ejemplo n.º 9
0
	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;
	}
Ejemplo n.º 10
0
//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";
	}

}
Ejemplo n.º 11
0
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);
    }


}
Ejemplo n.º 12
0
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;
}
Ejemplo n.º 13
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;
}
Ejemplo n.º 14
0
// 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;
}
Ejemplo n.º 15
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;
		}
		}
	}
Ejemplo n.º 16
0
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;
}