|
|
来源:http://www.blog.edu.cn/user1/4750/archives/2004/8633.shtml
BSPCollision和别的DEMO程序不同,它分别继承了两个类:ExampleRefAppApplication和ExampleRefAppFrameLis
tener.
先来看它的构造部分:BSPCollisionApplication类,继承自ExampleRefAppApplication类。
都使用默认的构造/析构函数。
首先定义了一个chooseSceneManager方法来指定场景的类型:
void chooseSceneManager(void)
{
mSceneMgr = mRoot->getSceneManager( ST_INTERIOR );
}
然后创建世界:
void createWorld(void)
{
// Create BSP-specific world
mWorld = new World(mSceneMgr, World::WT_REFAPP_BSP);
}
其中世界是一个World类的对象,那么什么是World类呢?查找一下文档,其定义为:
enum WorldType { WT_REFAPP_GENERIC, WT_REFAPP_BSP }
World //type, you'll want to extend this for your own apps.
构造函数是
OgreRefApp::World::World ( SceneManager * sceneMgr,
WorldType worldType = WT_REFAPP_GENERIC
)
然后就是熟悉的创建场景方法了:
程序首先指定了场景管理器的阴影类型:
mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE); //有待于学习
然后是设置环境光源和主光源。
Light* l = mSceneMgr->createLight("MainLight");
l->setPosition(-100,50,100);
l->setAttenuation(8000,1,0,0); //有待于学习
完成了对场景管理器的初步设置后开始设置世界:
mWorld->setGravity(Vector3(0, 0, -60)); //设置重力向量
mWorld->getSceneManager()->setWorldGeometry("ogretestmap.bsp"); //设置世界的地图
对摄象机的设置不太懂,暂时搁置!!!!!!!!!
// modify camera for close work
mCamera->setNearClipDistance(10);
mCamera->setFarClipDistance(20000);
然后是对摄象机的初始化:
// Also change position, and set Quake-type orientation
// Get random player start point
ViewPoint vp = mSceneMgr->getSuggestedViewpoint(true);
mCamera->setPosition(vp.position);
mCamera->pitch(90); // Quake uses X/Y horizon, Z up
mCamera->rotate(vp.orientation);
// Don't yaw along variable axis, causes leaning
mCamera->setFixedYawAxis(true, Vector3::UNIT_Z);
// Look at the boxes
mCamera->lookAt(-150,40,30);
创造一个球:
ball = mWorld->createBall("ball", 7, vp.position + Vector3(0,0,80));
ball->setDynamicsEnabled(true);
ball->getEntity()->setMaterialName("Ogre/Eyes");
创造方块:
Box* box = mWorld->createBox("shelf", 75, 125, 5, Vector3(-150, 40, 30));
box->getEntity()->setMaterialName("Examples/Rocky");
static const Real BOX_SIZE = 15.0f;
static const int num_rows = 3;
创造盒子的函数定义如下:
OgreRefApp::Box * OgreRefApp::World::createBox ( const String & name,
Real width,
Real height,
Real depth,
const Vector3 & pos = Vector3::ZERO,
const Quaternion & orientation = Quaternion::IDENTITY
)
看到这里我有一个疑问:为什么盒子有重量,但是球却没有呢?有待于研究。
继续看。
for (int row = 0; row < num_rows; ++row)
{
for (int i = 0; i < (num_rows-row); ++i)
{
Real row_size = (num_rows - row) * BOX_SIZE * 1.25;
String name = "box";
name += StringConverter::toString((row*num_rows) + i);
box = mWorld->createBox(name, BOX_SIZE,BOX_SIZE,BOX_SIZE ,
Vector3(-150,
40 - (row_size * 0.5) + (i * BOX_SIZE * 1.25) ,
32.5 + (BOX_SIZE / 2) + (row * BOX_SIZE)));
box->setDynamicsEnabled(false, true);
box->getEntity()->setMaterialName("Examples/10PointBlock");
}
}
在看之前我估计这段程序的作用是复制出其他的方块,但实际上却是窗在出不同的方块,也许是因为每个方块都可能有不同的行为所以就不能用克隆方式了吧。
在创建场景的最后是设置屏幕提示。
这个类的最后是创建一个FrameListener.
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
然后再来看BspCollisionListener类都做了什么事,首先,它是ExampleRefAppFrameListener的子类,构造函数也和普通的ExampleFrameListener是一样的。
最大的不同之处在于它重写了frameEnded方法,而不是frameStarted方法,原因暂时不详。
首先定义了一个静态变量:
// local just to stop toggles flipping too fast
static Real timeUntilNextToggle = 0;
然后是这样一段代码,555555555555555555555~~~My poor English!
// Deal with time delays that are too large
// If we exceed this limit, we ignore
static const Real MAX_TIME_INCREMENT = 0.5f;
if (evt.timeSinceLastEvent > MAX_TIME_INCREMENT)
{
return true;
}
if (timeUntilNextToggle >= 0)
timeUntilNextToggle -= evt.timeSinceLastFrame;
然后就是电泳父类的方法完成对输入动作的处理。
// Call superclass
bool ret = ExampleRefAppFrameListener::frameEnded(evt);
if (mInputDevice->isKeyDown(KC_SPACE) && timeUntilNextToggle <= 0)
{
timeUntilNextToggle = 2;
ball->setPosition(mCamera->getPosition() +
mCamera->getDirection() * mCamera->getNearClipDistance() * 2);
ball->setLinearVelocity(mCamera->getDirection() * 200);
ball->setAngularVelocity(Vector3::ZERO);
}
|
|