ogre 学习笔记 - Day 7
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);
}
tweakSneakAnim();
从代码可以看出来,动画是在.skeleton里的。调整骨骼动画,通常这一步不需要的,动画通常由动画师制作好,程序不需要去修改。不在此对这一操作深入。想深入,需要对骨骼动画有所了解。现在这个阶段,可以不看。加载 mesh,确保可以获得用于bbox计算的缓冲区? 这个操作有点奇怪,先记住。HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY 硬件可写。硬件读写状态,从硬件读取数据会非常耗时。
创建动画控制器
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相关推荐
- Ogre学习笔记Basic Tutorial 前四课总结
转自:http://blog.csdn.net/yanonsoftware/article/details/1011195 OGRE Homepage:http://www.ogre3d.org/ ...
- 开源3D图形渲染引擎OGRE学习笔记
参考资料: 电子书:<Pro OGRE 3D Programming>中文翻译本 官方wiki: http://www.ogre3d.org/wiki/index.php/Main_Pag ...
- Ogre学习笔记(8):骨骼动画
OGRE 的基本动画控制是很简单的,设置一个动画的操作是这样: // Set idle animation mAnimationState = ent->getAnimationState( & ...
- Ogre 学习笔记 (二) 环境:阴影 、雾效、灯光
1. 雾效 雾的类型:线性和指数,线性雾呈线性增长厚度,指数雾呈指数增长厚度.每个单位距离的雾,后者增长的快. ColourValue fadeColour(0.9,0.9,0.9); mWindow ...
- C++ MFC 学习笔记+小型通讯录系统实现
MFC 最详细入门教程 [MFC常用函数总结](https://www.cnblogs.com/jiu0821/p/4606639.html) [C++ & MFC]https://www.c ...
- PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 call
您的位置 首页 PyTorch 学习笔记系列 PyTorch 学习笔记(六):PyTorch hook 和关于 PyTorch backward 过程的理解 发布: 2017年8月4日 7,195阅读 ...
- 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 容器云原生DevOps学习笔记——第二期:如何快速高质量的应用容器化迁移
暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...
- 2020年Yann Lecun深度学习笔记(下)
2020年Yann Lecun深度学习笔记(下)
最新文章
- 怎么查找表_MySQL索引是怎么支撑千万级表的快速查找?
- make menuconfig错误
- 系统安全攻防战:DLL注入技术详解
- Spring Session源码解析
- python反射详解
- scala的数值类型(三)
- python中日期使用_在Python中使用日期时间的每月总金额
- CodeForces - 245H Palindromes区间dp_记忆化搜索
- Ubuntu 16.04配置VNC进行远程桌面连接
- AJAX 跨域访问 — 方法大全
- oracle9i如何卸载,如何卸载oracle 9i
- 支付宝支付即时到账接口在ThinkPHP商城中的应用
- 利用WinDriver开发PCI设备驱动程序
- 工欲善其事必先利其器(一) —— VScode
- Yolov5 最简推理代码
- Dynamics CRM 数据迁移工具DataMigrationUtility
- imx6ull:uboot的make xxx_defconfig 过程分析
- target is not existed: .page-component__scroll .el-scrollbar__wrap
- 怎样删除具有trustedinstall权限的文件
- html5废弃html4什么,HTML5废弃的标签及属性
热门文章
- 语音处理 之 训练维护
- 微软逼迫Office客户切换成年度付费会员:否则月度订阅价格将提高20%
- Mac外接键盘ikbc win键无法使用问题
- js手机号中间部分隐藏****,显示前三位和后四位
- 选计算机硬盘原则和注意事项,旧电脑升级是升内存还是SSD?按照这个原则就对了!...
- 一封超级牛的数据库程序员的情书表白
- SolidWorks宏工具介绍——初识宏工具
- tree--树,最常见的复杂关系结构
- HTML5--CSS3在线编辑工具 超酷!!!(24款非常实用的CSS3工具终极收藏)
- 【Spring】JdbcTemplate常用方法使用示例