假设箱子只受重力。
#include <windows.h>
#include <gl/Gl.h>
#include <gl/Glu.h>
#include <gl/glut.h>
#include "math.h"
#include "vector2.h"
#pragma comment(lib, "glut.lib")
const int windowWidth = 800;
const int windowHeight = 600;
const double rads_per_deg = 0.01745; //度换算成弧度
const double pixels_per_meter = 10; //米换算成像素
const double g = 9.81; //重力加速度 9,81 m/s^2
double theta = 30; //坡度
double mass = 1; //箱子的重量,1kg
bool simulation_over = false; //箱子移动是否结束
double box_pos = 0; //箱子的位置
double box_vel = 0; //箱子的速度
Vector2 force_grav; //箱子所受重力
LARGE_INTEGER clock_freq;
LARGE_INTEGER last_time;
void myDisplay(void)
{
glClear(GL_COLOR_BUFFER_BIT); //清屏
glColor3f( 1, 1, 1 );
//箱子所受重力
force_grav.x = mass * g * sin( theta * rads_per_deg );
force_grav.y = -mass * g * cos( theta * rads_per_deg );
LARGE_INTEGER i;
QueryPerformanceCounter( &i );
double elapsed_time = double( i.QuadPart - last_time.QuadPart ) / clock_freq.QuadPart;
last_time = i;
if(! simulation_over )
{
//F = ma -> a = F/m
double acc = force_grav.x / mass; //加速度
box_vel += ( acc * elapsed_time ); //速度
box_pos += ( box_vel * pixels_per_meter ) * elapsed_time; //位置
}
if( box_pos >= 600 )
{
simulation_over = true;
}
//地面
glBegin( GL_LINES );
glVertex2i( 700, 100 );
glVertex2i( 100, 100 );
glEnd();
double dw = 600; //斜面,原始位置为(700,100)
glPushMatrix();
//原点
glTranslatef( 700, 100, 0 );
glRotatef( -theta, 0, 0, 1);
//斜坡
glBegin( GL_LINES );
glVertex2i( 0, 0 );
glVertex2i( -dw, 0 );
glEnd();
//箱子的位置
glTranslatef( box_pos-dw, 50, 0 );
//箱子
glBegin( GL_LINE_LOOP );
glVertex2i( -50, 50 );
glVertex2i( 50, 50 );
glVertex2i( 50, -50 );
glVertex2i( -50, -50 );
glEnd();
glPopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
void myInit()
{
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluOrtho2D( 0, windowWidth, 0, windowHeight );
glClearColor(0, 0, 0, 0); //背景颜色是黑色
glViewport(0, 0, windowWidth, windowHeight);
}
int main(int argc, char *argv[])
{
if( QueryPerformanceFrequency( &clock_freq ) )
{
QueryPerformanceCounter( &last_time );
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(50, 50);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("DEMO");
myInit();
glutDisplayFunc(myDisplay);
}
glutMainLoop();
return 0;
}
vector2.h
#ifndef _Vector2_H
#define _Vector2_H
#include <cmath>
#include <iostream>
using namespace std;
class Vector2
{
public:
// vars
float x, y;
// constructors
Vector2() {}
Vector2( float x1, float y1 ) : x(x1), y(y1) {}
// vector ops
void normalize()
{
float temp = 1 / length();
x *= temp;
y *= temp;
}
inline double length() const
{
return( sqrt((x * x) + (y * y)) );
}
Vector2 perp() const
{
return( Vector2( y, -x ) );
}
// operators
Vector2 operator + ( const Vector2 & rhs ) const
{
return( Vector2(x + rhs.x, y + rhs.y) );
}
Vector2 operator - ( const Vector2 & rhs ) const
{
return( Vector2( x - rhs.x, y - rhs.y ) );
}
Vector2 operator / ( float k ) const
{
return( Vector2(x / k, y / k) );
}
float operator * ( const Vector2 & rhs ) const
{
// dot product
return( (x * rhs.x) + (y * rhs.y) );
}
Vector2 operator * ( const float & rhs ) const
{
// scale by scalar
return( Vector2( x * rhs, y * rhs ) );
}
bool operator == ( const Vector2 & rhs )
{
return( rhs.x == x && rhs.y == y );
}
friend Vector2 operator * ( const float & lhs, const Vector2 & rhs )
{
// scale by scalar
return( Vector2( rhs.x * lhs, rhs.y * lhs ) );
}
friend istream & operator >> ( istream & i, Vector2 & v )
{
i >> v.x >> v.y;
return( i );
}
friend ostream & operator << ( ostream & o, Vector2 & v )
{
o << v.x << " " << v.y;
return( o );
}
}; // end class
#endif // _Vector2_H