令人信服的 C# 物理学






4.72/5 (16投票s)
2003 年 12 月 27 日
4分钟阅读

103094

1112
如何使用 C# 创建逼真的物理效果。
引言
在阅读了精彩的文章《高级角色物理学》[1] 后,我意识到,与我先前的看法相反,在计算机上创建逼真的物理效果并非极其复杂。事实上,它相当简单,而且对 CPU 的要求也不高。我想这可能会是某些开发人员感兴趣的话题,于是我为 CodeProject 整理了这些项目和这篇文章。
设置
要求
要能够编译和使用这些项目,您需要 DirectX9 的托管扩展[2]。安装 DirectX9 SDK 后,您可能需要执行额外的步骤。请参考 DirectX9 SDK 附带的 readme.txt 文件。ParticleSystem 项目依赖于 DirectX9 进行一些基本的向量和矩阵操作。测试应用程序则更 heavily 依赖 DirectX9,因为它使用 DirectX9 来可视化粒子约束系统。
编译
一旦您有了 DirectX9 的托管扩展,编译这些项目应该会很容易。
运行测试应用程序
您应该会看到一个类似上面图片所示的跳伞盒子。有一些简单的命令可以移动视角以及更改粒子约束系统的一些参数。
- 箭头键:移动视角。
- A:使重力向量指向下方。
- B:使重力向量指向上方。
- S:抖动粒子。
- K:增加风力强度(影响降落伞)。
- L:减小风力强度(影响降落伞)。
测试项目中的代码简直糟糕透顶,我只是对 DirectX9 向导生成的代码进行了足够的修补,以便能够查看粒子约束系统。有趣的代码在 ParticleSystem 项目中。
如何创建简单的粒子约束系统
假设您想创建一个非常简单的系统,其中只有一个小盒子。
// Begin a transaction
ParticleSystem.Transaction lTransaction = ps.GetTransaction();
// Adds a global constraint to the system (to make sure that the box
// doesn't fall and fall and fall)
lTransaction.AddGlobalConstraint(new AxisAlignedBox(
new Vector3(-10, -15, -10),
new Vector3(10, 15, 10)));
// Set the gravity vector of the system
ps.Gravity = new Vector3(0, -1, 0);
// Creates a stick-constraint factory (since we want our box to be created
// using stiff stick-constraints)
Tools.ITwoParticleConstraintFactory lStickConstraintFactory =
new Tools.StickConstraintFactory();
// Create the box at position (0,0,0), with mass 10.0 and side-length 1.0
Tools.CreateBox(
new Vector3(0.0f, 0.0f, 0.0f),
10.0f,
1.0f,
lStickConstraintFactory,
lTransaction);
// Commit the added particles and constraints to the system
lTransaction.Commit();
如果您想测试示例的外观,只需将 InitializeParticleSystem
函数中的代码替换为上面的代码。此外,您还需要添加一行 windEffect = null;
现在,假设您想将一个链条连接到盒子和一个不动的粒子上。代码将如下所示:
// Begin a transaction
ParticleSystem.Transaction lTransaction = ps.GetTransaction();
// Adds a global constraint to the system (to make sure that the box
// doesn't fall and fall and fall)
lTransaction.AddGlobalConstraint(new AxisAlignedBox(
new Vector3(-10, -15, -10),
new Vector3(10, 15, 10)));
// Set the gravity vector of the system
ps.Gravity = new Vector3(0, -1, 0);
// Creates a stick-constraint factory (since we want our box to be created
// using stiff stick-constraints)
Tools.ITwoParticleConstraintFactory lStickConstraintFactory =
new Tools.StickConstraintFactory();
// Create the box at position (0,0,0), with mass 10.0 and side-length 1.0
Particle[] lBoxParticles = Tools.CreateBox(
new Vector3(0.0f, 0.0f, 0.0f),
10.0f,
1.0f,
lStickConstraintFactory,
lTransaction);
// Create a single particle
Particle lParticle = new Particle(1.0f, new Vector3(0.0f, 5.0f, 0.0f));
// Make the particle non-moving
lParticle.Immoveable = true;
// Add the particle the system
lTransaction.AddParticle(lParticle);
// Create a chain between the single particle and a box-particle
Tools.CreateChain(
lParticle,
lBoxParticles[0],
1.0f,
6,
lStickConstraintFactory,
lTransaction);
// Commit the added particles and constraints to the system
lTransaction.Commit();
有关更复杂的示例,请参阅 ParticleSystemTestApplication 中的跳伞盒子代码。
ParticleSystem 项目简介
- 该项目名为 ParticleSystem。一个更好的名字可能是 ParticleConstraintSystem,因为本质上它就是这样的。
- ParticleSystem 的设计目标主要是为了让开发人员能够轻松地添加新的约束、效果和全局约束类。此外,我还想让创建“实验”变得相对容易。性能并不是首要考虑因素。
- 您通过
Transaction
对象向ParticleSystem
添加粒子、约束、效果和全局约束的实例。您可以通过调用ParticleSystem
实例上的GetTransaction()
来获取Transaction
对象的实例。请记住提交。 - 要生成下一帧,请调用
TimeStep()
。 - 您可以通过实现所需接口来创建自己的约束、效果和全局约束。例如,要创建约束,对象必须实现
IConstraint
,它只有一个方法:Apply()
。 - 一个合理的问题是,当一个约束对象收到
Apply()
调用时应该做什么?它应该检查约束是否无效。如果无效,那么它应该移动构成约束的粒子,直到约束再次有效。例如,以StickConstraint
为例;如果粒子之间的距离太远,它会拉近它们,直到它们达到正确的距离。如果它们太近,它会推开它们,直到它们达到正确的距离。它还会考虑粒子的质量,并根据它们的重量移动不同。请参阅《高级角色物理学》[1] 以更深入地了解如何创建约束。 Tool
类包含许多静态方法,旨在方便开发人员。
面向读者的练习
这当然是对学生文学中常见的“面向读者的练习”的一种讽刺式的暗示。
- 实现一个“真正的”降落伞。降落伞中的粒子不再受向上风力的固定影响,而是可能受到取决于降落伞粒子平均速度的风的影响。也就是说,它们向下运动的速度越快,向上吹的风力就越强。
- 实现一个帆船游戏。
待办事项
- 添加 NUnit 测试
- 改进文档并提供 NDoc 项目
- 将重力重新设计为
IEffect
,而不是ParticleSystem
类的一个内在部分。这样就可以允许具有重力中心或多个重力源的系统。 - 实现粒子与三角形之间的碰撞检测。这将能够实现一些非常酷的功能,例如:实体之间的反弹、蹦床和摩擦。
致谢
Thomas Jakobsen - 因为如果没有他出色的文章[1],我怀疑我是否会开始玩弄虚拟粒子和约束(从而过着一种不那么充实的生活)。此外,在构建 ParticleSystem 时,我无耻地借鉴了他的文章中的代码。
参考文献
- [1] 高级角色物理学。
- [2] DirectX 9.0 SDK 更新 - (2003 年夏季)。
变更历史
- 2003-12-27 - 文章发布。
- 2003-12-27 - 添加了“更改历史”部分。
- 2003-12-27 - 删除了“关于作者”部分。
- 2003-12-30 - 更新了源代码和二进制文件