转载:OGRE一起学(九)平面

来源:互联网 发布:如何用js判断是否闰年 编辑:程序博客网 时间:2024/04/30 05:17

转载:OGRE一起学(九)平面

第九章 平面

运行截图:

Image:Yanchen91.jpg

前几节悬空的模型没有为我们提供一个“踏实”的参照系,难以体现物体空间位置的变化,因为没有地面。所以在学习移动、缩放和旋转之前,我们先学习创造一个地面。

要在场景中创建并渲染一个平面,需要下面三个步骤: 1. 定义平面; 2. 从定义的平面创建平面模型; 3. 将平面模型绑定到场景节点。

  • 1. 定义平面 :
  Plane plane; // 定义平面  plane.normal = Vector3::UNIT_Y; // 定义平面的法线方向(也就是平面正面的朝向)  plane.d = 100; // 定义平面与世界原点的距离

平面 ( Plane ) 是 OGRE 唯一的一种内置简单几何体 (Primitive) 。当然,如果你高兴,你可以修改 OGRE 的内核代码,使它能够创建更多类型的简单几何体例如立方体 (Cube/Box) 、球体 (Sphere) 、柱体 (Cylinder) 、锥体 (Cone) 、 圆环体 (Torus) 、或者茶壶 (Teapot) ,很多商业引擎具有直接创建这些简单几何体的能力,但是 OGRE 目前只能创建简单平面。

OGRE:: Plane (平面) 对象的定义参看头文件 OgrePlane.h ,它有五个重载的构造函数,意味着我们可以使用五种不同的方法来创建一个平面:

  // 使用默认设置直接创建平面  Plane::Plane ()  {  normal = Vector3::ZERO;  d = 0.0;  }  // 使用现有平面的设置新建一个平面  Plane::Plane (const Plane& rhs)  {  normal = rhs.normal;  d = rhs.d;  }  // 由法线方向和平面到世界原点的距离创建一个平面  Plane::Plane (const Vector3& rkNormal, Real fConstant)  {  normal = rkNormal;  d = -fConstant;  }  // 由法线方向和平面上的一点创建一个平面  Plane::Plane (const Vector3& rkNormal, const Vector3& rkPoint)  {  normal = rkNormal;  d = -rkNormal.dotProduct(rkPoint);  }  // 三点确定一个平面  Plane::Plane (const Vector3& rkPoint0, const Vector3& rkPoint1, const Vector3& rkPoint2)  {  redefine(rkPoint0, rkPoint1, rkPoint2);  }

平面具有两种基本属性:

  Vector3 normal; // 法线方向  Real d; // 与世界原点的距离
  • 2. 从定义的平面创建平面模型 :
  Mesh* pGround = MeshManager::getSingleton().createPlane(  "GroundPlane", // 模型名称  plane, // 平面定义  2000, // X 方向宽度  1000, // Z 方向宽度  10, // X 方向分割  5, // Z 方向分割  true, // 是否创建法线  2, // 纹理坐标数量  16, // U 方向纹理铺嵌的行数  8, // V 方向纹理铺嵌的行数  Vector3::UNIT_Z // 正面朝向  );

在第一步中,我们仅仅是定义了一个非常抽象的平面,这个抽象的平面只拥有法线方向和与世界原点的距离两个属性,在第二步,我们就要使用 createPlane 方法使这个平面具体化,赋予它名称、尺寸、分割、纹理坐标等具体属性,正式构建出一个平面模型 ( Mesh ) 。

MeshManager:: createPlane () (创建平面)方法在头文件 OgreMeshManager.h 中定义:

  Mesh * Ogre::MeshManager::createPlane (  const String & name, // 平面模型的名称  const Plane & plane, // 所使用的平面定义的名称  Real width, // 平面宽度 (X 方向)  Real height, // 平面高度 (Y 方向)  int xsegments = 1, // X 方向分割数目  int ysegments = 1, // Y 方向分割数目  bool normals = true, // 是否创建垂直于平面的法线  int numTexCoordSets = 1, // 纹理坐标集的数目(也就是多层纹理的层数)  Real uTile = 1.0f, // U 方向纹理铺嵌行数  Real vTile = 1.0f, // V 方向纹理铺嵌行数  const Vector3 & upVector = Vector3::UNIT_Y,   // 上方向法线,指示平面的正面朝向  HardwareBuffer::Usage vertexBufferUsage = HardwareBuffer::HBU_STATIC_WRITE_ONLY,   // 顶点缓存用途  HardwareBuffer::Usage indexBufferUsage = HardwareBuffer::HBU_STATIC_WRITE_ONLY,   // 索引缓存用途  bool vertexShadowBuffer = true, // 顶点阴影缓存  bool indexShadowBuffer = true // 索引阴影缓存  ) 

后面四个参数目前暂不深究,使用默认值。

  • 3. 将平面模型绑定到场景节点 :
  // 创建实体(地面)  Entity* entGround = mSceneMgr->createEntity( "ground", "GroundPlane" );  // 为地面设置材质  entGround->setMaterialName( "Examples/Rockwall" );  // 在场景根节点下创建一个子节点用于绑定这个地面实体  SceneNode* groundNode = rootNode->createChildSceneNode();  // 把地面实体绑定到这个子节点  groundNode->attachObject( entGround );

Entity:: setMaterialName () (设置材质名称) 方法在头文件 OgreEntity.h 中定义,使用这个方法可以整体替换模型的本体材质,非常方便:

  void Ogre::Entity:: setMaterialName ( const String & name ) 

材质和模型、粒子一样,属于一种预制资源。打开 OGRE\Samples\Media\materials\scripts\ 目录,可以在下面看到一系列后缀是 *.material 的文件,这些都是材质的定义脚本。使用文本编辑器打开 Example.material ,在里面你可以查找到包含 Examples/Rockwall 字样的脚本段落,它在这个文件的最后:

  material Examples/Rockwall // material 材质名称  {  technique // 材质渲染技术块  {  pass // 材质渲染通道  {  texture_unit // 纹理单位  {  texture rockwall.tga // texture 纹理贴图名称  }  }  }  } 

其中的纹理贴图 rockwall.tga ,和其它所有的贴图文件一起,位于 OGRE\Samples\Media\textures\ 目录下,在这里我们不用指定贴图的路径, 凭借配置文件 resources.cfg , OGRE 可以自动找到这张贴图。

材质脚本的详细内容以后找时间再介绍。

最后,我用离线浏览工具下载了 OGRE 官网的手册 (Manual) ,里面有关于材质脚本的解说,比较详细,可以先看看。

0 0
原创粉丝点击