#include #include #include #include #include using namespace osg; typedef std::pair Point; // bool=true signifies a newly created point, false indicates original point. typedef std::vector PointList; typedef std::vector VertexList; // convert a vector for Vec3 into a vector of Point's. void convert(const VertexList& in,PointList& out) { out.reserve(in.size()); for(VertexList::const_iterator itr=in.begin(); itr!=in.end(); ++itr) { out.push_back(Point(0,*itr)); } } // clip the convex hull 'in' to plane to generate a clipped convex hull 'out' // return true if points remain after clipping. unsigned int clip(const Plane& plane,const PointList& in, PointList& out,unsigned int planeMask) { std::vector distance; distance.reserve(in.size()); for(PointList::const_iterator itr=in.begin(); itr!=in.end(); ++itr) { distance.push_back(plane.distance(itr->second)); } out.clear(); for(unsigned int i=0;i=0.0f) { out.push_back(in[i]); if (distance[i_1]<0.0f) { unsigned int mask = (in[i].first & in[i_1].first) | planeMask; float r = distance[i_1]/(distance[i_1]-distance[i]); out.push_back(Point(mask,in[i].second*r+in[i_1].second*(1.0f-r))); } } else if (distance[i_1]>0.0f) { unsigned int mask = (in[i].first & in[i_1].first) | planeMask; float r = distance[i_1]/(distance[i_1]-distance[i]); out.push_back(Point(mask,in[i].second*r+in[i_1].second*(1.0f-r))); } } return out.size(); } // clip the convex hull 'in' to planeList to generate a clipped convex hull 'out' // return true if points remain after clipping. unsigned int clip(const Polytope::PlaneList& planeList,const VertexList& vin,PointList& out) { PointList in; convert(vin,in); unsigned int planeMask = 0x1; for(Polytope::PlaneList::const_iterator itr=planeList.begin(); itr!=planeList.end(); ++itr) { if (!clip(*itr,in,out,planeMask)) return false; in.swap(out); planeMask <<= 1; } in.swap(out); return out.size(); } void transform(PointList& points,const osg::Matrix& matrix) { for(PointList::iterator itr=points.begin(); itr!=points.end(); ++itr) { itr->second = itr->second*matrix; } } void transform(const PointList& in,PointList& out,const osg::Matrix& matrix) { for(PointList::const_iterator itr=in.begin(); itr!=in.end(); ++itr) { out.push_back(Point(itr->first,itr->second * matrix)); } } void pushToFarPlane(PointList& points) { for(PointList::iterator itr=points.begin(); itr!=points.end(); ++itr) { itr->second.z() = 1.0f; } } void computePlanes(const PointList& front, const PointList& back, Polytope::PlaneList& planeList) { for(unsigned int i=0;isecond; ++cptr; } for(PointList::const_iterator bitr=back.begin(); bitr!=back.end(); ++bitr) { *cptr = bitr->second; ++cptr; } geoset->setCoords(coords); osg::Vec4* color = osgNew osg::Vec4[1]; color[0].set(1.0f,1.0f,1.0f,0.5f); geoset->setColors(color); geoset->setColorBinding(osg::GeoSet::BIND_OVERALL); geoset->setPrimType(osg::GeoSet::POINTS); geoset->setNumPrims(totalNumber); //cout << "totalNumber = "<addDrawable(geoset); osg::StateSet* stateset = osgNew osg::StateSet; stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF); stateset->setMode(GL_BLEND,osg::StateAttribute::ON); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); geoset->setStateSet(stateset); return geoset; } bool ShadowVolumeOccluder::computeOccluder(const NodePath& nodePath,const ConvexPlanerOccluder& occluder,CullStack& cullStack,bool createDrawables) { // std::cout<<" Computing Occluder"<=3) { // compute the points on the far plane. PointList farPoints; farPoints.reserve(points.size()); transform(points,farPoints,MVP); pushToFarPlane(farPoints); transform(farPoints,invP); // move the occlude points into projection space. transform(points,MV); // create the front face of the occluder Plane occludePlane = computeFrontPlane(points); _occluderVolume.add(occludePlane); // create the sides of the occluder computePlanes(points,farPoints,_occluderVolume.getPlaneList()); _occluderVolume.setupMask(); // if the front face is pointing away from the eye point flip the whole polytope. if (occludePlane[3]>0.0f) { _occluderVolume.flip(); } if (createDrawables && !nodePath.empty()) { osg::Group* group = dynamic_cast(nodePath.back()); if (group) { osg::Matrix invMV; invMV.invert(MV); transform(points,invMV); transform(farPoints,invMV); osg::Geode* geode = osgNew osg::Geode; group->addChild(geode); geode->addDrawable(createOccluderDrawable(points,farPoints)); } } for(ConvexPlanerOccluder::HoleList::const_iterator hitr=occluder.getHoleList().begin(); hitr!=occluder.getHoleList().end(); ++hitr) { PointList points; if (clip(cullingset.getFrustum().getPlaneList(),hitr->getVertexList(),points)>=3) { _holeList.push_back(); Polytope& polytope = _holeList.back(); // compute the points on the far plane. PointList farPoints; farPoints.reserve(points.size()); transform(points,farPoints,MVP); pushToFarPlane(farPoints); transform(farPoints,invP); // move the occlude points into projection space. transform(points,MV); // create the front face of the occluder Plane occludePlane = computeFrontPlane(points); // create the sides of the occluder computePlanes(points,farPoints,polytope.getPlaneList()); polytope.setupMask(); // if the front face is pointing away from the eye point flip the whole polytope. if (occludePlane[3]>0.0f) { polytope.flip(); } if (createDrawables && !nodePath.empty()) { osg::Group* group = dynamic_cast(nodePath.back()); if (group) { osg::Matrix invMV; invMV.invert(MV); transform(points,invMV); transform(farPoints,invMV); osg::Geode* geode = osgNew osg::Geode; group->addChild(geode); geode->addDrawable(createOccluderDrawable(points,farPoints)); } } } } return true; } else { return false; } } bool ShadowVolumeOccluder::contains(const std::vector& vertices) { if (_occluderVolume.containsAllOf(vertices)) { for(HoleList::iterator itr=_holeList.begin(); itr!=_holeList.end(); ++itr) { if (itr->contains(vertices)) return false; } return true; } return false; } bool ShadowVolumeOccluder::contains(const BoundingSphere& bound) { if (_occluderVolume.containsAllOf(bound)) { for(HoleList::iterator itr=_holeList.begin(); itr!=_holeList.end(); ++itr) { if (itr->contains(bound)) return false; } return true; } return false; } bool ShadowVolumeOccluder::contains(const BoundingBox& bound) { if (_occluderVolume.containsAllOf(bound)) { for(HoleList::iterator itr=_holeList.begin(); itr!=_holeList.end(); ++itr) { if (itr->contains(bound)) return false; } return true; } return false; }