自己动手写2D物理引擎-初级篇(1)

第一章 框架设计

总体的类如下图所表示。
在这里插入图片描述
Shape作为形状基类。存储了与形状有关的物理量

class Shape
{
public:
	float I = 0.0f, invI = 0.0f;//转动惯量和逆
};

Rectangle和Circle派生于Shape,存储了实际的形状信息。

class Rectangle :public Shape
{
public:
	//存储矩形的长宽
	agl::vec2f r;
};

class Circle :public Shape
{
public:
	float r;
};

PhyAttr中存放的是各种物理属性,这些属性是不限于任何物体都有的属性。

namespace phy2d
{
	class PhyAttr
	{
	public:
		PhyAttr()
		{
			velocity = agl::vec2f(0.0f);
			position = agl::vec2f(0.0f);
			force = agl::vec2f(0.0f);
		}
		agl::vec2f velocity;//速度
		agl::vec2f position;//位置
		float rotation = 0.0f;//旋转角度
		float angularVelocity = 0.0f;//角速度
		agl::vec2f force;//力
		float torque = 0.0f;//转矩
		float friction = 0.0f;//摩擦力
		float mass = 0.0f, invMass = 0.0f;//质量和逆
		~PhyAttr() {}
	};
};

PhyObj是PhyRect与PhyCircle的父类,其主要作用是做为基类指针,支持动态类型使用,分别继承了形状和物理特性,组成了有物理特性的形状。

namespace phy2d
{
	class PhyObj {};
	class PhyRect :public PhyObj,public Rectangle, public PhyAttr
	{
	public:
	};

	class PhyCircle :public PhyObj, public Circle, public PhyAttr
	{
	public:
	};
};

World中负责整个物理世界的运行,存储物体和碰撞信息。协调整个物理引擎的流程。

namespace phy2d
{
	class World
	{
		//存储物体
		std::vector<PhyObj*> objects;
		//存储碰撞信息
		std::unordered_map<std::tuple<PhyObj*, PhyObj*>, Contact> collisions;
	public:
	};
}

Contact是存储碰撞信息的结构体,Impulse是存储冲量的,因为我们要实现冲量累积方法,所以碰撞信息中保留上一次的冲量信息。Driver是存储两个物体指针和其碰撞信息的结构体,这个结构是存放碰撞后结果的直接结构体,并且其中要有计算两个物体冲量变化的能力。

namespace phy2d
{
	class Impulse
	{
	public:
		//正面和侧面的动量
		float ImpulseNormal;
		float ImpulseSide;
	};
	//碰撞信息
	class Contact
	{
	public:
		Contact() {}
		agl::vec2f position;//碰撞点位置
		agl::vec2f normal;//分离轴方向
		//agl::vec2f r1, r2;//半径//现场算
		float separation;//最小相交距离
	};

	class Driver
	{
	public:
		//碰撞信息列表
		std::vector<Contact> contacts;
		//碰撞物体
		PhyObj *a, *b;
		//运动执行函数
		void ApplyImpulse()
		{
			//计算好必要的值

			//由于之前的冲量计算是在连个形状相交情况下计算,
			//所以一旦两个物体分开,计算将不会连续
			//循环迭代
		}
	};
}

还有一些数学计算,向量计算的类,这些类可以自己写,也可以用现成的比如GLM,这里就使用自己写的向量矩阵计算库了。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一个完整的2D物理引擎需要涉及到很多知识,包括数学、物理等方面。以下是一个简单的物理引擎实现的代码,可以作为参考。 ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define GRAVITY 9.8f // 重力加速度 #define DELTA_T 0.01f // 时间间隔 typedef struct { float x; // x轴坐标 float y; // y轴坐标 float vx; // x轴速度 float vy; // y轴速度 float ax; // x轴加速度 float ay; // y轴加速度 float mass; // 物体质量 float radius; // 物体半径 } Circle; // 计算两个物体之间的距离 float distance(Circle c1, Circle c2) { float dx = c1.x - c2.x; float dy = c1.y - c2.y; return sqrt(dx * dx + dy * dy); } // 计算两个物体之间的碰撞 void collide(Circle *c1, Circle *c2) { float dx = c1->x - c2->x; float dy = c1->y - c2->y; float d = sqrt(dx * dx + dy * dy); float nx = dx / d; float ny = dy / d; float tx = -ny; float ty = nx; float dpTan1 = c1->vx * tx + c1->vy * ty; float dpTan2 = c2->vx * tx + c2->vy * ty; float dpNorm1 = c1->vx * nx + c1->vy * ny; float dpNorm2 = c2->vx * nx + c2->vy * ny; float m1 = (dpNorm1 * (c1->mass - c2->mass) + 2.0f * c2->mass * dpNorm2) / (c1->mass + c2->mass); float m2 = (dpNorm2 * (c2->mass - c1->mass) + 2.0f * c1->mass * dpNorm1) / (c1->mass + c2->mass); c1->vx = tx * dpTan1 + nx * m1; c1->vy = ty * dpTan1 + ny * m1; c2->vx = tx * dpTan2 + nx * m2; c2->vy = ty * dpTan2 + ny * m2; } // 更新物体的位置和速度 void update(Circle *c) { c->vx += c->ax * DELTA_T; c->vy += c->ay * DELTA_T; c->x += c->vx * DELTA_T; c->y += c->vy * DELTA_T; c->ax = 0.0f; c->ay = -GRAVITY; } int main() { Circle c1 = {0, 0, 0, 0, 0, 0, 1, 1}; Circle c2 = {3, 0, 0, 0, 0, 0, 1, 1}; Circle c3 = {0, 3, 0, 0, 0, 0, 1, 1}; Circle c4 = {3, 3, 0, 0, 0, 0, 1, 1}; Circle *circles[] = {&c1, &c2, &c3, &c4}; int numCircles = sizeof(circles) / sizeof(Circle*); int i, j; for (i = 0; i < numCircles; i++) { for (j = i + 1; j < numCircles; j++) { float d = distance(*circles[i], *circles[j]); if (d < circles[i]->radius + circles[j]->radius) { collide(circles[i], circles[j]); } } } for (i = 0; i < numCircles; i++) { update(circles[i]); printf("circle %d: (%f, %f)\n", i, circles[i]->x, circles[i]->y); } return 0; } ``` 这个物理引擎实现了圆形物体的运动和碰撞。在主函数中,定义了四个圆形物体,并对它们进行了初始化。然后,计算了所有物体之间的距离,并在物体之间发生碰撞时,调用了碰撞函数。最后,更新了所有物体的位置和速度,并输出了它们的坐标。这个物理引擎只是一个简单的示例,需要根据具体需求进行修改和完善。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值