贝塞尔曲线的应用
#ifndef __BezierPatch_H__
#define __BezierPatch_H__
#include "SdkSample.h"
using namespace Ogre;
using namespace OgreBites;
class _OgreSampleClassExport Sample_BezierPatch : public SdkSample
{
public:
Sample_BezierPatch()
{
mInfo["Title"] = "Bezier Patch";
mInfo["Description"] = "A demonstration of the Bezier patch support.";
mInfo["Thumbnail"] = "thumb_bezier.png";
mInfo["Category"] = "Geometry";
}
mInfo是个Ogre::NameValuePairList参数 保存的是程序刚开始运行时左边显示的介绍信息
void checkBoxToggled(CheckBox* box)
{
mPatchPass->setPolygonMode(box->isChecked() ? PM_WIREFRAME : PM_SOLID);
}
void sliderMoved(Slider* slider)
{
mPatch->setSubdivision(slider->getValue());
}
上面两个函数是程序左上角UI的处理函数 至于何时调用,那应该和Ogre内在GUI系统(通过一个叫做“tray”的实现)有关,virtual的关系。用查找的方式可以找到其基类virtual版本以及调用
protected:
#if OGRE_COMPILER == OGRE_COMPILER_MSVC
# pragma pack(push, 1)
#endif
这里的pragma pack的解释请看http://blog.youkuaiyun.com/a523330620/article/details/7257415
struct PatchVertex
{
float x, y, z;
float nx, ny, nz;
float u, v;
};
#if OGRE_COMPILER == OGRE_COMPILER_MSVC
# pragma pack(pop)
#endif
void setupContent()
{
// setup some basic lighting for our scene
mSceneMgr->setAmbientLight(ColourValue(0.5, 0.5, 0.5));
mSceneMgr->createLight()->setPosition(100, 100, 100);
// define the control point vertices for our patch
PatchVertex verts[9] =
{
{-50, -35, -50, -0.5, 0.5, 0.0, 0.0, 0.0},
{ 0, 0, -50, 0.0, 0.5, 0.0, 0.5, 0.0},
{ 50, 35, -50, 0.5, 0.5, 0.0, 1.0, 0.0},
{-50, 0, 0, -0.5, 0.5, 0.0, 0.0, 0.5},
{ 0, 0, 0, 0.0, 0.5, 0.0, 0.5, 0.5},
{ 50, 0, 0, 0.5, 0.5, 0.0, 1.0, 0.5},
{-50, 35, 50, -0.5, 0.5, 0.0, 0.0, 1.0},
{ 0, 0, 50, 0.0, 0.5, 0.0, 0.5, 1.0},
{ 50, -35, 50, 0.5, 0.5, 0.0, 1.0, 1.0}
};
通过Ogre左手坐标系点的模拟,上面的点确定的就是一块由9个顶点做成的布。从法向量的坐标值来看,这块布的正面是朝上的,只要这些自定义的法向量确定的平面是正确的即可,具体我觉得还需要空间模拟以及空间想象力。纹理坐标:对角线的纹理坐标分别是(0,0)和(1,1), 其他点的纹理坐标可以按比例设置。
// specify a vertex format declaration for our patch: 3 floats for position, 3 floats for normal, 2 floats for UV
VertexDeclaration* decl = HardwareBufferManager::getSingleton().createVertexDeclaration();
decl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
decl->addElement(0, sizeof(float) * 3, VET_FLOAT3, VES_NORMAL);
decl->addElement(0, sizeof(float) * 6, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
顶点声明,定义了顶点的数据格式,如果没有这个声明,那么上面的PatchVertex结构就无法被识别。
addElement函数的参数:1 起始地址 2 偏移地址 3 数据格式 4 数据的类型
顶点声明以及顶点结构(例如PatchVertex)中数据的声明顺序至关重要:
位置, 混合权重, 法线, 漫反射颜色, 镜面颜色, 纹理坐标
并且如果其中有缺少项,内存中不能留白,内存地址需要紧密,例如上面的VES_POSITION和VES_NORMAL之间的内存地址。
// create a patch mesh using vertices and declaration
mPatch = MeshManager::getSingleton().createBezierPatch("patch",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, (float*)verts, decl, 3, 3, 5, 5, PatchSurface::VS_BOTH);
创建贝塞尔曲线的函数,效果可以通过修改观察不同的效果。
mPatch->setSubdivision(0); // start at 0 detail
设置曲线的细节层次0 - 1之间,可能是弯曲度吧?
// create a patch entity from the mesh, give it a material, and attach it to the origin
Entity* ent = mSceneMgr->createEntity("Patch", "patch");
ent->setMaterialName("Examples/BumpyMetal");
mSceneMgr->getRootSceneNode()->attachObject(ent);
// save the main pass of the material so we can toggle wireframe on it
mPatchPass = ent->getSubEntity(0)->getMaterial()->getTechnique(0)->getPass(0);
// use an orbit style camera
mCameraMan->setStyle(CS_ORBIT);
设置相机的控制模式:CS_ORBIT 鼠标左键旋转 右键上下移动控制拉近拉远
mCameraMan->setYawPitchDist(Degree(0), Degree(30), 250);
设置相机的初始旋转以及与原点的距离
mTrayMgr->showCursor();
显示光标
// create slider to adjust detail and checkbox to toggle wireframe
mTrayMgr->createThickSlider(TL_TOPLEFT, "Detail", "Detail", 120, 44, 0, 1, 6);
mTrayMgr->createCheckBox(TL_TOPLEFT, "Wireframe", "Wireframe", 120);
创建GUI
}
void cleanupContent()
{
mPatchPass->setPolygonMode(PM_SOLID);
MeshManager::getSingleton().remove(mPatch->getHandle());
}
PatchMeshPtr mPatch;
Pass* mPatchPass;
};
#endif