开源的物理引擎

物理引擎是用于创建虚拟环境的模拟器,该虚拟环境融合了来自物理世界的定律。 除了对象之间的相互作用(例如,碰撞)之外,该虚拟环境还可以包括具有附加作用力(例如重力)的对象。 物理引擎在模拟的环境中模拟牛顿物理学,并管理这些力和相互作用。

物理引擎最受欢迎的应用之一是娱乐和游戏行业(请参见图1 ),其中物理引擎提供了游戏环境(包括玩家和可能存在的其他对象)的实时仿真。 在游戏中使用之前,物理学引擎在科学领域中发现了许多应用,从天体的大规模模拟到天气模拟,一直到小规模模拟,以可视化纳米粒子及其相关行为的可视化。军队。

图1.游戏应用程序环境中的物理引擎
该图显示了物理引擎如何与诸如图形引擎,声音等其他元素相关联地进入游戏循环。

这些应用程序之间的主要区别之一是,尽管以游戏为重点的物理引擎专注于实时逼近,但科学多样性却更多地专注于精确计算以提高准确性。 科学物理引擎可以依靠超级计算机来获得原始处理能力,其中游戏物理引擎可以在资源受限得多的平台(例如手持游戏设备和移动电话)上运行。 游戏物理引擎通过避免诸如布朗运动之类的事情来缩减仿真的规模,从而降低了仿真的处理复杂性。 内置到这些发动机的数学和物理概念的范围是本文的范围之外,但你可以找到链接到更多信息相关主题

根据要求,存在许多类型的游戏物理,尽管它们都是同一主题的变体。 在游戏中,您可以找到布娃娃物理 (模拟复杂的铰接系统的行为)和粒子系统 (模拟许多小粒子和大粒子响应爆炸等事件的行为)。 ENIAC计算机是最早的软件物理引擎之一,用于给定质量,角度,推进力和风等变量来模拟炮弹。 Wikipedia提供了对此应用程序的有趣介绍-请参阅参考资料中的链接。

开源选项

物理引擎(尤其是实时性和低精度的变化)的主要用途之一是开发游戏运行时间。 基于这些软件框架的流行,有许多开源选项可供选择。 本文探讨了一些可用的开源物理引擎,并说明了它们在简单应用程序中的使用。

Box2D

Box2D是具有广泛用途的简单物理引擎。 它最初是由Erin Catto设计的,作为2006年游戏开发者大会上进行的物理演示的演示引擎。Box2D最初称为Box2D Lite ,但除了包括连续碰撞检测之外,该引擎还进行了扩展以增强API。 Box2D用C++编写,其可移植性通过使用它的平台(Adobe®Flash®,Apple iPhone和iPad,Nintendo DS和Wii以及Google Android)得到了证明。 Box2D提供了许多流行的掌上游戏背后的物理功能,其中包括《 愤怒的小鸟》和《 蜡笔物理豪华版》。

Box2D提供了一个刚体模拟,支持诸如圆形或多边形的几何形状。 Box2D可以使用关节来连接形状,甚至包括关节电机和滑轮。 在Box2D中,引擎可以施加重力和摩擦力,同时管理对碰撞的检测以及由此产生的动力学。

Box2D被定义为提供各种服务的丰富API。 这些服务允许定义一个由许多对象和属性组成的世界。 定义了对象和属性后,接下来您将以离散的时间步长模拟世界。 该示例应用程序(基于Erin Catto的示例应用程序)探索了一个用重力投掷到世界的盒子。

Box2D示例

清单1说明了创建一个简单的世界的过程,该世界由一个盒子(在向上的动量中)和一个地平面占据。 您可以使用引力和世界函数定义世界和世界的引力矢量。 世界的true参数只是说它是一个睡觉的身体,因此不需要模拟。

定义世界后,您可以指定该世界内的地面物体及其位置。 地面是Box2D知道的静态盒子,因为盒子的质量为零(默认情况下),因此不会与其他对象碰撞。

接下来,创建具有位置,初始线速度和角度的动态物体。 此设置与地面物体的创建类似,不同之处在于您为动态物体定义了其他属性。 这些属性包括物体的密度和摩擦力。 通过使用CreateFixture创建装置将新的动态物体添加到世界中。

定义好世界及其对象后,您可以继续进行仿真。 首先定义模拟的时间步长(在这种情况下为60Hz)。 您还定义了要运行的迭代次数,该迭代次数决定了对速度和位置计算进行迭代的次数(因为求解一个会修改另一个)。 迭代次数越多,获得的精度就越高,并且在计算上花费的时间也就越多。

最后,您运行模拟,这涉及通过调用世界的Step方法来执行模拟中的Step 。 调用返回当前时间步后,您将从最后一步清除施加到对象的力,然后获得动态物体的当前位置和角度。 这些返回的变量将被发送到标准输出(stdout)进行查看。 您可以继续进行仿真,直到您的动态身体休息(即睡觉)为止。

清单1.使用Box2D的简单应用程序(改编自Erin Catto的HelloWorld)
#include <Box2D/Box2D.h>

#include <cstdio>

int main()
{
	// Define the gravity vector.
	b2Vec2 gravity(0.0f, -10.0f);

	// Construct a world object, which will hold and simulate the rigid bodies.
	// Allow bodies to sleep.
	b2World world(gravity, true);

	// Define the ground body.
	b2BodyDef groundBodyDef;
	groundBodyDef.position.Set(0.0f, -10.0f);
	b2Body* groundBody = world.CreateBody(&groundBodyDef);

	// Define the ground box shape.
	b2PolygonShape groundBox;
	groundBox.SetAsBox(50.0f, 10.0f);

	// Add the ground fixture to the ground body.
	groundBody->CreateFixture(&groundBox, 0.0f);

	// Define the dynamic body. Set its position and call the body factory.
	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;
	bodyDef.position.Set(0.0f, 4.0f);
	bodyDef.linearVelocity.Set(5.0f, 5.0f);
	bodyDef.angle = 0.25f * b2_pi;

	b2Body* body = world.CreateBody(&bodyDef);

	// Define another box shape for your dynamic body.
	b2PolygonShape dynamicBox;
	dynamicBox.SetAsBox(1.0f, 1.0f);

	// Define the dynamic body fixture.
	b2FixtureDef fixtureDef;
	fixtureDef.shape = &dynamicBox;
	fixtureDef.density = 1.0f;
	fixtureDef.friction = 0.3f;

	// Add the shape to the body.
	body->CreateFixture(&fixtureDef);

	float32 timeStep = 1.0f / 60.0f;
	int32 velocityIterations = 6;
	int32 positionIterations = 2;

	do {
		world.Step(timeStep, velocityIterations, positionIterations);

		world.ClearForces();

		b2Vec2 position = body->GetPosition();
		float32 angle = body->GetAngle();

		printf("%4.2f %4.2f %4.2f\n", position.x, position.y, angle);

	} while (body->IsAwake());

	return 0;
}

Box2D旨在与渲染器无关(图形可视化)。 图2显示了框位置的简单渲染(来自清单1 )。 请注意,盒子在重力作用下将其拉到地面,静止并发生碰撞的位置行为。

图2.清单1中框位置的简单呈现
该图显示了跟踪x,y坐标的曲线。它显示了升力,下降,然后有小弹跳。

子弹

Bullet是3D开源物理引擎,它支持刚体和软体动力学以及3D中的碰撞检测。 Bullet由Erwin Coumans在索尼计算机娱乐公司期间开发。 许多平台都支持该引擎,例如Sony Playstation 3,Xbox360®,iPhone和Wii。 它包括对Windows®,Linux®和Mac OS的操作系统支持,以及针对Playstation 3中的单元协同处理单元和PC上的OpenCL框架的许多优化。

Bullet是一种生产物理引擎,在游戏和电影中均得到广泛支持。 一些使用Bullet的游戏包括Rockstar的Red Dead Redemption和Sony的Free Realms (MMORPG)。 Bullet还被用于许多商业电影的特殊效果,包括“ The A-team”(Weta Digital)和“ Shrek 4”(DreamWorks)。

Bullet包括具有离散和连续碰撞检测功能的刚体模拟,包括对软体(如布料或其他可变形物体)的支持。 作为生产引擎,Bullet包含丰富的API和SDK。

项目符号示例

清单2中显示的Bullet示例是Bullet发行版中的“ Hello World”程序。 它实现了与Box2D示例中演示的模拟类似的模拟(但在这种情况下,使用球体代替下落的对象而不是盒子)。 如您所料,由于API的丰富性和多样性增加,因此此实现比以前的示例要复杂得多。

该示例应用程序分为三个部分:设置,模拟和清除。 设置阶段创建了仿真阶段可以使用的环境。 清理阶段只是重新分配世界上的各种对象。

要创建世界,您需要定义一个广相算法(一种用于识别不应碰撞的对象的优化方法),一个碰撞配置和一个约束求解器(其中包括重力和其他力以及碰撞并定义对象的方式)相互作用)。 您还可以通过调用setGravity将重力定义为y轴。 通过定义这些元素,您可以创建自己的世界。 设置阶段的后两个部分定义了静态地面物体和动态球体。

通过调用方法stepSimulation执行仿真。 该方法定义了60Hz的间隔,并模拟了在重力作用下落到地面的球体后面的物理过程。 在每个模拟步骤之后,都会发射球体的高度( y参数)。 遍历模拟过程可使球体与地面碰撞,然后停下来。

最后阶段是简单的清理,它将对象和其他元素从内存中释放出来。

如图所示,尽管模拟需要大量的设置,但是一旦您定义了模拟环境,引擎就会为您完成所有繁重的工作。 Bullet包含一个庞大的API,可以对环境及其行为进行微调,还可以对模拟中发生的事件(例如冲突和重叠)进行大量回调。

清单2.使用Bullet进行简单的落球模拟
#include <iostream>
 
#include <btBulletDynamicsCommon.h>
 
int main (void)
{

  // Setup
 
  btBroadphaseInterface* broadphase = new btDbvtBroadphase();
 
  btDefaultCollisionConfiguration* collisionConfiguration = 
					new btDefaultCollisionConfiguration();
  btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
 
  btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
 
  btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(
				dispatcher,broadphase,solver,collisionConfiguration);
 
  dynamicsWorld->setGravity(btVector3(0,-10,0));
 
 
  btCollisionShape* groundShape = new btStaticPlaneShape(btVector3(0,1,0),1);
 
  btCollisionShape* fallShape = new btSphereShape(1);
 
 
  btDefaultMotionState* groundMotionState = new 
	btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,-1,0)));
  btRigidBody::btRigidBodyConstructionInfo
                groundRigidBodyCI(0,groundMotionState,groundShape,btVector3(0,0,0));
  btRigidBody* groundRigidBody = new btRigidBody(groundRigidBodyCI);
  dynamicsWorld->addRigidBody(groundRigidBody);

 
  btDefaultMotionState* fallMotionState =
       new btDefaultMotionState(btTransform(btQuaternion(0,0,0,1),btVector3(0,50,0)));
  btScalar mass = 1;
  btVector3 fallInertia(0,0,0);
  fallShape->calculateLocalInertia(mass,fallInertia);
  btRigidBody::btRigidBodyConstructionInfo 
		fallRigidBodyCI(mass,fallMotionState,fallShape,fallInertia);
  btRigidBody* fallRigidBody = new btRigidBody(fallRigidBodyCI);
  dynamicsWorld->addRigidBody(fallRigidBody);
 
  // Simulation
 
  for (int i=0 ; i<300 ; i++) {
    dynamicsWorld->stepSimulation(1/60.f,10);

    btTransform trans;
    fallRigidBody->getMotionState()->getWorldTransform(trans);

    std::cout << "sphere height: " << trans.getOrigin().getY() << std::endl;
  }

  // Cleanup
 
  dynamicsWorld->removeRigidBody(fallRigidBody);
  delete fallRigidBody->getMotionState();
  delete fallRigidBody;
 
  dynamicsWorld->removeRigidBody(groundRigidBody);
  delete groundRigidBody->getMotionState();
  delete groundRigidBody;
 
  delete fallShape;
 
  delete groundShape;
 
  delete dynamicsWorld;
  delete solver;
  delete collisionConfiguration;
  delete dispatcher;
  delete broadphase;
 
  return 0;
}

开源物理引擎列表

Box2D和Bullet是有用且广泛使用的物理引擎的两个示例。 但是,除了使用许多不同的许可证外,还有许多其他实例专注于物理模拟的不同方面(性能或准确性)。 Box2D和Bullet都使用Zlib许可证(支持在商业应用程序中使用它们)。 表1列出了一些更常见的开源物理引擎以及它们使用的许可证。 此外,尽管大多数引擎都支持C++C ,但许多引擎还支持与其他语言的绑定,例如Ruby或Python。

表1.开源物理引擎
发动机 类型 执照
Box2D 2D Zlib
子弹 3D Zlib
花栗鼠 2D 麻省理工学院(MIT)
计时::引擎 3D GPLv3
发电机 3D GPL
Moby(Physsim) 3D GPLv2
牛顿游戏动力学 3D Zlib
开放动力引擎 3D BSD
开放式物理抽象层 不适用 BSD / LGPL
开放式组织 3D Zlib
物理抽象层(PAL) 不适用 BSD
托卡马克 3D BSD / Zlib

由斯科特·莱姆贝克(Scott Lembcke)基于Box2D开发的花栗鼠(Chipmunk)包括2D物理的多项功能,包括直接支持C以及支持iPhone绑定的Objective-Chipmunk。 其他绑定包括Ruby,Python和Haskell。

Tokamak是David Lam用C++编写的3D物理引擎SDK。 它包括许多优化措施,可以最大程度地减少内存带宽,因此使其非常适合小型便携式设备。 Tokamak的一项有趣功能是支持模型破坏,其中复合对象可以在碰撞时破坏,然后在仿真中创建多个对象。

尽管在物理引擎下列出了这些抽象层,但它们提供了一种有趣的功能,不应忽略。 PAL在单个应用程序中的多个物理引擎上提供了统一的接口,这使开发人员可以轻松地为特定应用程序使用正确的物理引擎,而无需进行移植工作。 PAL的插件体系结构支持几种领先的开源物理引擎,例如Box2D,Bullet,Newton Game Dynamics,OpenTissue,Tokakak等。 它还支持诸如游戏开发中流行的Havok之类的商业物理引擎。 PAL的缺点是它可以限制特定物理引擎提供的功能,因为它的重点是通用抽象。

硬件加速

随着图形处理单元(GPU)的发展趋势,物理上的硬件加速在过去几年中不断发展。 GPU是一种硬件协处理器,可以加速计算机图形应用程序的计算。 GPU已发展成为图形处理单元(GPGPU)上的通用计算,可将其用于更通用的加速任务中。 物理处理单元(PPU)加速物理引擎计算的运动可能已被使用更多可访问的GPGPU转移了。 GPGPU的示例包括ATI的Stream技术和NVIDIA的通用统一设备架构(CUDA)架构。

更进一步

物理引擎使您不必开发复杂的软件即可在软件中实现物理和碰撞检测。 相反,您可以将时间投入到特定的应用程序(游戏或模拟)中。 尽管它有助于理解这些引擎背后的数学原理,但是并不需要使用和享受它们。 “ 相关主题”部分包含指向许多开放源代码物理引擎的链接,这些引擎可在Linux和Windows系统上轻松使用。 每个示例都包括示例性演示示例,以帮助您了解其API和概念,从而可以将物理技术引入您的应用程序。


翻译自: https://www.ibm.com/developerworks/opensource/library/os-physicsengines/index.html

开源的物理引擎

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐