ogrenewt初学者教程

118 篇文章 4 订阅
6 篇文章 0 订阅

From Ogre Wiki
Using Ogre with the Newton Game Dynamics physics SDK
by Walaber
内容
• 1 介绍 
• 2 开始 
• 3 Newton SDK 
• 4 The Newton World 

介绍
这个教程意在解释如何用Ogre version 1.0.0和Newton Game Dynamics physics SDK version 1.31建立一个简单的程序。
要求:
1. 需要安装Ogre 1.1.x (Dagon),可正常编译和运行。如果你是安装的.0.x of Ogre,这个教程也可以适用,但是需要做少量修改。
2. 需要安装Newton。如果没有,去http://www.newtondynamics.com 网站下载一个sdk即可,该软件是免费的。
3. 最后还需要安装我编写的 "OgreNewt" 库来连接Ogre和Newton。OgreNewt 在Ogre CVS 的ogre插件部分可以找到,也可以在我的网站walaber.com下载。. 本教程我将解释一些Newton的基础以及OgreNewt如何实现。
________________________________________
译注:一些OgreNewt Demo的截图

 

 

 

 

开始
首先我们要作的是编译OgreNewt,令它运行。假设你的目录如下:
<some_dir>/OGRE/ogrenew                <- ogre 安装目录
<some_dir>/OGRE/ogreaddons/OgreNewt/   <- OgreNewt 安装目录
<some_dir>/NewtonSDK                   <- Newton SDK 安装目录
<some_dir>/tinyxml                        <- Tinyxml库 (只在 demo08用到, OgreNewt自身不需要用)

如果你的目录不同,在工程里修改为你自己的目录就可以了。
Okay, 打开 VC++, 加载 "OgreNewt" solution. 你将可以看到9个工程:
1. OgreNewt_Main – 这是OgreNewt的库,在这个文件中定义了所有的类。
2. Demo01_TheBasics – 一个非常简单的demo,你可以用一个物体扔令一个物体,看到碰撞效果。
3. Demo02_Joints – 令一个简单demo,可以看到TreeCollison效果和简单的连接。
4. Demo03_CollisionCallbacks – 高级碰撞。通过Callbacks来模拟传送带上的物体行为。
5. Demo04_Raycasting – 对固体使用Raycasting。
6. Demo05_SimpleVehicle – 如何使用Newton的汽车系统
7. Demo06_SimpleBuoyancy – 如何使用 Newton 的浮力系统
8. Demo07_CustomJoints – 一个简单的教你如何用OgreNewt创建自己的关节的例子。
9. Demo08_RagdollExample – 使用ragdoll。
如果你的目录结构如上所示,那么编译应该没有问题。Demo08需要tinyxml才可以编译。
可执行文件在 "OgreNewt/Bin/Debug" 或者 "OgreNewt/Bin/Release" 目录中。拷贝Ogre的.dll文件和newton的.dll文件到该文件夹,试下执行吧!
DEMO 的控制:
1. MOUSE:摄像机
2. ARROW KEYS:运动
3. SPACE BAR:扔物体
4. ESC:退出.
Okay... 实现让我们来创建我们的Application类。创建一个新工程并且添加一个头文件,命名为"OgreNewtApplication.h"。添加如下代码。

//OgreNewtApplication.h
#ifndef _OGRENEWTAPPLICATION_
#define _OGRENEWTAPPLICATION_

#include "ExampleApplication.h"

class OgreNewtApplication :
 public ExampleApplication
{
public:
 OgreNewtApplication(void);
 ~OgreNewtApplication(void);

 void createScene();

 void createFrameListener(void);
};
看起来眼熟吧,这只是继承了Ogre的ExampleApplication类。首先在工程中包含下面的目录:
Include目录:
ogrenew/ogremain/include
ogrenew/samples/common/include
ogreaddons/OgreNewt/OgreNewt_Main/inc
ogreaddons/OgreNewt/demos/Include
NewtonSDK/sdk
库目录:
ogrenew/ogremain/lib/debug <or release>
ogreaddons/OgreNewt_Main/lib/debug <or release>
NewtonSDK/dll/
现在我们需要添加一些Newton需要的内容。
#include <OgreNewt.h>
简单吧?现在在private成员里加入下面代码:
OgreNewt::World* mWorld;
如果你成功安装,你将会在输入OgreNewt::之后看到一大串类名。现在让我们用一些时间来说以下Newton SDK和它是如何工作的。
________________________________________
Newton SDK
这部分简要介绍下Newton SDK,无意代替SDK自带的文档。我的OgreNewt几乎是SDK类名的翻版,所以多数函数都在SDK文档里描述了。
Newton有一些基本元素描述了物理世界……它们是:
 
WORLD (OgreNewt::World) 
这是一个包含物体的空间。所有的物体都需要一个World来创建,并且包含在这个World里。大多数情况,你只需要创建一个World然后包含所有物体,但是需要的话系统也允许多个World共存。在本教程中只用到一个World。
 
RIGID BODY (OgreNewt::Body) 
这是物理世界里的一个基本的类。它代表一个固体,该固体可以和场景中的其他BODY互动。BODY可以有重量,大小和和形状。基本上你想被力所影响的物体都需要创建BODY。
 
COLLISION (OgreNewt::Collision) 
这个类代表某个形状。上面的Rigid Body需要一个Collision来定义它的形状。你可以重复使用Collision。比如你需要100个不同的箱子,你需要创建100个不同的BODY,但是只需要创建一个collision。Newton支持以下几种方法来描述collision:
• PRIMITIVE SHAPES :包括: Boxes, Ellipsoids, Cylinders, Capsules, Cones, and Chamfer Cylinders。
• CONVEX HULLS : Convex hulls 用空间的一系列点来创建一个最小的凸型。大多数情况,你可以用模型的顶点来创建,用这个方法将建立一个和你的3d模型差不多的collsion
• TREE COLLISIONS : 从名字不太容易看出来这个类是干什么的,不过TreeCollision" 就是多边形collision.比如如果你有一个由多边型构成的城市模型,你可以由该模型来建立collsion。注意collsion是不可以用在活动物体上。所有由Treecollsion建立的模型都被自动赋予无限大的质量,所以是完全不能运动的。它们最好被用作那些不需要运动的背景模型。对于运动物体,你必须使用convex hull或者general primitives。
• 注意:你是不能把这3种方法组合的来创建一个“组合collision”的。
JOINT (OgreNewt::Joint) 
Joints 是在两个body之间的连接,它将会影响到它们之间的互动。比如你将两个物体用hinge joint连接起来就可以创建一个门。
 
MATERIAL (OgreNewt::MaterialID && OgreNewt::MaterialPair) 
Materials 是Newton可以让你调整两个body相互运动的方式。简单的讲比如调整摩擦力,但是也有更复杂的用途。首先你要创建一个MaterialID来代表你系统里可能需要的material。一些普遍的例子比如: wood_mat, metal_mat, plastic_mat, or player_mat, 等.
然后你创建一个叫MaterialPair的东西。它描述了两个Material碰到一起会发生的行为。比如,你可以为collision创建一个包括铁和钢的MaterialPair。然后你可以为它创建火花,和声效。当两个这样的东西碰到一起的时候就会发生你所定义的事情。

Okay, 这就是Newton里最重要和基本的部分了。注意Newton里还有其它部分帮助创建ragdolls和汽车。如果需要请看Newton的开发文档吧。目前,OgreNewt还没有实现这些功能的部分。
________________________________________
The Newton World
好了,让我们回到我们的OgreNewtApplication类。正如你可以看到的,我们为一个OgreNewt::World加了一个指针,这就是我们将要放物体的World。现在为OgreNewtApplication.cpp添加内容。最后的效果看起来如下:
//OgreNewtApplication.cpp
#include "./ogrenewtapplication.h"

OgreNewtApplication::OgreNewtApplication(void)
{
}

OgreNewtApplication::~OgreNewtApplication(void)
{
}

void OgreNewtApplication::createScene()
{

}

void OgreNewtApplication::createFrameListener()
{

}
现在,在构造函数里创建Newton world,加入:
mWorld = new OgreNewt::World();
这行代码创建了一个OgreNewt::World 的实例。在创建其它实例前你需要先创建它,其它实例会要求你传递一个OgreNewt::World的指针,在析构函数里添加:
delete mWorld;
现在我们还需要为Application类添加一个部分:frame listener。在大多数的demo中,都有一个类继承ExampleFrameListener。这里也一样,不同的是我们要创建令一个framelistener专门来更新Newton world。首先创建标的ExampleFrameListener 类:
//OgreNewtApplication.cpp
void OgreNewtApplication::createFrameListener()
{
 mFrameListener = new ExampleFrameListener( mWindow, mCamera );
 mRoot->addFrameListener( mFrameListener );
}

现在我们来添加一个frame listener来更新物理世界,并且提供了debug的一些功能。我在OgreNewt库里已经假加入了类似的frame listener,叫BasicFrameListener 。为Application类添加一个成员变量:
OgreNewt::BasicFrameListener* mOgreNewtListener;
然后在 createFrameListener() 中添加:
mOgreNewtListener = new OgreNewt::BasicFrameListener( mWindow, mCamera, mSceneMgr, mWorld, 120 );
mRoot->addFrameListener( mOgreNewtListener );
OgreNewt::BasicFrameListener 是一个简单frame listener,用来每桢更新Newton world,用了time-slicing的方法,这意味着你可以控制物理更新的速度。最后一个参数你希望的更新fps。

Okay, 现在所有东西都创建好了。现在让我们来建立一个简单的场景。对于demo来说,我们将创建一个非常简单的场景,几个掉落的盒子。
让我们开始吧,首先创建地面:
Ogre::Vector3 size(10.0,1.0,10.0);
Ogre::SceneNode* node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
Ogre::Entity* ent = mSceneMgr->createEntity( "floorobj", "box.mesh" );
node->attachObject( ent );
node->setScale( size );
现在建立一个Rigid Body来代表这个物体。实际上是非常简单的:首先建立一个collision来代表形状:
OgreNewt::Collision* col = new OgreNewt::CollisionPrimitives::Box( mWorld, size );
然后,从这个collision来创建一个Rigid body。
OgreNewt::Body* floorbody = new OgreNewt::Body( mWorld, col );
现在我们的body创建好了,最后我们需要把它连到在SceneNode上的3d物体上。什么意思呢?Newton有一个很有意思的callback系统,这以为着如果你已经创建好了场景,Newton会自动为一更新物体的位置和旋转角度。比如在场景中你有50个不同的物体,当你要求Newton更新物理系统的时候,它会通过物理定律计算场景中所有物体的位置和角度。而其它的引擎,可能需要你创建一个循环读取场景中所有的物体,获取它们的坐标,赋予它们的模型。但是Newton有一个内置的callback系统可以为你作这些。这个非常酷!而且效率也很高,因为Newton只对移动的物体作处理。该功能可以通过OgreNewt::Body类里的attachToNode()来实现。
floorbody->attachToNode( node );
最后,我们来初始化地面的位置,让我们把它放在世界中心,距离Y轴向下5个单位:
floorbody->setPositionOrientation( Ogre::Vector3(0,-5,0), Ogre::Quaternion::IDENTITY );
delete col;
你注意到我们删除了collison的实例,因为我们不再需要它了。
现在地面完成了。接着,让我们创建几个几何体落在地面上。首先创建一个柱形。
// CYLINDER BODY
// 半径0.5, 高度 1.3
size = Ogre::Vector3( 1.3, 0.5, 0.5 );
node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
ent = mSceneMgr->createEntity("cylinder_body", "cylinder.mesh" );
node->attachObject( ent );
node->setScale( size );

// rigid body.
col = new OgreNewt::CollisionPrimitives::Cylinder( mWorld, 0.5, 1.3 );
OgreNewt::Body* bod = new OgreNewt::Body( mWorld, col );
bod->attachToNode( node );

// initial position
bod->setPositionOrientation( Ogre::Vector3(-2,3,2), Ogre::Quaternion::IDENTITY );
delete col;
好了,目前这些看起来都象我们在创建地面时候做的。不过我们要添加一些代码让这个物体动起来,比如下降,和撞击其它物体。为此,我们需要为这个Rigid body创建一些其它特性,比如质量和惯性。质量很简单,我推荐用单位用“千克”。惯性就不那么直观了,它代表着物体抵抗旋转的能力。很多因素都可以影响到这个值,得到准确的值就不是我能作到的了。但是,网上有一些现成的公式来计算某一时刻的惯性。为了方便,我已经把一些公式包含在OgreNewt里了。碰巧有一个通过质量和大小计算柱体惯性的公式。代码如下:
Ogre::Real mass = 10.0;
Ogre::Vector3 inertia = OgreNewt::MomentOfInertia::CalcCylinderSolid( mass, 0.5, 1.3 );

bod->setMassMatrix( mass, inertia );
好了,现在物体有了质量!但是如果现在你要编译运行程序的话(你也可以试试看!),这个物体并不会落到地上。这是因为我们为这个物体施加外力。在物理模拟中,最通常的外力是重力。我们如何用Newton来施加重力呢?
类似于Newton可以返回你物体的位置和方向。Newton还为物体提供了一个callback,你可以通过它来调整力的大小。我还没有完全把它移植到了OgreNewt里,如果要移植的话看看Newton文档也不是太难。但是我在OgreNewt::Body中包括了一个basicForceTorqueCallback(),它向物体施加一个不变的-Y方向的力,大小为9.8units/sec^2。要调用,只需要如下代码:
bod->setStandardForceCallback();
完成!你的物体现在有重力了。现在让我们再加一些物体吧。
// CONE BODY
// cone with a radius of 0.8, height of 1.0
size = Ogre::Vector3( 1.0, 0.8, 0.8 );
node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
ent = mSceneMgr->createEntity("cone_body", "cone.mesh" );
node->attachObject( ent );
node->setScale( size );
 
// rigid body.
col = new OgreNewt::CollisionPrimitives::Cone( mWorld, 0.8, 1.0 );
bod = new OgreNewt::Body( mWorld, col );
bod->attachToNode( node ); 

// initial position
bod->setPositionOrientation( Ogre::Vector3(2,3,2), Ogre::Quaternion::IDENTITY );
delete col;

mass = 10.0;
inertia = OgreNewt::MomentOfInertia::CalcCylinderSolid( mass, 0.5, 1.3 );
bod->setMassMatrix( mass, inertia );
bod->setStandardForceCallback();


// BOX BODY
// standard 1x1x1 cube.
size = Ogre::Vector3( 1, 1, 1 );
node = mSceneMgr->getRootSceneNode()->createChildSceneNode();
ent = mSceneMgr->createEntity("box_body", "box.mesh" );
node->attachObject( ent );
node->setScale( size );

// rigid body.
col = new OgreNewt::CollisionPrimitives::Box( mWorld, size );
bod = new OgreNewt::Body( mWorld, col );
bod->attachToNode( node );

// initial position
bod->setPositionOrientation( Ogre::Vector3(0,3,-2),Ogre::Quaternion::IDENTITY );
delete col;

mass = 10.0;
inertia = OgreNewt::MomentOfInertia::CalcBoxSolid( mass, size );
bod->setMassMatrix( mass, inertia );
bod->setStandardForceCallback();
好了,全部完成!现在不要忘记在你的场景中加上光源,和初始化摄像机的位置。现在编译运行你的程序,你将会看到我们建立的3个物体掉落到地上。
这个教程对于你开始学习Ogre和Newton已经足够了。不过我意在抛砖引玉,让你可以通过这个库来开始自己的Ogre和Newton学习。祝你好运~有一个好的物理系统!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值