Ogre的贴花操作….
说明:
ManualObject需要在Begin()与End()之间执行创建位置与纹理坐标等操作, 如果需要对手动物体添加贴图, 则在Begin(“MatName”)传入材质名称.
关于创建顶点索引,这里是以正方形顺时针创建.
#pragma once #include <Ogre.h> #include <string> #include "Util.h" class Decal { public: Decal(const std::string &name, const std::string &matName, const Ogre::Vector2 &dimen, const Ogre::Vector2 &position, float heightOffset = 0.5, int resolution = 4, Ogre::SceneManager *sceneMgr = Util::getSceneManager()) : mDim(dimen), mHeightOffset(heightOffset), mRes(resolution) { mDecal = new Ogre::ManualObject(name); mDecal->setCastShadows(false); mDecal->setDynamic(true); //mDecal->setRenderQueueGroup(Ogre::RENDER_QUEUE_WORLD_GEOMETRY_2); mDecal->begin(matName); for (int i = 0; i <= mRes; i++) { for (int j = 0; j <= mRes; j++) { // 顶点坐标 mDecal->position(i, 0, j); // 纹理坐标[0~1] mDecal->textureCoord(i / (float)mRes, j / (float)mRes); } } // 顶点索引处不<= for (int i = 0; i < mRes; i++) { for (int j = 0; j < mRes; j++) { // 顶点索引, 顺时针,小方格 mDecal->quad(i * (mRes + 1) + j, i * (mRes + 1) + j + 1, (i + 1) * (mRes + 1) + j + 1, (i + 1) * (mRes + 1) + j); } } mDecal->end(); mDecalNode = sceneMgr->getRootSceneNode()->createChildSceneNode(); mDecalNode->attachObject(mDecal); mQuery = sceneMgr->createRayQuery(Ogre::Ray()); moveTo(position); } ~Decal(void) { delete mQuery; mDecalNode->detachAllObjects(); mDecalNode->getParent()->removeChild(mDecalNode); delete mDecal; } void moveTo(const Ogre::Vector2& pos) { float xBegin = pos.x - (mDim.x / 2); float zBegin = pos.y - (mDim.y / 2); float xWidth = mDim.x / mRes; float zWidth = mDim.y / mRes; // 更新 mDecal->beginUpdate(0); for (int i = 0; i <= mRes; i++) { for (int j = 0; j <= mRes; j++) { float x = xBegin + (xWidth * i); float z = zBegin + (zWidth * j); float y = getHeight(x, z) + mHeightOffset; mDecal->position(x, y, z); mDecal->textureCoord(i / (float)mRes, j / (float)mRes); } } for (int i = 0; i < mRes; i++) { for (int j = 0; j < mRes; j++) { mDecal->quad(i * (mRes + 1) + j, i * (mRes + 1) + j + 1, (i + 1) * (mRes + 1) + j + 1, (i + 1) * (mRes + 1) + j); } } mDecal->end(); } private: float getHeight(float x, float z) { mQuery->setRay(Ogre::Ray(Ogre::Vector3(x, 5000, z), Ogre::Vector3::NEGATIVE_UNIT_Y)); Ogre::RaySceneQueryResult &result = mQuery->execute(); Ogre::RaySceneQueryResult::iterator i = result.begin(); if(i != result.end() && i->worldFragment) return i->worldFragment->singleIntersection.y; return 0; } private: Ogre::ManualObject *mDecal; Ogre::SceneNode *mDecalNode; Ogre::Vector2 mDim; float mHeightOffset; Ogre::RaySceneQuery *mQuery; int mRes; };