[osg-users] Setting the transform matrices

Chris Kuliukas chris at kuliukas.com
Fri Sep 1 19:48:14 PDT 2017


Oops, forgot that most readers are on the mailing list. Here is the code which breaks with vertex attrib aliasing:


Code:
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commercial and non commercial applications,
 * as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>

#include <osg/Switch>
#include <osg/Types>
#include <osgText/Text>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>

#include <osgGA/Device>

#include <iostream>

#include <osg/ShapeDrawable>
#include <osg/MatrixTransform>
#include <osg/Point>
#include <osg/PointSprite>


#include <osgParticle/ParticleSystem>
#include <osgParticle/ParticleSystemUpdater>
#include <osgParticle/ModularEmitter>
#include <osgParticle/ModularProgram>

#include <osgParticle/AccelOperator>
#include <osgParticle/DampingOperator>
#include <osgParticle/BounceOperator>
#include <osgParticle/SinkOperator>

void createFountainEffect(osgParticle::ModularEmitter* emitter, osgParticle::ModularProgram* program)
{
	// Emit specific number of particles every frame
	osg::ref_ptr<osgParticle::RandomRateCounter> rrc = new osgParticle::RandomRateCounter;
	rrc->setRateRange(500, 2000);

	// Accelerate particles in the given gravity direction.
	osg::ref_ptr<osgParticle::AccelOperator> accel = new osgParticle::AccelOperator;
	accel->setToGravity();

	// Multiply each particle's velocity by a damping constant.
	osg::ref_ptr<osgParticle::DampingOperator> damping = new osgParticle::DampingOperator;
	damping->setDamping(0.9f);

	// Bounce particles off objects defined by one or more domains.
	// Supported domains include triangle, rectangle, plane, disk and sphere.
	// Since a bounce always happens instantaneously, it will not work correctly with unstable delta-time.
	// At present, even the floating error of dt (which are applied to ParticleSystem and Operator separately)
	// causes wrong bounce results. Some one else may have better solutions for this.
	osg::ref_ptr<osgParticle::BounceOperator> bounce = new osgParticle::BounceOperator;
	bounce->setFriction(-0.05);
	bounce->setResilience(0.35);
	bounce->addDiskDomain(osg::Vec3(0.0f, 0.0f, -2.0f), osg::Z_AXIS, 8.0f);
	bounce->addPlaneDomain(osg::Plane(osg::Z_AXIS, 5.0f));

	// Kill particles going inside/outside of specified domains.
	osg::ref_ptr<osgParticle::SinkOperator> sink = new osgParticle::SinkOperator;
	sink->setSinkStrategy(osgParticle::SinkOperator::SINK_OUTSIDE);
	sink->addSphereDomain(osg::Vec3(), 20.0f);

	emitter->setCounter(rrc.get());
	program->addOperator(accel.get());
	program->addOperator(damping.get());
	program->addOperator(bounce.get());
	program->addOperator(sink.get());
}

const std::string OSG_DATA_FOLDER("C:/Users/User/Desktop/OpenSceneGraph/OpenSceneGraph-Data/");

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

	auto useVertexAttributeAliasing = false;
	auto useModelViewAndProjectionUniforms = true;
	bool useShaders = false;
	if (argc > 1) {
		auto caseNo = atoi(argv[1]);
		// 8 pemutations of 3 options, 0-7
		// Case 4 : Black cow
		// Case 5 : Black cow, purple particle smoke
		// Case 6 : Black cow
		useVertexAttributeAliasing = (0x4 & caseNo)!=0;
		useModelViewAndProjectionUniforms = (0x2 & caseNo) != 0;
		useShaders = (0x1 & caseNo) != 0;
	}

	// use an ArgumentParser object to manage the program arguments.
	osg::ArgumentParser arguments(&argc, argv);

	osgViewer::Viewer viewer(arguments);

	std::string textureFile(OSG_DATA_FOLDER + "Images/smoke.rgb");
	while (arguments.read("--texture", textureFile)) {}

	float pointSize = 20.0f;
	while (arguments.read("--point", pointSize)) {}

	double visibilityDistance = -1.0f;
	while (arguments.read("--visibility", visibilityDistance)) {}

	bool customShape = false;
	while (arguments.read("--enable-custom")) { customShape = true; }

	unsigned int helpType = 0;
	if ((helpType = arguments.readHelpType()))
	{
		arguments.getApplicationUsage()->write(std::cout, helpType);
		return 1;
	}

	// report any errors if they have occurred when parsing the program arguments.
	if (arguments.errors())
	{
		arguments.writeErrorMessages(std::cout);
		return 1;
	}

	// set up the camera manipulators.
	{
		osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

		keyswitchManipulator->addMatrixManipulator('1', "Trackball", new osgGA::TrackballManipulator());
		keyswitchManipulator->addMatrixManipulator('2', "Flight", new osgGA::FlightManipulator());
		keyswitchManipulator->addMatrixManipulator('3', "Drive", new osgGA::DriveManipulator());
		keyswitchManipulator->addMatrixManipulator('4', "Terrain", new osgGA::TerrainManipulator());
		keyswitchManipulator->addMatrixManipulator('5', "Orbit", new osgGA::OrbitManipulator());
		keyswitchManipulator->addMatrixManipulator('6', "FirstPerson", new osgGA::FirstPersonManipulator());
		keyswitchManipulator->addMatrixManipulator('7', "Spherical", new osgGA::SphericalManipulator());

		std::string pathfile;
		double animationSpeed = 1.0;
		while (arguments.read("--speed", animationSpeed)) {}
		char keyForAnimationPath = '8';
		while (arguments.read("-p", pathfile))
		{
			osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
			if (apm || !apm->valid())
			{
				apm->setTimeScale(animationSpeed);

				unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
				keyswitchManipulator->addMatrixManipulator(keyForAnimationPath, "Path", apm);
				keyswitchManipulator->selectMatrixManipulator(num);
				++keyForAnimationPath;
			}
		}

		viewer.setCameraManipulator(keyswitchManipulator.get());
	}

	// add the state manipulator
	viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));

	// add the thread model handler
	viewer.addEventHandler(new osgViewer::ThreadingHandler);

	// add the window size toggle handler
	viewer.addEventHandler(new osgViewer::WindowSizeHandler);

	// add the stats handler
	viewer.addEventHandler(new osgViewer::StatsHandler);

	// add the help handler
	viewer.addEventHandler(new osgViewer::HelpHandler(arguments.getApplicationUsage()));

	// add the record camera path handler
	viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

	// add the LOD Scale handler
	viewer.addEventHandler(new osgViewer::LODScaleHandler);

	// add the screen capture handler
	viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);

	// load the data
	osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFiles(arguments);

	// any option left unread are converted into errors to write out later.
	arguments.reportRemainingOptionsAsUnrecognized();

	// report any errors if they have occurred when parsing the program arguments.
	if (arguments.errors())
	{
		arguments.writeErrorMessages(std::cout);
		return 1;
	}

	/***
	Customize particle template and system attributes
	***/
	osg::ref_ptr<osgParticle::ParticleSystem> ps = new osgParticle::ParticleSystem;

	ps->getDefaultParticleTemplate().setLifeTime(5.0f);

	if (customShape)
	{
		// osgParticle now supports making use of customized drawables. The draw() method will be executed
		// and display lists will be called for each particle. It is always a huge consumption of memory, and
		// hardly to use shaders to render them, so please be careful using this feature.
		ps->getDefaultParticleTemplate().setShape(osgParticle::Particle::USER);
		ps->getDefaultParticleTemplate().setDrawable(new osg::ShapeDrawable(new osg::Box(osg::Vec3(), 1.0f)));
		useShaders = false;
	}
	else
	{
		// The shader only supports rendering points at present.
		ps->getDefaultParticleTemplate().setShape(osgParticle::Particle::POINT);
	}

	// Set the visibility distance of particles, due to their Z-value in the eye coordinates.
	// Particles that are out of the distance (or behind the eye) will not be rendered.
	ps->setVisibilityDistance(visibilityDistance);

	if (useShaders)
	{
		// Set using local GLSL shaders to render particles.
		// At present, this is slightly efficient than ordinary methods. The bottlenack here seems to be the cull
		// traversal time. Operators go through the particle list again and again...
		ps->setDefaultAttributesUsingShaders(textureFile, true, 0);
	}
	else
	{
		// The default methods uses glBegin()/glEnd() pairs. Fortunately the GLBeginEndAdapter does improve the
		// process, which mimics the immediate mode with glDrawArrays().
		ps->setDefaultAttributes(textureFile, true, false, 0);

		// Without the help of shaders, we have to sort particles to make the visibility distance work. Sorting is
		// also useful in rendering transparent particles in back-to-front order.
		if (visibilityDistance>0.0)
			ps->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
	}

	// At last, to make the point sprite work, we have to set the points size and the sprite attribute.
	osg::StateSet* stateset = ps->getOrCreateStateSet();
	stateset->setAttribute(new osg::Point(pointSize));
	stateset->setTextureAttributeAndModes(0, new osg::PointSprite, osg::StateAttribute::ON);

	/***
	Construct other particle system elements, including the emitter and program
	***/
	osg::ref_ptr<osgParticle::ModularEmitter> emitter = new osgParticle::ModularEmitter;
	emitter->setParticleSystem(ps.get());

	osg::ref_ptr<osgParticle::ModularProgram> program = new osgParticle::ModularProgram;
	program->setParticleSystem(ps.get());

	createFountainEffect(emitter.get(), program.get());

	/***
	Add the entire particle system to the scene graph
	***/
	osg::ref_ptr<osg::MatrixTransform> parent = new osg::MatrixTransform;
	parent->addChild(emitter.get());
	parent->addChild(program.get());

	// The updater can receive particle systems as child drawables now. The addParticleSystem() method
	// is still usable, with which we should define another geode to contain a particle system.
	osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater = new osgParticle::ParticleSystemUpdater;
	//updater->addDrawable( ps.get() );

	osg::ref_ptr<osg::Group> root = new osg::Group;
	root->addChild(parent.get());
	root->addChild(updater.get());

	// FIXME 2010.9.19: the updater can't be a drawable; otehrwise the ParticleEffect will not work properly. why?
	updater->addParticleSystem(ps.get());

	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
	geode->addDrawable(ps.get());
	root->addChild(geode.get());

	std::string cowFile(OSG_DATA_FOLDER + "cow.osg");
	auto cow = osgDB::readNodeFile(cowFile);
	root->addChild(cow);
	
	viewer.setSceneData(root);

	viewer.realize();

	auto cams = std::vector<osg::Camera*>();


	viewer.getCameras(cams, false);
	for (int i = 0; i < cams.size(); i++) {
		if(cams.at(i)->getGraphicsContext() ) cams.at(i)->getGraphicsContext()->getState()->setUseVertexAttributeAliasing(useVertexAttributeAliasing);
		if (cams.at(i)->getGraphicsContext()) cams.at(i)->getGraphicsContext()->getState()->setUseModelViewAndProjectionUniforms(useModelViewAndProjectionUniforms);
	}

	viewer.run();


}



------------------------
http://www.hrwallingford.com/facilities/ship-simulation-centre (http://www.hrwallingford.com/facilities/ship-simulation-centre)

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=71599#71599







More information about the osg-users mailing list