查看: 3449|回复: 27

新人求助:粒子系统案例——喷水

[复制链接]

该用户从未签到

发表于 2012-10-10 10:44:30 | 显示全部楼层 |阅读模式
本帖最后由 mxl12315 于 2012-10-15 10:54 编辑

    最近学习了下书中粒子系统这章,仿照喷泉做个消防车的喷水效果,水的弧度和粒子大小还算满意,但水柱很短。。本以为方向设定好后,粒子数目多一些,速度变大,这样使粒子因为大的速度而喷的更远,形成一个长长的、基本保持弧度的效果,可始终还是老样子~求助各位做过这方面的高手,看看我代码中哪部分需要修改?
PS:我看过论坛里以前这方面的例子,甚至我按照人家的效果数据设置,可是差强人意~

问题截图:
111.bmp
水柱太短,很小~但粒子效果和弧度还可以

该用户从未签到

 楼主| 发表于 2012-10-10 14:29:05 | 显示全部楼层
我又调节了我注释黑体的代码处,结果喷水的长度达到了,但是成为“冲击波”了。。。晕了,各位高手看看我的代码哪些地方导致这些问题效果?具体如何调节数值呢?

222.bmp

该用户从未签到

发表于 2012-10-11 10:06:46 | 显示全部楼层
调节发射速度就可以了,也没什么特别的技巧

该用户从未签到

 楼主| 发表于 2012-10-12 10:10:16 | 显示全部楼层
各位大侠,有谁知道为什么osg自带的osgParticle::SegmentPlacer做出的粒子效果是向上发射的呢?粒子柱虽然是起点发射到终点,但是各个粒子却是向上的(见上图)。。我将粒子的生命周期调小,水柱确实变细了,但是仔细看,每个粒子都是直接冲向Z轴上方直至消失的。。。。求解~

该用户从未签到

发表于 2012-10-13 00:50:45 | 显示全部楼层
首先你把空气阻力删掉,试一下效果!

然后删掉空气阻力后,在代码中再添加一个更新器再试试
                 osg::ref_ptr<osgParticle:articleSystemUpdater> psu1 = new osgParticle::ParticleSystemUpdater();
                 //关联粒子系统
                 psu1->addParticleSystem(ps.get());
                root->addChild(psu1.get());
绝对应该没有问题了~
两种效果自己选吧

该用户从未签到

 楼主| 发表于 2012-10-15 10:52:48 | 显示全部楼层
本帖最后由 mxl12315 于 2012-10-17 12:36 编辑
buaahc 发表于 2012-10-13 00:50
首先你把空气阻力删掉,试一下效果!

然后删掉空气阻力后,在代码中再添加一个更新器再试试


高人啊~呵呵,去掉后确实跟我想要的近似了,但与真实的水柱还是欠缺些效果,您看我下面的截图,水柱在喷的过程中,虽然弧度和喷水的扇形散射出来了,可是从水管口开始就这样了。。。您看看我的代码中是哪里的问题?需要改动什么数值才能达到真实效果(下下图)呢?我试过粒子数目、半径和发射速度,但是还这样。。。

问题效果:
问题.bmp

代码:
        
        //创建发射器计数器,调整每一帧增加的粒子的数目
        osg::ref_ptr<osgParticle::RandomRateCounter> counter = new osgParticle::RandomRateCounter();  

        //设置每秒添加的粒子的个数
        counter->setRateRange(180.0f, 280.0f);

        //关联计数器
        emitter->setCounter(counter.get());

        //设置一个点放置器
        osg::ref_ptr<osgParticle:ointPlacer> placer = new osgParticle::PointPlacer();

        //设置位置
        placer->setCenter(osg::Vec3(63.2f,49.7f,10.6f));

        //关联点放置器
        emitter->setPlacer(placer.get());

        //创建弧度发射器
        osg::ref_ptr<osgParticle::RadialShooter> shooter = new osgParticle::RadialShooter();

        //设置发射器速度变化范围
        shooter->setInitialSpeedRange(50.0f, 5.0f);

        //喷水弧度
        shooter->setThetaRange(-osg::PI_2+osg::PI_4*0.8,-osg::PI_2+osg::PI_4*0.8);
        shooter->setPhiRange(osg::PI_2,osg::PI_2);

        //关联发射器
        emitter->setShooter(shooter.get());

想要的效果:
20091108_182300.jpg

该用户从未签到

发表于 2012-10-15 19:26:17 | 显示全部楼层

不是让你定义两个更新器么
        osg::ref_ptr<osgParticle:articleSystemUpdater> psu = new osgParticle::ParticleSystemUpdater();
        //关联粒子系统
        psu->addParticleSystem(ps.get());
osg::ref_ptr<osgParticle::ParticleSystemUpdater> psu1 = new osgParticle::ParticleSystemUpdater();
        //关联粒子系统
        psu1->addParticleSystem(ps.get());
root->addChild(psu.get());
root->addChild(psu1.get());
这样试试

不行再说
还有为什么让你删掉空气阻力,你想你设定重量那点小,空气阻力肯定对他影响大啊,一根鸡毛你为什么扔不远,就是空气阻力的原因,
所以你可以把质量设定的大一点,然后加上阻力再试试,

该用户从未签到

发表于 2012-10-15 21:45:47 | 显示全部楼层
我给你调试了一下
修改这么几个方面:
粒子模板加上
        ptemplate.setShape(osgParticle:article:UAD);
这样setSizeRange()会产生效果
其次 速度设定为shooter->setInitialSpeedRange(12.0f, 15.0f);
关键是粒子的生命周期设定为6s或以上
ptemplate.setLifeTime(6.0f);
粒子数目最好不要超过太多,800以内吧
至于粒子更新器,你添加一个也行,添加两个试试效果,你想用几个就用几个,
ok自己选吧。。。

该用户从未签到

 楼主| 发表于 2012-10-16 13:49:09 | 显示全部楼层
buaahc 发表于 2012-10-15 21:45
我给你调试了一下
修改这么几个方面:
粒子模板加上

确实如您所说,全都正确了~现在OK了,以前没从事过粒子系统的学习,见笑了
   我还想向您请教一个问题,osg自带的osgParticle::SegmentPlacer做出的粒子效果中,每个粒子是向正上方发射的,但是粒子汇聚成的粒子束又是线段型,这是为什么呢?难道不能调节这个线段放置器中每个粒子方向嘛??还是它还有待完善。。


111.bmp

该用户从未签到

发表于 2012-10-16 20:26:53 | 显示全部楼层
不好意思我也没有深入研究过那个放置器。。
还有别的问题么

该用户从未签到

 楼主| 发表于 2012-10-17 11:53:35 | 显示全部楼层
buaahc 发表于 2012-10-16 20:26
不好意思我也没有深入研究过那个放置器。。
还有别的问题么

目前还有两个小问题哈:
  (1)我现在用的是osgParticle::RadialShooter中的“->setInitialSpeedRange”方法设置速度的,但是是个速度范围哈~我看过粒子系统还有一个设置初始速度,还有一个对每个粒子本身设置速度。。。但我很困惑的是,比如说喷泉,为什么粒子系统没有一个平均速度的设置?这样貌似更加方便,不像是在那个速度范围中随机选取一个速度。。。(PS:或者我没学到那里)
  (2)osgParticle:article 中只有一个"->setLifeTime()"方法,用来设置粒子的生命周期,可我想得到整个喷水过程的时间,我的意思是,比如两个点,从出水点喷到建筑物所用的时间,这个您能给我点播下吗?(PS:速度范围中系统总是随机选取的,无法按照“距离/速度=时间”)

        麻烦您了,有时间回复哈~新手见谅~

该用户从未签到

发表于 2012-10-18 19:39:51 | 显示全部楼层
这个应该没有,
再说你载入的场景中的 量纲是什么?厘米还是米 还是千米
还有粒子系统的量纲是什么 这些都需要考虑
粒子系统中设置的速度单位是什么等等
粒子系统就是个模拟
喷不到你可以加大速度,慢慢调试。不像数学计算出一个速度安上就行了。。。

该用户从未签到

 楼主| 发表于 2012-10-19 22:21:22 | 显示全部楼层
buaahc 发表于 2012-10-18 19:39
这个应该没有,
再说你载入的场景中的 量纲是什么?厘米还是米 还是千米
还有粒子系统的量纲是什么 这些都 ...

谢谢您~我还是采取您建议的方式做出了效果~如果以后还有问题,向您请教哈~

该用户从未签到

发表于 2013-1-7 16:41:17 | 显示全部楼层
mxl12315 发表于 2012-10-17 11:53
目前还有两个小问题哈:
  (1)我现在用的是osgParticle::RadialShooter中的“->setInitialSpeedRange” ...

大神,问您个问题啊,我想让粒子往下喷,该如何调节参数啊,调了很长时间,都没有调处来。多谢多谢!

该用户从未签到

发表于 2013-1-7 22:22:16 | 显示全部楼层
使用setThetaRange和 setPhiRange调角度

该用户从未签到

发表于 2013-1-7 22:22:43 | 显示全部楼层
liuweiwei9 发表于 2013-1-7 16:41
大神,问您个问题啊,我想让粒子往下喷,该如何调节参数啊,调了很长时间,都没有调处来。多谢多谢!


使用setThetaRange和 setPhiRange调角度

该用户从未签到

发表于 2013-1-8 10:33:02 | 显示全部楼层
liuweiwei9 发表于 2013-1-7 16:41
大神,问您个问题啊,我想让粒子往下喷,该如何调节参数啊,调了很长时间,都没有调处来。多谢多谢!

小雀雀朝下

该用户从未签到

发表于 2013-1-8 21:38:57 | 显示全部楼层
buaahc 发表于 2013-1-7 22:22
使用setThetaRange和 setPhiRange调角度

恩,这个问题解决了,现在有这样一个问题,我想每一帧都改变喷出粒子的数量,该如何做,请大神指教。

该用户从未签到

发表于 2013-1-9 11:22:23 | 显示全部楼层
自己写一个专用的Counter对象即可

该用户从未签到

发表于 2013-3-10 08:46:44 | 显示全部楼层
buaahc 发表于 2012-10-18 19:39
这个应该没有,
再说你载入的场景中的 量纲是什么?厘米还是米 还是千米
还有粒子系统的量纲是什么 这些都 ...

找了好久终于找到了。大神,我想请教一下量纲问题,我做的是喷泉,当放入场景后喷的总是太低,达不到效果。实际中的应该有2m但我做的只能喷20cm左右不到膝盖高,不管我怎么调重量,速度,生命周期。。。都达不到效果,所以我想问是不是量纲问题,我的场景是3dmax做的,里面的默认单位是cm,粒子系统的书上说是m,所以我想问下这个有什么关系没??应该怎么弄???谢谢!

该用户从未签到

发表于 2013-3-10 15:38:26 | 显示全部楼层
学习中………………

该用户从未签到

发表于 2013-3-11 23:53:45 | 显示全部楼层
1162810317 发表于 2013-3-10 08:46
找了好久终于找到了。大神,我想请教一下量纲问题,我做的是喷泉,当放入场景后喷的总是太低,达不到效果 ...

你把空气阻力去掉试试,再不行就改重力参数值
其实就是不断调整初始速度,这没有什么高深的。。。

该用户从未签到

发表于 2013-3-12 07:06:54 | 显示全部楼层
buaahc 发表于 2013-3-11 23:53
你把空气阻力去掉试试,再不行就改重力参数值
其实就是不断调整初始速度,这没有什么高深的。。。

按你上面说的做了,貌似不行,初速度什么的都调了很久了就是没用,速度大了成一条直线,,,,,然后就是没往上喷的水会比较多(有一部分水是往下滴的,,,,,)我就是想确定下是不是单位问题,,,,,粒子系统的单位能不能改啊??????谢谢!

该用户从未签到

发表于 2013-3-13 23:45:24 | 显示全部楼层
本帖最后由 buaahc 于 2013-3-13 23:46 编辑

1

该用户从未签到

发表于 2013-3-13 23:46:06 | 显示全部楼层
1162810317 发表于 2013-3-12 07:06
按你上面说的做了,貌似不行,初速度什么的都调了很久了就是没用,速度大了成一条直线,,,,,然后就是 ...

其实最好的方法就是贴出问题代码 让大家给解决一下,你这样说 我不知道怎么判断问题所在

该用户从未签到

发表于 2013-3-14 09:50:15 | 显示全部楼层
buaahc 发表于 2013-3-13 23:46
其实最好的方法就是贴出问题代码 让大家给解决一下,你这样说 我不知道怎么判断问题所在

嗯,行上代码,还请大神指点!
class CONDUIT_DLL Conduit
{
public:
  Conduit(void);
  ~Conduit(void);
  osgParticle:articleSystem * CreateConduitScene(osg::Group* root);  
  float m_fTheNum;  
  float m_fTheSize; //单位:m
  float m_fTheSpeech; //单位:米/秒  
  float m_fmass;// 单位:千克
  float m_flifetime;//单位:s

  osg::Node * CreateConduit(osg::Group * root);   
  osg::Vec3 m_VecPosition;
  void setconduit(float speed,float size,float num,float mass,float life);
};//Conduit.h 结束
#define CONDUIT_DLL _declspec(dllexport)
#include "Conduit.h"
Conduit::Conduit(void) : m_fTheNum(800)
, m_fTheSize(0.5)
, m_fTheSpeech(1000)
,m_fmass(0.02)
,m_flifetime(5)
{
    //默认位置
  m_VecPosition.set (15, 64, 3) ;
}
Conduit::~Conduit(void)
{
}
osgParticle::ParticleSystem * Conduit::CreateConduitScene(osg::Group* root)
{
  osgParticle::Particle ptemplate;
//生周期为 2,对于喷泉已经够了
     ptemplate.setLifeTime(m_flifetime);  
         
         ptemplate.setShape(osgParticle::Particle :UAD);

   //设置图形变化范围
     ptemplate.setSizeRange(osgParticle::rangef(0.1f, 0.5f));   //单位:m
   //设置透明度变化范围
     ptemplate.setAlphaRange(osgParticle::rangef(1.0f, 0.5f));   
     //设置颜色范围
         ptemplate.setColorRange(osgParticle::rangev4(  osg::Vec4(0.7f, 1.0f, 1.0f, 1.5f),   
         osg::Vec4(0.8f, 0.8f, 1.0f, 0.0f)));   
      //设置半径
     ptemplate.setRadius(m_fTheSize);      
     //  设置重量
     ptemplate.setMass(m_fmass);      
     osgParticle::ParticleSystem *ps = new osgParticle::ParticleSystem;
     ps->setDefaultAttributes("Images/smoke.rgb", true, true);//纹理 ,是否放射粒子,是否光照
     //加入模版  
    ps->setDefaultParticleTemplate(ptemplate);   
     //建立发射器,中包含发射枪,数目及位置设定
   osgParticle::ModularEmitter *emitter = new osgParticle::ModularEmitter;   

     //加入模版及总属性
  emitter->setParticleSystem(ps);        
       //数目变化      
  osgParticle::RandomRateCounter *counter = new osgParticle::RandomRateCounter;      
  //数目变化,当前场景中的粒子数目变化范围
  counter->setRateRange(m_fTheNum, m_fTheNum); // 生成 m_fTheNum 到 m_fTheNum 个粒子每秒
  
     //加入到发射器中
emitter->setCounter(counter);   
  //设置位置

  osgParticle::PointPlacer *placer = new osgParticle::PointPlacer;   
     placer->setCenter(m_VecPosition);
     //加入到发射器中
  emitter->setPlacer(placer);   
     //设置发射枪,可以设置初速度等
osgParticle::RadialShooter *shooter = new osgParticle::RadialShooter;   
//设置速度范围
     shooter->setInitialSpeedRange(m_fTheSpeech, 0);
     emitter->setShooter(shooter);
     root->addChild(emitter);

   //设置影响操作,
     osgParticle::ModularProgram *program = new osgParticle::ModularProgram;  
     program->setParticleSystem(ps);

   //速度操作
     osgParticle::AccelOperator *op1 = new osgParticle::AccelOperator;
     op1->setToGravity();
     program->addOperator(op1);
     osgParticle::FluidFrictionOperator *op3 = new osgParticle::FluidFrictionOperator;
     op3->setFluidToAir();
     program->addOperator(op3); //空气阻力
     root->addChild(program);

     osg::Geode *geode = new osg::Geode;
     geode->addDrawable(ps);
     root->addChild(geode);
     return ps;
}
osg::Node * Conduit::CreateConduit(osg::Group * root)
{
       osgParticle::ParticleSystem *ps2 = CreateConduitScene(root);  
           osgParticle::ParticleSystem *ps3 = CreateConduitScene(root);
         osgParticle::ParticleSystemUpdater *psu = new osgParticle::ParticleSystemUpdater;
         psu->addParticleSystem(ps2);
                   psu->addParticleSystem(ps3);

    return psu ;
}
void Conduit::setconduit (float speed,float size,float num,float mass,float life)
{
                m_fTheSpeech=speed;
         m_fTheNum=num;  
         m_fTheSize=size;
         m_fmass=mass;
         m_flifetime=life;
}
        //Conduit.cpp 结束
int main(int, char**)
{
        float speed=1050,size=0.06,num=700,positionx=0;
        osg::ref_ptr<osgViewer::Viewer>viewer = new osgViewer::Viewer ();   
        osg::Group * node = new osg::Group ;
        //在此处加入喷泉
        Conduit od[3] ;
        for(int i=0;i<3;i++)
        {
                od.setconduit (speed,size,num,0.08f,3.0f);
                od.m_VecPosition .set (positionx, 0, 0) ;
                node ->addChild (od.CreateConduit (node)) ;
                speed+=100;
                num+=100;
                positionx+=1;
        }

        viewer->setSceneData(node);
        viewer->realize();  
        viewer->run ();
        return 0;
} 谢谢!

该用户从未签到

发表于 2013-3-20 23:42:16 | 显示全部楼层
1162810317 发表于 2013-3-14 09:50
嗯,行上代码,还请大神指点!
class CONDUIT_DLL Conduit
{

不还意思,最近一周多没有上论坛。。。。
你的程序代码没有什么问题。。。
但是你设置的速度太大了1050肯定不对。。。设计的小一点,尽量小,比如20。。。
还有        //设置速度范围: shooter->setInitialSpeedRange(m_fTheSpeech, 0);两个值中任何一个都不要出现0值,这样会出现往下喷的现象, 都设置为比较小的范围,比如 shooter->setInitialSpeedRange(m_fTheSpeech, 10)。。。
这样应该就行了,你试一下,
我猜你可能是在比较大的场景添加粒子系统,可能需要很大的效果,但是你可以通过设置粒子的大小变化范围来实现,而不是通过巨大的速度来实现。。。

该用户从未签到

发表于 2013-3-21 09:47:10 | 显示全部楼层
buaahc 发表于 2013-3-20 23:42
不还意思,最近一周多没有上论坛。。。。
你的程序代码没有什么问题。。。
但是你设置的速度太大了1050 ...

非常感谢,我回去再试试。谢谢!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表