第一节 Getting started
这个例程将告诉你如何把 newton 物理引擎和你的图形引擎结合起来。
如果你没有解过 SDK 包,先解开包。
打开 Visual studio 找到包里的 Tutorials.dsw 后双击。
选择子项目 Tutorial 1 getting started 并使它活动起来。
选择 Tutorial.cpp 文件并双击在编辑框中打开。
在文件的开始你将发现 include 部分。
看下面几行(注意黑体):
#include “newton.h”
#include "tutorial.h"
#include "HiResTimer.h"
#include "RenderPrimitive.h"
#include "Newton.h"
找到文件主要函数。
首先初始化图形引擎。在这个案例中我们已经把 opengl 的初始化压成一个简单的函数。它可以完成你的引擎中主要系统的初始化。
// Initialize opengl
InitOpenGl (argc, argv, "NewtonGetting Started", DrawScene, NULL, Keyboard);
接下来你将看到场景初始化的的相关调用。
// Create the physics scene. This represents your engine scene initialization
InitScene();
最后是 opengl 的主体循环调用,它描述的是你的引擎主循环。
现在找到函数 InitScene , 物理引擎的初始化就在那里。
在这个例程中,我们将实现一个简单的物理场景:一个刚体球悬浮在真空中。
我们将看到:
// Create the newton world
nWorld = NewtonCreate (NULL, NULL);
// 译者注:实际上这之前还需要声明 nWorld ,以下许多地方类似
它将为 nowton 世界创建一个句柄,并初始化所有内部结构。这里我们先忽视两个参数,在下个例程中我们将对之详细说明。我们保持这个指向 nowton 世界的句柄为全程变量。
但是它( nowton 世界)不可能脱离 opengl 循环,所以我们要设定一个事件去终止 nowton 世界和我们已经分配的所有资源。这就是 onexit (Cleanup) 所要做的。
接下来我们要创建一个刚体,在这之前我们要创建它的几何碰撞。(刚体每时每刻都必须有几何碰撞)
所以我们根据图形箱子大小去创建一个碰撞。
// Create the collision shape
collision = NewtonCreateBox (nWorld, box.m_x * 2.0f, box.m_y * 2.0f, box.m_z * 2.0f, NULL);
第一个参数是 Newton world ,接下来的是箱子大小,最后一个参数是用来设置从源刚体而得到的几何碰撞中偏转转换矩阵。当使用 Null 时,这个箱子会被源物体替代。现在我们创建刚体并保存为一个全局变量。
// Create the ridid body
ribidBodyBox = NewtonCreateBody (nWorld, collision);
当你使用完碰撞对象后你要释放它,碰撞对象在 newton 里是唯一一个使用 reference 数的对象,这是有必要的因为其他刚体可以分享几何碰撞。取个例子来说,你可以创建很多个同样大小的箱子,你可以使用同一个几何碰撞。
// Get rid of the collision
NewtonReleaseCollision (nWorld, collision);
当 newton 创建一个刚体,质量设置为无限以保持这个刚体呈静态。我们需要去告诉 newton 这个物体是动态的,就调用下面这个
// set the body mass and inertia
NewtonBodySetMassMatrix (ribidBodyBox, 1.0f, 1.0f, 1.0f, 1.0f);
别去考虑质量与惯性,他们将会在例程 the Dealing with Mass and Inertia 中讨论。
我们同样需要在这个世界中物体的位置。
// Set the transformation matrix 设置变换矩阵
dMatrix matrix (box.GetMatrix());
matrix.m_posit.m_x = 0.0f;
matrix.m_posit.m_y = 1.0f;
matrix.m_posit.m_z = 0.0f;
NewtonBodySetMatrix (ribidBodyBox, &matrix[0][0]);
这里没有应力和应变应用在这个物体上,我们仅仅是应用了最初的角速度 。
// Animate the body by setting the angular velocity 设置角速度使物体动起来
dVector omega (1.0f, 1.0f, 1.0f);
NewtonBodySetOmega (ribidBodyBox, &omega[0]);
// 这里的 NewtonBodySetOmega 中的 Omega 其实是小写希腊字母最后一个—— ω ,即物理中的角速度。
这是所有初始化,现在是主要的仿真循环。
每一帧在 OPENGL 或者你的引擎中都将在主要仿真循环中创建一个回调。在这个例程中,它是函数 DrawScene 。
注意我们需要取得从最后一次更新到现在的时间。它使用下面这个函数。
// get the time step
timeStep = timer.GetElapsedSeconds();
接下来,我们调用 NewtonUpdate 来用时间量推动这个世界。
// update the Newton physics world
NewtonUpdate (nWorld, timeStep);
现在我们需要找到在世界更新的过程中位置改变的物体变换矩阵,在这个例子中我们只有一个物体。
// get the matrix from the rigid body
dMatrix matrix;
NewtonBodyGetMatrix(ribidBodyBox, &matrix[0][0]);
现在我们需要去应用这些转换到图形物体中。
// Set the matrix of the visual body
box.SetMatrix (matrix);
最后我们渲染场景。
// Render the object
glPushMatrix();
box.Render();
glPopMatrix();
这些都包含在主循环中。
最后的事情就是终止应用程序,我们用点击关闭窗体按钮或者按 ESCAPE 键来终止。每个案例都是用 exit(0) 。
这个函数将会调用所有终止程序并次序颠倒的运行。在我们的案例中我们仅仅是使用 cleanup 函数去销毁 the Newton world 。
操作这个例程用 WSAD 键。
改变运动趋势按鼠标并移动鼠标。
例程结束。
从这个例程中我们可以看出,物理引擎的基本操作步骤。
1、 初始化物理引擎。
2、 取得物体的几何碰撞。
3、 根据几何碰撞创建刚体。
4、 释放几何碰撞(很多人会忘记,但很重要)
5、 设置变换矩阵。
6、 更新物理引擎。
7、 取得变换矩阵。
8、 根据取得的变换矩阵设置绘制物体当前状态。
9、 释放物理引擎。