[osg-users] Most efficient way to get the gl_ModelViewMatrix of PREVIOUS frame?

Philipp Meyer philipp.meyer at fh-bielefeld.de
Thu Jun 23 00:56:23 PDT 2016


Hi,

so here is a little update on my current progress. I have a working solution, but im not 100% happy with it as it is pretty messy and offers bad performance.

The basic idea is to assign a uniform variable to each and every transform node of the scene graph, storing its total modelMatrix so it can be accessed by the shader.

1) After building the scene graph, traverse through all nodes. Once a transform node is found, create a uniform and attach it to it. Also add an entry into a global map variable, linking the created uniform with a list of transform nodes (all parents of the current node).
2) Then, with every frame, iterate through the uniform map and calculate the current model matrices based on the matrix transform list.

This works, but there are several drawbacks:

1) If the scene graph is modified in any way after buidling the map, it will yield wrong results. So with every change of the scene graph, the map needs to be rebuilt.
2) If multiple parents share the same transform node and it is not an identity matrix transform (with no effect), the approach wont work at all because there is no unique stateset for that transform.
3) Somewhat bad performance, lots of CPU load and bottlenecking.

If anyone has a better idea about how to obtain the model matrix of the PREVIOUS frame in the vertex shader, please let me know.


Code:
void MDRT::MotionDeskRT::updatePreviousFrameModelMatrices(
		const osg::Matrix &viewMatrix) {
	if (modelMatrixUniformMap.empty()) {
		buildModelMatrixUniformMap(sceneRoot,
				std::vector<osg::MatrixTransform*>());
	}

	osg::Matrix modelMatrix;

	for (const auto & pair : modelMatrixUniformMap) {
		osg::Uniform *mmUniform = pair.first;
		const auto &mtList = pair.second;
		const size_t mtListLen = mtList.size();

		modelMatrix = mtList[0]->getMatrix();
		for (size_t i = 1; i < mtListLen; ++i) {
			modelMatrix = mtList[i]->getMatrix() * modelMatrix;
		}
		//modelViewMatrix = modelViewMatrix * viewMatrix;

		mmUniform->set(modelMatrix);
	}
}

void MDRT::MotionDeskRT::buildModelMatrixUniformMap(osg::Node* root,
		const std::vector<osg::MatrixTransform*> &matrixTransforms) {

	//all of the below only works if no matrix transforms with a matrix != identity are shared.
	//otherwise, all use the same state set, which will make it impossible
	//to have a unique uniform storing the individual overall transform of a MT node.
	osg::Group *group = dynamic_cast<osg::Group*>(root);
	if (!group) {
		return; //is leaf and not MT
	}

	const unsigned int childCount = group->getNumChildren();
	osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(group);

	if (mt && mt->getMatrix() != osg::Matrix::identity()) {
		//is matrix transform, update modelview matrix
		auto modifiedMatrixTransforms = matrixTransforms;
		if (mt->getReferenceFrame()
				!= osg::Transform::ReferenceFrame::RELATIVE_RF) {
			//this mt doesnt use relative reference frame, and therefore ignores all parent MTs when calculating the final model matrix.
			modifiedMatrixTransforms.clear();
		}
		modifiedMatrixTransforms.push_back(mt);

		osg::Uniform *mmUniform = mt->getOrCreateStateSet()->getOrCreateUniform(
				"oldModelMatrix", osg::Uniform::Type::FLOAT_MAT4, 1);

		modelMatrixUniformMap[mmUniform] = modifiedMatrixTransforms;

		for (unsigned int cid = 0; cid < childCount; ++cid) {
			buildModelMatrixUniformMap(group->getChild(cid),
					modifiedMatrixTransforms);
		}

		return;
	}

	for (unsigned int cid = 0; cid < childCount; ++cid) {
		buildModelMatrixUniformMap(group->getChild(cid), matrixTransforms);
	}

}




Thank you!

Cheers,
Philipp

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








More information about the osg-users mailing list