ogre 学习笔记 - Day 7


[Sample_ParticleFX]

粒子效果

    void setupParticles(){ParticleSystem::setDefaultNonVisibleUpdateTimeout(5);  // set nonvisible timeoutParticleSystem* ps;// create some nice fireworks and place it at the originps = mSceneMgr->createParticleSystem("Fireworks", "Examples/Fireworks");mSceneMgr->getRootSceneNode()->attachObject(ps);// create a green nimbus around the ogre headps = mSceneMgr->createParticleSystem("Nimbus", "Examples/GreenyNimbus");mSceneMgr->getRootSceneNode()->attachObject(ps);ps = mSceneMgr->createParticleSystem("Rain", "Examples/Rain");  // create a rainstormps->fastForward(5);   // fast-forward the rain so it looks more naturalmSceneMgr->getRootSceneNode()->createChildSceneNode(Vector3(0, 1000, 0))->attachObject(ps);// create aureola around ogre head perpendicular to the groundps = mSceneMgr->createParticleSystem("Aureola", "Examples/Aureola");mSceneMgr->getRootSceneNode()->attachObject(ps);// create shared pivot node for spinning the fountainsmFountainPivot = mSceneMgr->getRootSceneNode()->createChildSceneNode();ps = mSceneMgr->createParticleSystem("Fountain1", "Examples/PurpleFountain");  // create fountain 1// attach the fountain to a child node of the pivot at a distance and anglemFountainPivot->createChildSceneNode(Vector3(200, -100, 0), Quaternion(Degree(20), Vector3::UNIT_Z))->attachObject(ps);ps = mSceneMgr->createParticleSystem("Fountain2", "Examples/PurpleFountain");  // create fountain 2// attach the fountain to a child node of the pivot at a distance and anglemFountainPivot->createChildSceneNode(Vector3(-200, -100, 0), Quaternion(Degree(-20), Vector3::UNIT_Z))->attachObject(ps);}

ps = mSceneMgr->createParticleSystem(“Fireworks”, “Examples/Fireworks”);

粒子材质

particle_system Examples/Fireworks
{material Examples/Flarepoint_rendering            falseparticle_width             10particle_height            10cull_each                  falsequota                      1000emit_emitter_quota         10billboard_type             point// Emitter that emits multiple Point emitters with name 'explosion'emitter Box{name                    mainEmitteremit_emitter            explosionangle                   30emission_rate           1000time_to_live            3direction               0 1 0velocity                200}// This Point emitter is emitted by the Box emitter and emits billboard particles itselfemitter Point{name                    explosionangle                   180emission_rate           100time_to_live            2direction               0 1 0velocity                80duration                -1repeat_delay_min        2repeat_delay_max        3}// Make em float downwardsaffector LinearForce{force_vector            0 -100 0force_application       add}// Give em some nice coloursaffector ColourInterpolator{time0                   0colour0                 1 1 0time1                   0.5colour1                 1 0 0time2                   0.9colour2                 0 0 1}
}

粒子以及粒子发射器属性配置,暂时不深究

mSceneMgr->getRootSceneNode()->attachObject(ps);
这里有个注意点,创建的所有的ParticleSystem都 attach 到了 RootSceneNode 上。
也就是说 相同类型的 object 可以 attach 多个到同一节点上,也就意味着不能通过类型获取到 object。

[Sample_Shadows]

阴影

    if (mRoot->getRenderSystem()->getCapabilities()->hasCapability(RSC_HWSTENCIL)){mSceneMgr->setShadowTechnique(SHADOWTYPE_STENCIL_MODULATIVE);mCurrentShadowTechnique = SHADOWTYPE_STENCIL_MODULATIVE;}else{mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);mCurrentShadowTechnique = SHADOWTYPE_TEXTURE_MODULATIVE;}

启用阴影


pPlaneEnt->setCastShadows(false);

设置是否产生阴影


mSceneMgr->setShadowTextureSettings(1024, 2);

设置基于纹理阴影的纹理属性


mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));

设置阴影颜色


mSceneMgr->setShadowTexturePixelFormat(PF_BYTE_RGBA);

设置基于纹理阴影的纹理像素格式


mSceneMgr->setShadowTextureCasterMaterial(themat);

设置阴影的材质


mSceneMgr->setShadowTextureSelfShadow(true);

设置是否启用基于纹理阴影的自阴影


[Sample_SkeletalAnimation]

骨骼动画

void setupContent()
{mShaderGenerator->invalidateScheme(Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);mViewport->setMaterialScheme(RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);//Add the hardware skinning to the shader generator default render statemSrsHardwareSkinning = mShaderGenerator->createSubRenderState<RTShader::HardwareSkinning>();Ogre::RTShader::RenderState* renderState = mShaderGenerator->getRenderState(Ogre::RTShader::ShaderGenerator::DEFAULT_SCHEME_NAME);renderState->addTemplateSubRenderState(mSrsHardwareSkinning);
}

设置RTSystem属性,并启用硬件蒙皮

SkeletonPtr skel = static_pointer_cast<Skeleton>(SkeletonManager::getSingleton().load("jaiqua.skeleton",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME));

加载骨骼

void setupModels()
{tweakSneakAnim();SceneNode* sn = NULL;Entity* ent = NULL;AnimationState* as = NULL;// make sure we can get the buffers for bbox calculationsMeshManager::getSingleton().load("jaiqua.mesh",ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY,HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, true, true);auto& controllerMgr = ControllerManager::getSingleton();for (int i = 0; i < NUM_MODELS; i++){// create scene nodes for the models at regular angular intervalssn = mSceneMgr->getRootSceneNode()->createChildSceneNode();sn->yaw(Radian(Math::TWO_PI * (float)i / (float)NUM_MODELS));sn->translate(0, 0, -20, Node::TS_LOCAL);mModelNodes.push_back(sn);// create and attach a jaiqua entityent = mSceneMgr->createEntity("Jaiqua" + StringConverter::toString(i + 1), "jaiqua.mesh");ent->setMaterialName("jaiqua");sn->attachObject(ent);// enable the entity's sneaking animation at a random speed and loop it manually since translation is involvedas = ent->getAnimationState("Sneak");as->setEnabled(true);as->setLoop(false);controllerMgr.createController(controllerMgr.getFrameTimeSource(),AnimationStateControllerValue::create(as, true),ScaleControllerFunction::create(Math::RangeRandom(0.5, 1.5)));mAnimStates.push_back(as);}// create name and value for skinning modeStringVector names;names.push_back("Help");names.push_back("Skinning");names.push_back(mBoneBoundingBoxesItemName);// create a params panel to display the help and skinning modemStatusPanel = mTrayMgr->createParamsPanel(TL_TOPLEFT, "HelpMessage", 200, names);mStatusPanel->setParamValue("Help", "H / F1");String value = "Software";enableBoneBoundingBoxMode( false );  // update status panel entry// change the value if hardware skinning is enabledMaterialPtr entityMaterial = ent->getSubEntity(0)->getMaterial();if(entityMaterial){Technique* bestTechnique = entityMaterial->getBestTechnique();if(bestTechnique){Pass* pass = bestTechnique->getPass(0);if (pass && pass->hasVertexProgram() && pass->getVertexProgram()->isSkeletalAnimationIncluded()) {value = "Hardware";}}}mStatusPanel->setParamValue("Skinning", value);
}
  1. tweakSneakAnim();
    从代码可以看出来,动画是在.skeleton里的。调整骨骼动画,通常这一步不需要的,动画通常由动画师制作好,程序不需要去修改。不在此对这一操作深入。想深入,需要对骨骼动画有所了解。现在这个阶段,可以不看。

  2. 加载 mesh,确保可以获得用于bbox计算的缓冲区? 这个操作有点奇怪,先记住。HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY 硬件可写。硬件读写状态,从硬件读取数据会非常耗时。

  3. 创建动画控制器

    auto& controllerMgr = ControllerManager::getSingleton();for (int i = 0; i < NUM_MODELS; i++)
    {// create scene nodes for the models at regular angular intervalssn = mSceneMgr->getRootSceneNode()->createChildSceneNode();sn->yaw(Radian(Math::TWO_PI * (float)i / (float)NUM_MODELS));sn->translate(0, 0, -20, Node::TS_LOCAL);mModelNodes.push_back(sn);// create and attach a jaiqua entityent = mSceneMgr->createEntity("Jaiqua" + StringConverter::toString(i + 1), "jaiqua.mesh");ent->setMaterialName("jaiqua");sn->attachObject(ent);// enable the entity's sneaking animation at a random speed and loop it manually since translation is involvedas = ent->getAnimationState("Sneak");as->setEnabled(true);as->setLoop(false);controllerMgr.createController(controllerMgr.getFrameTimeSource(),AnimationStateControllerValue::create(as, true),ScaleControllerFunction::create(Math::RangeRandom(0.5, 1.5)));mAnimStates.push_back(as);
    }
    

    从上面的操作,只创建了一个mesh Entity,并没有绑定骨骼。然后就开始获取AnimationState。因为动画在skeleton里,能获取就说明绑定了,什么时候绑定的?
    看看 Entity的代码,发现里面有 Mesh,Mesh里有skeleton,通过调试,发现,在 read Mesh的时候,有一个 M_MESH_SKELETON_LINK。也就是说在读取mesh的时候就绑定了骨骼。

    • 调试过程
      找到Mesh 中有String mSkeletonName; SkeletonPtr mSkeleton; 之后,搜索 "mSkeletonName = " 赋值的地方,发现只有3个,每个地方下一个断点。调试,走到了 Mesh::setSkeletonName。查看调用堆栈,找到了 readMesh -> readSkeletonLink.

    Controller<Real>* ControllerManager::createController(const ControllerValueRealPtr& src,const ControllerValueRealPtr& dest, const ControllerFunctionRealPtr& func);
    

    创建动画控制器,该函数没有详细的说明。看看 Controller 类。这个类很简单,除了一个get,set,只有一个Updata

    void update(void)
    {if(mEnabled)mDest->setValue(mFunc->calculate(mSource->getValue()));
    }
    

    AnimationStateControllerValue::create(as, true),通过entity获取到的AnimationState创建一个ControllerValue,该ControllerValue应该是绑定在 该Entity的AnimationState上。
    通过第三个参数func,与第一个参数计算当前的值,设置给Dest。
    按照这个猜测,上面应该是获取ControllerManager最后一帧的时间,给获取到的AnimationState 随机加 [0.5 - 1.5] 的时间。

[Terrain]

地形

void setupContent()
{//! [terrain_create]mTerrainGroup = new Ogre::TerrainGroup(mSceneMgr, Ogre::Terrain::ALIGN_X_Z, TERRAIN_SIZE, TERRAIN_WORLD_SIZE);mTerrainGroup->setFilenameConvention(TERRAIN_FILE_PREFIX, TERRAIN_FILE_SUFFIX);mTerrainGroup->setOrigin(mTerrainPos);//! [terrain_create]configureTerrainDefaults(l);
#ifdef PAGING// Paging setupmPageManager = OGRE_NEW PageManager();// Since we're not loading any pages from .page files, we need a way just// to say we've loaded them without them actually being loadedmPageManager->setPageProvider(&mDummyPageProvider);mPageManager->addCamera(mCamera);mTerrainPaging = OGRE_NEW TerrainPaging(mPageManager);PagedWorld* world = mPageManager->createWorld();mTerrainPaging->createWorldSection(world, mTerrainGroup, 2000, 3000,TERRAIN_PAGE_MIN_X, TERRAIN_PAGE_MIN_Y,TERRAIN_PAGE_MAX_X, TERRAIN_PAGE_MAX_Y);
#else//! [define_loop]for (long x = TERRAIN_PAGE_MIN_X; x <= TERRAIN_PAGE_MAX_X; ++x)for (long y = TERRAIN_PAGE_MIN_Y; y <= TERRAIN_PAGE_MAX_Y; ++y)defineTerrain(x, y);// sync load since we want everything in place when we startmTerrainGroup->loadAllTerrains(true);//! [define_loop]
#endif
//! [init_blend]if (mTerrainsImported){for (const auto& ti : mTerrainGroup->getTerrainSlots()){initBlendMaps(ti.second->instance);}}mTerrainGroup->freeTemporaryResources();//! [init_blend]
}

先创建一个 TreeainGroup, 指定场景;对齐方式(指定一个平面),这里是XZ平面(水平面);地形大小(顶点数);在世界当中的大小

TerrainGroup::TerrainGroup(SceneManager* sm, Terrain::Alignment align, uint16 terrainSize, Real terrainWorldSize)
{}

mTerrainGroup->setFilenameConvention 设置命名约定?
mTerrainGroup->defineTerrain(x, y, 0.0f); 定义一个指定位置的固定高度

       String filename = mTerrainGroup->generateFilename(x, y);if (ResourceGroupManager::getSingleton().resourceExists(mTerrainGroup->getResourceGroup(), filename)){mTerrainGroup->defineTerrain(x, y);}else{Image img;getTerrainImage(x % 2 != 0, y % 2 != 0, img);mTerrainGroup->defineTerrain(x, y, &img);mTerrainsImported = true;}

按照定义生成一个dat文件

mTerrainGroup->loadAllTerrains(true);

导入地形,参数:是否异步。


从这两天对几个特定sample的学习,发现ogre在每个功能的基本使用上都挺简单的。

但是,随着时间的推移,一步步深入,越来越多的东西没有理解,都只能去按照注释简单的翻译,无法知道它的具体作用。终归为对ogre的实现都没有深入的去看。

毕竟这是一个学习过程。

所以到这里,把引擎最基本的功能(Material, Mesh, Scene, Light, Skybox, Particle, Skybox, Shadow, Animation, Terrain)稍微过了一遍之后,剩下的sample就暂时不看了,那些sample基本都是一些高级应用,看了也无法真正理解(说难听点,就是看也看不懂)。

接下来去看这些基本功能的代码,去分析理解代码。

ogre 学习笔记 - Day 7相关推荐

  1. Ogre学习笔记Basic Tutorial 前四课总结

    转自:http://blog.csdn.net/yanonsoftware/article/details/1011195 OGRE Homepage:http://www.ogre3d.org/   ...

  2. 开源3D图形渲染引擎OGRE学习笔记

    参考资料: 电子书:<Pro OGRE 3D Programming>中文翻译本 官方wiki: http://www.ogre3d.org/wiki/index.php/Main_Pag ...

  3. Ogre学习笔记(8):骨骼动画

    OGRE 的基本动画控制是很简单的,设置一个动画的操作是这样: // Set idle animation mAnimationState = ent->getAnimationState( & ...

  4. Ogre 学习笔记 (二) 环境:阴影 、雾效、灯光

    1. 雾效 雾的类型:线性和指数,线性雾呈线性增长厚度,指数雾呈指数增长厚度.每个单位距离的雾,后者增长的快. ColourValue fadeColour(0.9,0.9,0.9); mWindow ...

  5. C++ MFC 学习笔记+小型通讯录系统实现

    MFC 最详细入门教程 [MFC常用函数总结](https://www.cnblogs.com/jiu0821/p/4606639.html) [C++ & MFC]https://www.c ...

  6. PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call

    您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...

  7. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  8. 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  9. 2020年Yann Lecun深度学习笔记(下)

    2020年Yann Lecun深度学习笔记(下)

最新文章

  1. 怎么查找表_MySQL索引是怎么支撑千万级表的快速查找?
  2. make menuconfig错误
  3. 系统安全攻防战:DLL注入技术详解
  4. Spring Session源码解析
  5. python反射详解
  6. scala的数值类型(三)
  7. python中日期使用_在Python中使用日期时间的每月总金额
  8. CodeForces - 245H Palindromes区间dp_记忆化搜索
  9. Ubuntu 16.04配置VNC进行远程桌面连接
  10. AJAX 跨域访问 — 方法大全
  11. oracle9i如何卸载,如何卸载oracle 9i
  12. 支付宝支付即时到账接口在ThinkPHP商城中的应用
  13. 利用WinDriver开发PCI设备驱动程序
  14. 工欲善其事必先利其器(一) —— VScode
  15. Yolov5 最简推理代码
  16. Dynamics CRM 数据迁移工具DataMigrationUtility
  17. imx6ull:uboot的make xxx_defconfig 过程分析
  18. target is not existed: .page-component__scroll .el-scrollbar__wrap
  19. 怎样删除具有trustedinstall权限的文件
  20. html5废弃html4什么,HTML5废弃的标签及属性

热门文章

  1. 语音处理 之 训练维护
  2. 微软逼迫Office客户切换成年度付费会员:否则月度订阅价格将提高20%
  3. Mac外接键盘ikbc win键无法使用问题
  4. js手机号中间部分隐藏****,显示前三位和后四位
  5. 选计算机硬盘原则和注意事项,旧电脑升级是升内存还是SSD?按照这个原则就对了!...
  6. 一封超级牛的数据库程序员的情书表白
  7. SolidWorks宏工具介绍——初识宏工具
  8. tree--树,最常见的复杂关系结构
  9. HTML5--CSS3在线编辑工具 超酷!!!(24款非常实用的CSS3工具终极收藏)
  10. 【Spring】JdbcTemplate常用方法使用示例