查看: 1924|回复: 15

前后两个mirror节点有什么区别吗?为什么要添加2个mirror啊?osgreflect实例!

[复制链接]

该用户从未签到

发表于 2012-9-20 10:39:48 | 显示全部楼层 |阅读模式
代码如下:
osg:rawable* mirror = createMirrorSurface(xMin,xMax,yMin,yMax,z);
osg::MatrixTransform* rootNode = new osg::MatrixTransform;      
{
        osg::Stencil* stencil = new osg::Stencil;
        stencil->setFunction(osg::Stencil::ALWAYS,1,~0u);
        stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE);


        osg::StateSet* statesetBin1 = new osg::StateSet();        
        statesetBin1->setAttributeAndModes(stencil,osg::StateAttribute::ON);

        osg::Geode* geode = new osg::Geode;
        geode->addDrawable(mirror); //第一个,添加第一个

        geode->setStateSet(statesetBin1);

        rootNode->addChild(geode);

}
{
        osg::Stencil* stencil = new osg::Stencil;
        stencil->setFunction(osg::Stencil::EQUAL,1,~0u);
        stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
               
        osg::Depth* depth = new osg::Depth;
        depth->setFunction(osg::Depth::ALWAYS);
        depth->setRange(1.0,1.0);


        osg::StateSet* statesetBin3 = new osg::StateSet();

        statesetBin3->setAttributeAndModes(stencil,osg::StateAttribute::ON);
        statesetBin3->setAttribute(depth);

        osg::Geode* geode = new osg::Geode;
        geode->addDrawable(mirror);   //第二个,添加第二个
        geode->setStateSet(statesetBin3);

        rootNode->addChild(geode);

}
{
        osg::StateSet* dstate = new osg::StateSet();
        osg::Stencil* stencil = new osg::Stencil;
        stencil->setFunction(osg::Stencil::EQUAL,1,~0u);
        stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);
        dstate->setAttributeAndModes(stencil,osg::StateAttribute::ON);

        osg::MatrixTransform* reverseMatrix = new osg::MatrixTransform;
        reverseMatrix->setStateSet(dstate);
        reverseMatrix->preMult(osg::Matrix::translate(0.0f,0.0f,-z)*osg::Matrix::scale(1.0f,1.0f,-1.0f)*osg::Matrix::translate(0.0f,0.0f,z));

        reverseMatrix->addChild(model);

        rootNode->addChild(reverseMatrix);

}

该用户从未签到

发表于 2012-9-20 11:25:58 | 显示全部楼层
因为模板缓冲区只能通过绘制来进行比较变化,所以必须进行两遍绘制

该用户从未签到

发表于 2012-9-20 11:29:50 | 显示全部楼层

该用户从未签到

 楼主| 发表于 2012-9-20 12:00:03 | 显示全部楼层
本帖最后由 sunnk 于 2012-9-20 12:02 编辑
liuzhiyu123 发表于 2012-9-20 11:25
因为模板缓冲区只能通过绘制来进行比较变化,所以必须进行两遍绘制


那我开始绘制了一个地形进入场景,之后使用MFC的消息响应才使用模板测试隐藏一部分地形,该怎么办?
开始绘制的时候没有开启模板测试!

第一:添加了一个地形以及一些模型到场景
第二:运行程序
第三:响应一个消息,比如:鼠标左键在地图上点几个点,然后在地形下面创建一个几何体
然后就是隐藏几何体前面的地形,看到几何体

我在消息响应以后使用的代码:
root->addChild(underside);  //地形下面的一个四方形
osg::Group* s3d = libo::getGlobalViewer().getSceneMgr()->getScene3d();
osg::Group* ground = new osg::Group;
int num = s3d->getNumChildren();
for (int i =0; i <num; ++i)
{
        osg::Node* node = s3d->getChild(i);
        if (node && node->getName() == "地形")
        {
                ground = node->asGroup();
        }
}

{
        osg::Stencil* stencil = new osg::Stencil;
        stencil->setFunction(osg::Stencil::ALWAYS,1,0xFF);
        stencil->setOperation(osg::Stencil::KEEP,osg::Stencil::KEEP,osg::Stencil::REPLACE);
        ground->getOrCreateStateSet()->setAttributeAndModes(stencil,osg::StateAttribute::ON);
}
{
        osg::Stencil* stencil = new osg::Stencil;
        ground->getOrCreateStateSet()->setAttributeAndModes(stencil,osg::StateAttribute::ON);
        stencil->setFunction(osg::Stencil::EQUAL,1,0xFF);
        stencil->setOperation(osg::Stencil::KEEP,osg::Stencil::KEEP,osg::Stencil::KEEP);

        osg:epth* depth = new osg::Depth;
        depth->setFunction(osg::Depth::ALWAYS);
        depth->setRange(1.0,1.0);

        ground->getOrCreateStateSet()->setAttributeAndModes(stencil,osg::StateAttribute::ON);
        ground->getOrCreateStateSet()->setAttribute(depth);
}
{
        osg::Stencil* stencil = new osg::Stencil;
        stencil->setFunction(osg::Stencil::EQUAL,1,0xFF);
        stencil->setOperation(osg::Stencil::KEEP,osg::Stencil::KEEP,osg::Stencil::KEEP);
        root->getOrCreateStateSet()->setAttributeAndModes(stencil,osg::StateAttribute::ON);
}
m_group_3d->addChild(root.get());

模板测试的时候,工作流程是先绘制一个模型,(如:地形进入缓存),setFunction(osg::Stencil::ALWAYS,,)和setOperation设置他的模板值;然后在绘制另外一个模型,使用setFunction(osg::Stencil::EQUAL,,)与之前的模型模板值比较?我一直看到这2个函数!OpenGL里面也是这2个函数!就是不是很清楚模板测试的时候工作流程是怎么样的!
求大侠解惑!!!

该用户从未签到

发表于 2012-9-20 12:26:17 | 显示全部楼层
sunnk 发表于 2012-9-20 12:00
那我开始绘制了一个地形进入场景,之后使用MFC的消息响应才使用模板测试隐藏一部分地形,该怎么办?
开 ...

找一下关于模板缓冲区使用的讲解,很容易明白

该用户从未签到

 楼主| 发表于 2012-9-20 15:53:21 | 显示全部楼层
liuzhiyu123 发表于 2012-9-20 12:26
找一下关于模板缓冲区使用的讲解,很容易明白

找到了一些介绍!看了之后还有点疑问!那些OpenGL例子都是先开启模板缓存模式!再绘制的图形!我这里是本来开始就有的!我需要把场景中的地形节点的属性状态设置好,复制一份场景,然后替换原来的场景;还是和那些例子一样直接设置;或者去最开始加入地形的地方设置模板值?
还有就是OSG清空缓存用的哪个函数啊?一直都是直接使用!都没清空过!
麻烦了啊!

该用户从未签到

 楼主| 发表于 2012-9-20 17:22:52 | 显示全部楼层
liuzhiyu123 发表于 2012-9-20 12:26
找一下关于模板缓冲区使用的讲解,很容易明白

我实现了!就是不知道方法是不是正确的!只是效果实现了!非常感谢您的帮助!!!谢谢!!!

该用户从未签到

 楼主| 发表于 2012-9-20 17:23:14 | 显示全部楼层
非常感谢大家的帮助!!谢谢!!!

该用户从未签到

 楼主| 发表于 2012-9-20 18:29:44 | 显示全部楼层
liuzhiyu123 发表于 2012-9-20 11:25
因为模板缓冲区只能通过绘制来进行比较变化,所以必须进行两遍绘制

{
        osg::ref_ptr<osg::StateSet> stateset = ground->getOrCreateStateSet();
        osg::ref_ptr<osg::Group> root = ground;                                     //ground中保存的是在场景中的地形
        osg::ref_ptr<osg::Stencil> stencil = new osg::Stencil();
        stencil->setFunction(osg::Stencil::ALWAYS,1,0xFF);
        stencil->setOperation(osg::Stencil::REPLACE,osg::Stencil::REPLACE,osg::Stencil::REPLACE);
        stateset->setAttributeAndModes(stencil.get(),osg::StateAttribute::ON);
        ground->setStateSet(stateset.get());
}
{
        osg::ref_ptr<osg::StateSet> stateset = m_group_3d->getOrCreateStateSet();

        osg::ref_ptr<osg::Stencil> stencil = new osg::Stencil();
        stencil->setFunction(osg::Stencil::ALWAYS,2,0xFF);
        stencil->setOperation(osg::Stencil::KEEP,osg::Stencil::REPLACE,osg::Stencil::REPLACE);
        stateset->setAttributeAndModes(stencil.get(),osg::StateAttribute::ON);
        m_group_3d->setStateSet(stateset.get());         //m_group_3d保存的是在响应鼠标选择消息后在地形下面绘制的几何体
}
{
        osg::ref_ptr<osg::StateSet> stateset = ground->getOrCreateStateSet();
        osg::ref_ptr<osg::Group> root = ground;
        osg::ref_ptr<osg::Stencil> stencil = new osg::Stencil();
        stencil->setFunction(osg::Stencil::EQUAL,1,0xFF);
        stencil->setOperation(osg::Stencil::REPLACE,osg::Stencil::KEEP,osg::Stencil::KEEP);

        stateset->setAttributeAndModes(stencil.get(),osg::StateAttribute::ON);
        ground->setStateSet(stateset.get());       //ground中保存的是地形
}
不知道这个方法有没有问题!求大侠指正!!!

该用户从未签到

发表于 2012-9-21 15:18:09 | 显示全部楼层
sunnk 发表于 2012-9-20 18:29
{
        osg::ref_ptr stateset = ground->getOrCreateStateSet();
        osg::ref_ptr root = ground;           ...

我想知道你在外面设置了其他参数么?比如深度缓存和ColorMask?用你的方式我没有实现,但是不知道为什么?

该用户从未签到

 楼主| 发表于 2012-9-21 17:26:04 | 显示全部楼层
本帖最后由 sunnk 于 2012-9-21 17:26 编辑
Berly 发表于 2012-9-21 15:18
我想知道你在外面设置了其他参数么?比如深度缓存和ColorMask?用你的方式我没有实现,但是不知道为什么?


我在外面没有其他相关模板测试的设置了!我的功能就是鼠标在地形上点几个点!根据交集测试获取这几个点!以这几个点以及他们的Z坐标减少相同值的几个点来创建的一个只有五个面的几何体!在地上看就像挖去了一块!
比如说鼠标在地形上点击选择了4个点!P1,P2,P3,P4
我在把他们的Z值减少P1.z -= 5,P2.z -= 5,....后面2个点一样!
这样八个点绘制的模型,直接加入的m_ground_3d节点中!
分2次绘制的!一次绘制的底面,一次绘制的四周!

该用户从未签到

发表于 2012-9-23 12:20:17 | 显示全部楼层
sunnk 发表于 2012-9-21 17:26
我在外面没有其他相关模板测试的设置了!我的功能就是鼠标在地形上点几个点!根据交集测试获取这几个点 ...

你是指画了一个槽状的模型对么?这样就可以了么?

该用户从未签到

 楼主| 发表于 2012-9-24 10:45:23 | 显示全部楼层
Berly 发表于 2012-9-23 12:20
你是指画了一个槽状的模型对么?这样就可以了么?

恩!画了个槽状模型!

该用户从未签到

发表于 2012-9-24 11:26:03 | 显示全部楼层
sunnk 发表于 2012-9-24 10:45
恩!画了个槽状模型!

那你的各个面的法线是怎么设置的呢?

该用户从未签到

 楼主| 发表于 2012-9-24 17:00:53 | 显示全部楼层
Berly 发表于 2012-9-24 11:26
那你的各个面的法线是怎么设置的呢?

这个。。。。。绘制图形不是我做的!貌似模板测试和这些木有关系啊!
我直接重新绘制了个四边形!什么都没有设置!就顶点数组和颜色数组!然后模板测试能通过!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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