osg解析系列-[Cull] - osg::Occluder的应用示例

// M23.11.W5.Cull.Occluder.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <Windows.h>

//osg
#include <osg/Texture2D>
#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/Geometry>
#include <osg/Material>
#include <osg/PolygonMode>
#include <osg/PolygonOffset>
#include <osg/OccluderNode>

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgGA/AnimationPathManipulator>

//osgAnimation
#include <osgAnimation/BasicAnimationManager>
#include <osgAnimation/Channel>
#include <osgAnimation/UpdateMatrixTransform>
#include <osgAnimation/StackedTranslateElement>
#include <osgAnimation/StackedRotateAxisElement>

//osgAnimation-skeleton
#include <osgAnimation/Bone>
#include <osgAnimation/Skeleton>
#include <osgAnimation/RigGeometry>
#include <osgAnimation/UpdateBone>
#include <osgAnimation/StackedTransform>
#include <osgAnimation/StackedTranslateElement>
#include <osgAnimation/StackedRotateAxisElement>

#include <osgAnimation/AnimationManagerBase>
#include <osgAnimation/TimelineAnimationManager>
#include <osgAnimation/ActionStripAnimation>
#include <osgAnimation/ActionBlendIn>
#include <osgAnimation/ActionBlendOut>
#include <osgAnimation/ActionAnimation>

//osglib
#pragma comment(lib,"OpenThreads_d.lib")
#pragma comment(lib,"osg_d.lib")
#pragma comment(lib,"osgDB_d.lib")
#pragma comment(lib,"osgFX_d.lib")
#pragma comment(lib,"osgGA_d.lib")
#pragma comment(lib,"osgUtil_d.lib")
#pragma comment(lib,"osgViewer_d.lib")
#pragma comment(lib,"osgShadow_d.lib")
#pragma comment(lib,"osgAnimation_d.lib")

osg::Node* createOccluder(const osg::Vec3& v1, const osg::Vec3& v2, const osg::Vec3& v3, const osg::Vec3& v4, float holeRatio = -1.0f)
{
	// create an occluder which will sit alongside the loaded model.
	osg::OccluderNode* occluderNode = new osg::OccluderNode;

	// create the convex planar occluder
	osg::ConvexPlanarOccluder* cpo = new osg::ConvexPlanarOccluder;

	// attach it to the occluder node.
	occluderNode->setOccluder(cpo);
	occluderNode->setName("occluder");

	// set the occluder up for the front face of the bounding box.
	osg::ConvexPlanarPolygon& occluder = cpo->getOccluder();
	occluder.add(v1);
	occluder.add(v2);
	occluder.add(v3);
	occluder.add(v4);

	// create a hole at the center of the occluder if needed.
	if (holeRatio > 0.0f)
	{
		// create hole.
		float ratio = holeRatio;
		float one_minus_ratio = 1 - ratio;
		osg::Vec3 center = (v1 + v2 + v3 + v4)*0.25f;
		osg::Vec3 v1dash = v1*ratio + center*one_minus_ratio;
		osg::Vec3 v2dash = v2*ratio + center*one_minus_ratio;
		osg::Vec3 v3dash = v3*ratio + center*one_minus_ratio;
		osg::Vec3 v4dash = v4*ratio + center*one_minus_ratio;

		osg::ConvexPlanarPolygon hole;
		hole.add(v1dash);
		hole.add(v2dash);
		hole.add(v3dash);
		hole.add(v4dash);

		cpo->addHole(hole);
	}

	osg::Geode* geode = new osg::Geode;
	// 绘制出遮挡面、以及遮挡面上留的洞口
	{// create a drawable for occluder.
		osg::Geometry* geom = new osg::Geometry;

		osg::Vec3Array* coords = new osg::Vec3Array(occluder.getVertexList().begin(), occluder.getVertexList().end());
		std::vector<osg::ConvexPlanarPolygon> & vHole = cpo->getHoleList();
		geom->setVertexArray(coords);

		osg::Vec4Array* colors = new osg::Vec4Array(1);
		(*colors)[0].set(0.0f, 1.0f, 1.0f, 0.5f);
		geom->setColorArray(colors, osg::Array::BIND_OVERALL);

		geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

		geode->addDrawable(geom);

		osg::StateSet* stateset = new osg::StateSet;
		stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
		stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
		stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
		//stateset->setRenderingHint(osg::StateSet::OPAQUE_BIN);
		geom->setStateSet(stateset);

		for (const auto & planar : vHole)
		{
			// create a drawable for occluder.
			osg::Geometry* geomhole = new osg::Geometry;

			osg::Vec3Array* coordshole = new osg::Vec3Array(planar.getVertexList().begin(), planar.getVertexList().end());
			geomhole->setVertexArray(coordshole);
			geomhole->setColorArray(colors, osg::Array::BIND_OVERALL);
			geomhole->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
			geode->addDrawable(geomhole);

			osg::StateSet* statesethole = new osg::StateSet;
			osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode;
			polymode->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
			statesethole->setAttributeAndModes(polymode, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);

			geomhole->setStateSet(statesethole);
		}
	}

	// add the occluder geode as a child of the occluder,
	// as the occluder can't self occlude its subgraph the
	// geode will never be occluded by this occluder.
	occluderNode->addChild(geode);

	return occluderNode;

}

osg::Group* createOccludersAroundModel(osg::Node* model)
{
	osg::Group* scene = new osg::Group;
	scene->setName("rootgroup");

	// add the loaded model into a the scene group.
	scene->addChild(model);
	model->setName("model");

	// get the bounding volume of the model.
	const osg::BoundingSphere bs = model->getBound();
	// create a bounding box around the sphere.
	osg::BoundingBox bb;
	bb.expandBy(bs);

	// 包围盒的6个面当做 遮挡面
	// front
	scene->addChild(createOccluder(bb.corner(0),bb.corner(1),bb.corner(5),bb.corner(4)));
	// right side
	scene->addChild(createOccluder(bb.corner(1),bb.corner(3),bb.corner(7),bb.corner(5)));
	// left side
	scene->addChild(createOccluder(bb.corner(2),bb.corner(0),bb.corner(4),bb.corner(6)));
	// back side
	scene->addChild(createOccluder(bb.corner(3),bb.corner(2),bb.corner(6),bb.corner(7)));
	// bottom side
	scene->addChild(createOccluder(bb.corner(1),bb.corner(0),bb.corner(2),bb.corner(3)));
	// top side
	// create a hole half the size of the occluder.
	scene->addChild(createOccluder(bb.corner(5),bb.corner(4),bb.corner(6),bb.corner(7), 0.5)); 

	return scene;
}

int main(int argc, char* argv[])
{
	osg::ArgumentParser psr(&argc, argv);
	osgViewer::Viewer viewer(psr);
	viewer.setCameraManipulator(new osgGA::TrackballManipulator());

	osg::ref_ptr<osg::Node> loadedmodel = osgDB::readRefNodeFile("Data/cow.osg");
	osg::ref_ptr<osg::Group> rootnode = createOccludersAroundModel(loadedmodel.get());
	viewer.setSceneData(rootnode);

	viewer.run();
    return 0;
}


运行效果:
模拟从洞口往盒子里看 如图
在这里插入图片描述
模拟从盒子不带洞口的面往里看

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值