65.9K
CodeProject 正在变化。 阅读更多。
Home

令人信服的 C# 物理学

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.72/5 (16投票s)

2003 年 12 月 27 日

4分钟阅读

viewsIcon

103094

downloadIcon

1112

如何使用 C# 创建逼真的物理效果。

Sample Image - parachute.jpg

引言

在阅读了精彩的文章《高级角色物理学》[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 时,我无耻地借鉴了他的文章中的代码。

参考文献

变更历史

  • 2003-12-27 - 文章发布。
  • 2003-12-27 - 添加了“更改历史”部分。
  • 2003-12-27 - 删除了“关于作者”部分。
  • 2003-12-30 - 更新了源代码和二进制文件 
© . All rights reserved.