Creating the Mesh
constfloat width =25;constfloat height =30; Ogre::ManualObject mo("GrassObject"); Ogre::Vector3 vec(width/2,0,0); Ogre::Quaternion rot; rot.FromAngleAxis(Ogre::Degree(60), Ogre::Vector3::UNIT_Y);
mo.begin("Examples/GrassBlades", Ogre::RenderOperation::OT_TRIANGLE_LIST); for(int i =0; i <3;++i){
mo.position(-vec.x, height,-vec.z); mo.textureCoord(0,0); mo.position(vec.x, height, vec.z); mo.textureCoord(1,0); mo.position(-vec.x,0,-vec.z); mo.textureCoord(0,1); mo.position(vec.x,0, vec.z); mo.textureCoord(1,1);
int offset = i *4; mo.triangle(offset, offset+3, offset+1); mo.triangle(offset, offset+2, offset+3);
vec = rot * vec;} mo.end();
mo.convertToMesh("GrassBladesMesh");
// Do not add to the code! Ogre::MeshPtr ptr = mo.convertToMesh("GrassBladesMesh"); Ogre::MeshSerializer ser; ser.exportMesh(ptr.getPointer(),"grass.mesh");
Adding Static Geometry
Ogre::Entity*grass = mSceneMgr->createEntity("grass","GrassBladesMesh"); Ogre::StaticGeometry*sg = mSceneMgr->createStaticGeometry("GrassArea"); constint size =375;constint amount =20;
sg->setRegionDimensions(Ogre::Vector3(size, size, size)); sg->setOrigin(Ogre::Vector3(-size/2,0,-size/2));
// Do not add to the project! sg->setOrigin(Vector3(-size/2,-size/2,-size/2)+ Vector3(x, y, z));
for(int x =-size/2; x < size/2; x +=(size/amount)) { for(int z =-size/2; z < size/2; z +=(size/amount)) { Ogre::Real r = size /(float)amount /2; Ogre::Vector3 pos(x + Ogre::Math::RangeRandom(-r, r), 0, z + Ogre::Math::RangeRandom(-r, r)); Ogre::Vector3 scale(1, Ogre::Math::RangeRandom(0.9,1.1),1); Ogre::Quaternion orientation; orientation.FromAngleAxis(Ogre::Degree(Ogre::Math::RangeRandom(0,359)), Ogre::Vector3::UNIT_Y); sg->addEntity(grass, pos, orientation, scale); } }
sg->build();
Conclusion
Modifying the StaticGeometry Object
Once the StaticGeometry is created, you are not supposed to do too much with it, since that would mostly defeat the purpose. You can, however, do things like wave the grass with the wind. If you are interested in how to do this, take a look at the grass demo which comes with Ogre. The GrassListener::waveGrass function modifies the grass to perform a wave-like motion.
Advanced Object Batching
This is, of course, just the beginnings of object batching. You should use StaticGeometry any time you have objects that are grouped together and will not move. If you are trying to create something as intensive or as expansive as a forest or trying to add grass to a huge amount of terrain, you should take a look at one of the more advanced batching techniques, like thePagedGeometry Engine.
Intermediate Tutorial 6 Projective Decals 投影贴花
Frustums
mDecalFrustum = new Ogre::Frustum(); mProjectorNode = mSceneMgr->getRootSceneNode()-> createChildSceneNode("DecalProjectorNode"); mProjectorNode->attachObject(mDecalFrustum); mProjectorNode->setPosition(0,5,0);
// Do not add this to the project mDecalFrustum->setProjectionType(Ogre::PT_ORTHOGRAPHIC); mDecalFrustum->setOrthoWindowHeight(100);
Modifying the Material
Ogre::MaterialPtr mat =(Ogre::MaterialPtr)Ogre::MaterialManager::getSingleton() .getByName(matName); Ogre::Pass*pass = mat->getTechnique(0)->createPass();
pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA); pass->setDepthBias(1); pass->setLightingEnabled(false);
Ogre::TextureUnitState*texState = pass->createTextureUnitState("decal.png"); texState->setProjectiveTexturing(true, mDecalFrustum); texState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); texState->setTextureFiltering(Ogre::FO_POINT, Ogre::FO_LINEAR, Ogre::FO_NONE);
Getting Rid of the Back Projection
Modifying the Projector
mFilterFrustum = new Ogre::Frustum(); mFilterFrustum->setProjectionType(Ogre::PT_ORTHOGRAPHIC); Ogre::SceneNode*filterNode = mProjectorNode ->createChildSceneNode("DecalFilterNode"); filterNode->attachObject(mFilterFrustum); filterNode->setOrientation(Ogre::Quaternion(Ogre::Degree(90),Ogre::Vector3::UNIT_Y));
Modifying the Material
texState = pass->createTextureUnitState("decal_filter.png"); texState->setProjectiveTexturing(true, mFilterFrustum); texState->setTextureAddressingMode(Ogre::TextureUnitState::TAM_CLAMP); texState->setTextureFiltering(Ogre::TFO_NONE);
Intermediate Tutorial 7 Render to texture (RTT)
Ogre::TexturePtr rtt_texture = Ogre::TextureManager::getSingleton() .createManual("RttTex", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D,
mWindow->getWidth(), mWindow->getHeight(),0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET);
Ogre::RenderTexture*renderTexture = rtt_texture->getBuffer()->getRenderTarget(); renderTexture->addViewport(mCamera); renderTexture->getViewport(0)->setClearEveryFrame(true); renderTexture->getViewport(0)->setBackgroundColour(Ogre::ColourValue::Black); renderTexture->getViewport(0)->setOverlaysEnabled(false);
renderTexture->update();
Ogre::MaterialPtr renderMaterial = Ogre::MaterialManager::getSingleton() .create("RttMat", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); renderMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false); renderMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex");
mMiniScreen->setMaterial("RttMat");
public Ogre::RenderTargetListener
virtual void preRenderTargetUpdate(const Ogre::RenderTargetEvent& evt); virtual void postRenderTargetUpdate(const Ogre::RenderTargetEvent& evt);用于 在渲染纹理时,是小窗口隐藏,渲染好后再显示。