查看: 3505|回复: 11

为什么自己画的矩形只有一个面呢?另外一个面是黑色的!贴纹理也是,望老师们指教!!

[复制链接]

该用户从未签到

发表于 2012-5-21 14:15:39 | 显示全部楼层 |阅读模式
如题:
我用osgGeometry画了一个矩形,然后设置了纹理坐标,但是运行后发现只有一个面能看见,是白色的(我设置材质反光颜色为白色),但是另外一个面没有颜色,是黑色的!现在的问题是怎么样能让这个矩形的两个面都有颜色,而且大楼能贴纹理贴图。没有什么思路,望老师们给个方向!谢谢!

该用户从未签到

 楼主| 发表于 2012-5-21 16:09:20 | 显示全部楼层
自己顶,在线等。。。。

该用户从未签到

发表于 2012-5-21 21:27:44 | 显示全部楼层
opengl里面有个背面剔除以及画法(顺时针逆时针)的指定。

该用户从未签到

发表于 2012-5-22 09:52:40 | 显示全部楼层
是否设置了纹理坐标

该用户从未签到

 楼主| 发表于 2012-5-22 17:07:39 | 显示全部楼层
array 发表于 2012-5-22 09:52
是否设置了纹理坐标

array老师,我设置了纹理坐标,但是估计只设置了一次,我用这个画的矩形当做一面旗子,但是当我把它放在场景中的时候,从一个面可以看见这面旗帜,但是从另外一个面就看不到旗帜了,就是什么都没有!!请问array老师,我哪些地方还没有考虑到,怎么才能解决让这个矩形的旗帜从任意的角度都能看到呢????谢谢array老师!!

该用户从未签到

 楼主| 发表于 2012-5-22 17:11:54 | 显示全部楼层
rcyboom 发表于 2012-5-21 21:27
opengl里面有个背面剔除以及画法(顺时针逆时针)的指定。

老师好!我用的是osg中的那个prerender例子(rtt相机的那个),现在是放到场景当中当做动态旗帜的时候,只能看见其中的一个面,按理来说,预想是能从各个角度都能看见这面旗子的,我是个新手,不是很明白其中的道理,还望老师多多指教!

该用户从未签到

发表于 2012-5-22 20:27:06 | 显示全部楼层
buptronin 发表于 2012-5-22 17:11
老师好!我用的是osg中的那个prerender例子(rtt相机的那个),现在是放到场景当中当做动态旗帜的时候,只 ...

这个主要是OSG默认背平面剔除,你可以设置双面渲染(LightModel),但是显示性能会下降的

该用户从未签到

发表于 2012-5-22 20:35:00 | 显示全部楼层
距我所知(也许是错误的啊,你可以参考下,最好自己去查证下,我也是新手),opengl里面只有三角形默认可以两个面可见,多边形默认是启用背面剔除功能的,你当然你自己可以关闭它,使用gldisable函数。至于opengl怎么就认为能看到的一面是正面,然后把不能看到的一面不渲染,这个就涉及opengl默认的顶点顺序的指定(顺时针,逆时针)的问题,当然这个也可以自己指定的,你百度下相关的资料就ok了。

该用户从未签到

 楼主| 发表于 2012-5-23 08:59:56 | 显示全部楼层
谢谢上边两位老师,问题解决了,设置lightMode->setTwoSide(true);就可以了!!!非常感谢!!!

该用户从未签到

 楼主| 发表于 2012-5-23 10:53:04 | 显示全部楼层
老师们,新的问题出现了,先上图吧,在这个场景中设置lightmodel是两面都可见的,但是,应用的另外一个场景当中的时候,只有一面可见了,另外一面直接变成了光杆了,没有旗帜!难道是跟场景灯光有关系吗??因为这个场景是没有灯光的,另外那个不可见的场景是加了灯光的!!!如果是灯光问题,该怎么去解决呢,再一次麻烦老师们!!!
2.jpg
1.jpg

该用户从未签到

 楼主| 发表于 2012-5-23 10:57:27 | 显示全部楼层
*/
#include "stdafx.h"

#include <osg/Node>
#include <osg/Geometry>
#include <osg/Notify>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osg/TextureRectangle>
#include <osg/ImageSequence>
#include <osg/Geode>
#include <osg/MatrixTransform>
#include <osg/Material>
#include <osg/ShapeDrawable>
#include <osg/Shape>

#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgUtil/SmoothingVisitor>
#include <osg/CullFace>
#include <osg/StateSet>
#include <osg/LightModel>
#include <osg/AlphaFunc>
#include <iostream>
using namespace std;

osg::ref_ptr<osg::Geode> createFlagGeometry(float radius,float flagzAxis,osg::Vec3 originCoodinate);

osg::ref_ptr<osg::Node> createCylinder(osg::Vec3 originCoodinate)
{
        osg::ref_ptr<osg::Geometry> cylinderGeom = new osg::Geometry;

        //计算圆柱体的顶点
        osg::ref_ptr<osg::Vec3Array> cylinderVertices = new osg::Vec3Array;
        cylinderGeom->setVertexArray( cylinderVertices.get() );
        float cylinderRadiusdown=0.02;
        float cylinderRadiusup=0.02;
        float cylinderHeight=2.5;

        //下底面顶点计算,以y轴坐标为自变量,x轴对应为因变量,最后加上世界坐标起始点
        for (float a=0.f;a<=2.0*cylinderRadiusdown;a+=2*cylinderRadiusdown/100.0)
        {   
                cylinderVertices->push_back(originCoodinate+osg::Vec3(sqrt(fabs(pow(cylinderRadiusdown,2)-pow(fabs(a-cylinderRadiusdown),2))),a,0.0f));
                cylinderVertices->push_back(originCoodinate+osg::Vec3(sqrt(fabs(pow(cylinderRadiusup,2)-pow(fabs(a*(cylinderRadiusup/cylinderRadiusdown)-cylinderRadiusup),2))),a*(cylinderRadiusup/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,cylinderHeight));
        }
        //上底面顶点计算
        for (float a=2.0*cylinderRadiusdown;a>=0;a-=2*cylinderRadiusdown/100.0)
        {
                cylinderVertices->push_back(originCoodinate+osg::Vec3(-1.0f*sqrt(fabs(pow(cylinderRadiusdown,2)-pow(fabs(a-cylinderRadiusdown),2))),a,0.0f));
                cylinderVertices->push_back(originCoodinate+osg::Vec3(-1.0f*sqrt(fabs(pow(cylinderRadiusup,2)-pow(fabs(a*(cylinderRadiusup/cylinderRadiusdown)-cylinderRadiusup),2))),a*(cylinderRadiusup/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,cylinderHeight));
        }

        //计算圆柱体各个顶点的法线
        float verticesNum=404;      
        osg::ref_ptr<osg::Vec3Array> cylinderNormal = new osg::Vec3Array;
        cylinderGeom->setNormalArray( cylinderNormal.get() );
        cylinderGeom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX);
        float x2=cylinderRadiusdown*cylinderHeight/sqrt(cylinderHeight*cylinderHeight+pow((cylinderRadiusdown-cylinderRadiusup),2));//x2为半径cylinderRadiusdown*pow(cosΘ,2),Θ角是圆柱的侧面与中轴线的夹角
        float x3=x2*(cylinderRadiusdown-cylinderRadiusup)/cylinderHeight;//x3为半径cylinderRadiusdown在圆柱侧表面的投影
        osg::Vec3 Vec3temp;
        //计算下底面的顶点法线坐标
        for (float a=-1.0*cylinderRadiusdown;a<=1.0*cylinderRadiusdown;a+=2*cylinderRadiusdown/100.0)
        {
                Vec3temp=osg::Vec3(0.0,0.0,0.0)+osg::Vec3(sqrt(fabs(pow(x2,2)-pow(a*(x2/cylinderRadiusdown),2))),a*(x2/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,x3);
                Vec3temp=Vec3temp*(1.0/sqrt(pow(Vec3temp.x(),2)+pow(Vec3temp.y(),2)+pow(Vec3temp.z(),2)));//法线归一化
                cylinderNormal->push_back(Vec3temp);
                cylinderNormal->push_back(Vec3temp);
        }

        //计算上地面的顶点法线坐标
        for (float a=1.0*cylinderRadiusdown;a>=-1.0*cylinderRadiusdown;a-=2*cylinderRadiusdown/100.0)
        {
                Vec3temp=osg::Vec3(0.0,0.0,0.0)+(osg::Vec3(-1*sqrt(fabs(pow(x2,2)-pow(a*(x2/cylinderRadiusdown),2))),a*(x2/cylinderRadiusdown),0.0f)+osg::Vec3(0.0,0.0,x3));
                Vec3temp=Vec3temp*(1.0/sqrt(pow(Vec3temp.x(),2)+pow(Vec3temp.y(),2)+pow(Vec3temp.z(),2)));
                cylinderNormal->push_back(Vec3temp);
                cylinderNormal->push_back(Vec3temp);
        }

        //各顶点颜色数组及参数设置
        osg::ref_ptr<osg::Vec4Array> cylinderColorArray = new osg::Vec4Array;
        cylinderColorArray->push_back( osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
        cylinderGeom->setColorArray( cylinderColorArray.get() );
        cylinderGeom->setColorBinding( osg::Geometry::BIND_OVERALL );
        cylinderGeom->addPrimitiveSet(new osg:rawArrays( osg:rimitiveSet::TRIANGLE_STRIP, 0,verticesNum) );

        osg::ref_ptr<osg::Geode> cylinderGeode = new osg::Geode;
        cylinderGeode->addDrawable(cylinderGeom.get());

        osg::ref_ptr<osg::MatrixTransform> flagMT = new osg::MatrixTransform;
        flagMT->addChild(createFlagGeometry(cylinderRadiusdown,cylinderHeight,originCoodinate));

        osg::ref_ptr<osg::MatrixTransform> cylinderMT = new osg::MatrixTransform();
        cylinderMT->addChild(cylinderGeode.get());
        cylinderMT->addChild(flagMT.get());

        osg::StateSet* cylinderStateset = cylinderGeode->getOrCreateStateSet();

        osg::ref_ptr<osg::Material> cylinderMaterial = new osg::Material();
        //漫反射光
        cylinderMaterial->setDiffuse( osg::Material::FRONT_AND_BACK,osg::Vec4( 1.f, 0.f, 0.f, 1.f ) );
        //镜面反射光
        cylinderMaterial->setSpecular( osg::Material::FRONT_AND_BACK,osg::Vec4( 1.f, 1.f, 1.f, 1.f ) );
        //环境反射光
        cylinderMaterial->setShininess( osg::Material::FRONT_AND_BACK, 128.f );
        cylinderStateset->setAttribute( cylinderMaterial.get() );
        cylinderStateset->setRenderingHint( osg::StateSet::OPAQUE_BIN );

        return cylinderMT.get();
}

class MyGeometryCallback : public osg::Drawable::UpdateCallback, public osg::Drawable::AttributeFunctor
{
public:
        MyGeometryCallback(const osg::Vec3& o,const osg::Vec3& x,const osg::Vec3& y,const osg::Vec3& z,double period,double xphase,double amplitude):
          _firstCall(true),
                  _startTime(0.0),
                  _time(0.0),
                  _period(period),
                  _xphase(xphase),
                  _amplitude(amplitude),
                  _origin(o),
                  _xAxis(x),
                  _yAxis(y),
                  _zAxis(z)
          {
          }

          virtual void update(osg::NodeVisitor* nv,osg::Drawable* drawable)
          {
                  const osg::FrameStamp* fs = nv->getFrameStamp();
                  double simulationTime = fs->getSimulationTime();
                  if (_firstCall)
                  {
                          _firstCall = false;
                          _startTime = simulationTime;
                  }

                  _time = simulationTime-_startTime;

                  drawable->accept(*this);
                  drawable->dirtyBound();

                  osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(drawable);
                  if (geometry)
                  {
                          osgUtil::SmoothingVisitor::smooth(*geometry);
                  }

          }

          virtual void apply(osg::Drawable::AttributeType type,unsigned int count,osg::Vec3* begin)
          {
                  if (type == osg::Drawable::VERTICES)
                  {
                          const float TwoPI=2.0f*osg::PI;
                          const float phase = -_time/_period;

                          osg::Vec3* end = begin+count;
                          for (osg::Vec3* itr=begin;itr<end;++itr)
                          {
                                  osg::Vec3 dv(*itr-_origin);
                                  osg::Vec3 local(dv*_xAxis,dv*_yAxis,dv*_zAxis);

                                  local.z() = local.x()*_amplitude*
                                          sinf(TwoPI*(phase+local.x()*_xphase));

                                  (*itr) = _origin +
                                          _xAxis*local.x()+
                                          _yAxis*local.y()+
                                          _zAxis*local.z();
                          }
                  }
          }

          bool    _firstCall;

          double  _startTime;
          double  _time;

          double  _period;
          double  _xphase;
          float   _amplitude;

          osg::Vec3   _origin;
          osg::Vec3   _xAxis;
          osg::Vec3   _yAxis;
          osg::Vec3   _zAxis;

};

osg::ref_ptr<osg::Geode> createFlagGeometry(float radius,float flagzAxis,osg::Vec3 originCoodinate)
{
        //纹理尺寸
        unsigned int tex_width =128;
        unsigned int tex_height = 64;
        bool useTextureRectangle = false;
        osg::Geometry* polyGeom = new osg::Geometry();//绘制几何体

        polyGeom->setName( "flagsurface" );//几何体的名字
        polyGeom->setDataVariance( osg::Object::DYNAMIC );
        polyGeom->setSupportsDisplayList(false);

        osg::Vec3f origin = osg::Vec3f(0.0f,radius,flagzAxis-0.3f) + originCoodinate;
        osg::Vec3 xAxis(1.0f,0.0f,0.0f);
        osg::Vec3 yAxis(0.0f,0.0f,1.0f);
        osg::Vec3 zAxis(0.0f,-1.0f,0.0f);
        float height = 0.3;
        float width = 0.5;
        int noSteps = 20;

        osg::Vec3Array* vertices = new osg::Vec3Array;
        osg::Vec3 bottom = origin;
        osg::Vec3 top = origin;
        top.z()+= height;
        osg::Vec3 dv = xAxis*(width/((float)(noSteps-1)));//以xAxis为单位向量,顶点坐标的最小单位

        osg::Vec2Array* texcoords = new osg::Vec2Array;

        // note, when we use TextureRectangle we have to scale the tex coords up to compensate.
        osg::Vec2 bottom_texcoord(0.0f,0.0f);
        osg::Vec2 top_texcoord(0.0f, useTextureRectangle ? tex_height : 1.0f);
        osg::Vec2 dv_texcoord((useTextureRectangle ? tex_width : 1.0f)/(float)(noSteps-1),0.0f);//纹理坐标的最小单位

        for(int i=0;i<noSteps;i++)
        {
                vertices->push_back(top);
                vertices->push_back(bottom);
                top+=dv;//顶部顶点以dv步进增大
                bottom+=dv;

                texcoords->push_back(top_texcoord);
                texcoords->push_back(bottom_texcoord);
                top_texcoord+=dv_texcoord;
                bottom_texcoord+=dv_texcoord;
        }

        // pass the created vertex array to the points geometry object.
        polyGeom->setVertexArray(vertices);//压入顶点坐标

        polyGeom->setTexCoordArray(0,texcoords);//压入纹理坐标

        osg::Vec4Array* colors = new osg::Vec4Array();//pushback颜色数组
        colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
        polyGeom->setColorArray(colors);
        polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL);

        polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet:UAD_STRIP,0,vertices->size()));

        // 添加纹理
        osg::Texture2D* flagTexture = new osg::Texture2D();
        flagTexture->setDataVariance(osg::Object::DYNAMIC);

        osg::Image* flagImage = osgDB::readImageFile("qizi.jpg");
        if (!flagImage)
        {
                cout << " couldn't find texture, quitting." << endl;
                return 0;
        }
        flagTexture->setImage(flagImage);

        osg::StateSet* stateset = new osg::StateSet;//创建状态集
        stateset = polyGeom->getOrCreateStateSet();
       
        //设置双面渲染
        osg::ref_ptr<osg:ightModel> lightModel = new osg::LightModel;
        lightModel->setTwoSided(true);//双面渲染
        stateset->setAttributeAndModes( lightModel.get() );

        stateset->setRenderingHint( osg::StateSet::DEFAULT_BIN );

        stateset->setTextureAttributeAndModes(0, flagTexture,osg::StateAttribute::ON);//将状态集关联到纹理

        polyGeom->setUpdateCallback(new MyGeometryCallback(origin,xAxis,yAxis,zAxis,1.0,1.0/width,0.2f));//绘制体回调函数

        osg::Geode* geode = new osg::Geode();
        geode->addDrawable(polyGeom);

        return geode;
}

int main(int argc, char **argv)
{

        // construct the viewer.
        osgViewer::Viewer viewer;

        osg::Vec3 originCoodinate = osg::Vec3(3.02756f, 368.043f, 12.3346f);//-21.373f , 242.777f , 8.535f;3.02756f, 368.043f, 12.3346f
        osg::ref_ptr<osg::Group> root = new osg::Group;
        osg::ref_ptr<osg::Node> flag = osgDB::readNodeFile( "hole1a.ive" );
        root->addChild(flag);
        root->addChild(createCylinder(originCoodinate));
代码附上,各位老师给个建议,谢谢谢谢。。。。

        viewer.setSceneData(root);

        return viewer.run();
}

该用户从未签到

发表于 2012-5-24 13:39:29 | 显示全部楼层
光照参数是否合理,是否把场景照得太亮了一片白
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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