BezierPatch.h
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/
/**
/file
Bezier.h 贝塞尔曲线平滑补丁
/brief
Specialisation of OGRE's framework application to show off
the bezier patch support.
将一些生硬的模型进行贝塞尔补丁使之平滑
*/
#include "ExampleApplication.h"
// Hack struct for test
PatchMeshPtr patch;
Pass* patchPass;
// Event handler to add ability to alter subdivision
// 事件监听类
class BezierListener : public ExampleFrameListener
{
protected:
public:
BezierListener(RenderWindow* win, Camera* cam)
: ExampleFrameListener(win, cam)
{
}
bool frameStarted(const FrameEvent& evt)
{
if( ExampleFrameListener::frameStarted(evt) == false )
return false;
static Real timeLapse = 0.0f;//timeLapse变量为一个记时器
static Real factor = 0.0; //factor 为patch中面数的调节比例参数(0~1)中
static bool wireframe = 0; //wireframe代表了渲染是采用线型还是实型
//timeSinceLastFrame为evt的成员变量,记录了上一帧到现在的时间
timeLapse += evt.timeSinceLastFrame;
// Prgressively grow the patch
// 调节 增长片
// 如果timeLapse大于1.0,则增加factor,并切换wireframe。切换渲染方式
if (timeLapse > 1.0f)
{
factor += 0.2;
if (factor > 1.0f)
{
wireframe = !wireframe;
//mCamera->setPolygonMode(wireframe ? PM_WIREFRAME : PM_SOLID);
patchPass->setPolygonMode(wireframe ? PM_WIREFRAME : PM_SOLID);
factor = 0.0f;
}
//设置Patch中模型面数
patch->setSubdivision(factor);
mDebugText = "Bezier subdivision factor: " + StringConverter::toString(factor);
timeLapse = 0.0f;
//计时器timeLapse归0
}
// Call default
return true;
}
};
//贝塞尔曲线应用程序
class BezierApplication : public ExampleApplication
{
protected:
VertexDeclaration* patchDecl; //顶点格式声明管理器
float* patchCtlPoints; //顶点缓冲指针
public:
BezierApplication() : patchDecl(NULL), patchCtlPoints(NULL) { }
~BezierApplication()
{
//释放顶点缓冲
if (patchCtlPoints)
delete [] patchCtlPoints;
// patch vertex declaration will be deleted automatically
}
protected:
#if OGRE_COMPILER == OGRE_COMPILER_MSVC
#pragma pack(push)
#pragma pack(1)
#endif
struct PatchVertex {
float x, y, z;
float nx, ny, nz;
float u, v;
};
#if OGRE_COMPILER == OGRE_COMPILER_MSVC
#pragma pack(pop)
#endif
// Just override the mandatory create scene method
//创建场景参数
void createScene(void)
{
// Set ambient light
//设置场景中的环境光
mSceneMgr->setAmbientLight(ColourValue(0.2, 0.2, 0.2));
// Create a point light
//创建一个点光源
Light* l = mSceneMgr->createLight("MainLight");
// Accept default settings: point light, white diffuse, just set position
// NB I could attach the light to a SceneNode if I wanted it to move automatically with
// other objects, but I don't
// 设置点光源的类型为方向光
l->setType(Light::LT_DIRECTIONAL);
//设置点光源的方向
l->setDirection(-0.5, -0.5, 0);
// Create patch
// 创建 可调节的模型
// 取得顶点格式声明管理器
patchDecl = HardwareBufferManager::getSingleton().createVertexDeclaration();
//设置顶点格式
//由位置0起始的float3格式的位置 如float x,y,z;
patchDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
//由float3起始的float3格式的法向量 如float nx,ny,nz;
patchDecl->addElement(0, sizeof(float)*3, VET_FLOAT3, VES_NORMAL);
//由float6起始的float2格式的纹理坐标 如 float u,v ;
patchDecl->addElement(0, sizeof(float)*6, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
// Make a 3x3 patch for test
// 创建9个顶点大小的顶点数组
patchCtlPoints = (float*)( new PatchVertex[9] );
// Patch data
// 创建顶点结构指针指向顶点缓冲
PatchVertex *pVert = (PatchVertex*)patchCtlPoints;
// 填充顶点信息
pVert->x = -500.0; pVert->y = 200.0; pVert->z = -500.0;
pVert->nx = -0.5; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 0.0; pVert->v = 0.0;
pVert++;
pVert->x = 0.0; pVert->y = 500.0; pVert->z = -750.0;
pVert->nx = 0.0; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 0.5; pVert->v = 0.0;
pVert++;
pVert->x = 500.0; pVert->y = 1000.0; pVert->z = -500.0;
pVert->nx = 0.5; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 1.0; pVert->v = 0.0;
pVert++;
pVert->x = -500.0; pVert->y = 0.0; pVert->z = 0.0;
pVert->nx = -0.5; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 0.0; pVert->v = 0.5;
pVert++;
pVert->x = 0.0; pVert->y = 500.0; pVert->z = 0.0;
pVert->nx = 0.0; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 0.5; pVert->v = 0.5;
pVert++;
pVert->x = 500.0; pVert->y = -50.0; pVert->z = 0.0;
pVert->nx = 0.5; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 1.0; pVert->v = 0.5;
pVert++;
pVert->x = -500.0; pVert->y = 0.0; pVert->z = 500.0;
pVert->nx = -0.5; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 0.0; pVert->v = 1.0;
pVert++;
pVert->x = 0.0; pVert->y = 500.0; pVert->z = 500.0;
pVert->nx = 0.0; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 0.5; pVert->v = 1.0;
pVert++;
pVert->x = 500.0; pVert->y = 200.0; pVert->z = 800.0;
pVert->nx = 0.5; pVert->ny = 0.5; pVert->nz = 0.0;
pVert->u = 1.0; pVert->v = 1.0;
pVert++;
//由模型管理器中创建贝塞尔可调节模型API创建可调节模型
//参数1为创建的可调节模型的名称
//参数2为使用资源组类型为缺省类型
//参数3为顶点缓冲
//参数4为顶点格式声明
//参数5为宽
//参数6为高
//参数7,8为设定的最大的调节级别
//参数9为三角形两面都渲染
patch = MeshManager::getSingleton().createBezierPatch(
"Bezier1", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
patchCtlPoints, patchDecl,
3, 3, 5, 5, PatchSurface::VS_BOTH);
// Start patch at 0 detail
// 设置起始调节参数为0
patch->setSubdivision(0.0f);
// Create entity based on patch
//由可调节模型创建一个实体
Entity* patchEntity = mSceneMgr->createEntity("Entity1", "Bezier1");
//创建材质
MaterialPtr pMat = MaterialManager::getSingleton().create("TextMat",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
//材质中的效果设置纹理
pMat->getTechnique(0)->getPass(0)->createTextureUnitState( "BumpyMetal.jpg" );
//设置实体的材质
patchEntity->setMaterialName("TextMat");
patchPass = pMat->getTechnique(0)->getPass(0);
// Attach the entity to the root of the scene
// 将实体加入场景
mSceneMgr->getRootSceneNode()->attachObject(patchEntity);
//设置摄像机位置
mCamera->setPosition(500,500, 1500);
//设置摄像机观察点
mCamera->lookAt(0,200,-300);
}
void destroyScene(void)
{
// free up the pointer before we shut down OGRE
// 释放可调节模型
patch.setNull();
}
void createFrameListener(void)
{
// This is where we instantiate our own frame listener
//创建帧监听器
mFrameListener= new BezierListener(mWindow, mCamera);
//给根
mRoot->addFrameListener(mFrameListener);
}
};
Bezier.cpp:
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/
/**
/file
Bezier.cpp
/brief
Shows OGRE's bezier patch feature
*/
#include "Bezier.h"
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char **argv)
#endif
{
// Create application object
// 创建程序
BezierApplication app;
try {
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL );
#else
std::cerr << "An exception has occured: " << e.getFullDescription();
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif