/**
 * ---|> [State]
 */
State::stateResult_t StrangeExampleRenderer::doEnableState(FrameContext & context,Node * node, const RenderParam & rp){

	if (rp.getFlag(NO_GEOMETRY) || rp.getFlag(SKIP_RENDERER))
		return State::STATE_SKIPPED;

	/// Collect all nodes in the frustum
	const auto nodes = collectNodesInFrustum<GeometryNode>(node, context.getCamera()->getFrustum());

	if(nodes.size() == 1 && nodes.front() == node) {
		WARN("This renderer must not be attached to GeometryNodes.");
		return State::STATE_SKIPPED;
	}

	/// Render all nodes with a little extra strangeness
	Geometry::Matrix4x4 m;
	float f=0;
	for(const auto & geoNode : nodes) {
		float f2=f+Util::Timer::now();
		m.setIdentity();
		m.scale(1.0+sin( f2)/40.0);
		m.rotate_deg( sin( f2/0.7)/2.0,0,1,0);
		context.getRenderingContext().pushMatrix_modelToCamera();
		context.getRenderingContext().multMatrix_modelToCamera(m);
		context.displayNode(geoNode,rp);
		context.getRenderingContext().popMatrix_modelToCamera();
		f+=137.0;

	}

	return State::STATE_SKIP_RENDERING;
}
Beispiel #2
0
State::stateResult_t SkyboxState::doEnableState(FrameContext & context, Node *, const RenderParam & rp) {
	if (rp.getFlag(NO_GEOMETRY)) {
		return State::STATE_SKIPPED;
	}

	Vec3 pos = context.getCamera()->getWorldOrigin();
	Geometry::Matrix4x4 matrix;
	matrix.translate(pos);
	context.getRenderingContext().pushMatrix_modelToCamera();
	context.getRenderingContext().multMatrix_modelToCamera(matrix);
	context.getRenderingContext().pushTexture(0);

	context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, false, Rendering::Comparison::LESS));
	context.getRenderingContext().pushAndSetLighting(Rendering::LightingParameters(false));

	Geometry::Box box(Geometry::Vec3(0.0f, 0.0f, 0.0f), sideLength);
	for (uint_fast8_t side = 0; side < 6; ++side) {
		if (!textures[side].isNull()) {
			context.getRenderingContext().setTexture(0,textures[side].get());
			const Geometry::corner_t * corners = Geometry::Helper::getCornerIndices(static_cast<Geometry::side_t> (side));
			// Reverse the corner order because we need the inner surface.
			Rendering::drawQuad(context.getRenderingContext(), box.getCorner(corners[1]), box.getCorner(corners[0]), box.getCorner(corners[3]), box.getCorner(corners[2]),Util::ColorLibrary::WHITE);

		}
	}
	context.getRenderingContext().popLighting();
	context.getRenderingContext().popDepthBuffer();
	context.getRenderingContext().popTexture(0);

	context.getRenderingContext().popMatrix_modelToCamera();
	return State::STATE_OK;
}
Beispiel #3
0
void FakeInstanceNode::doDisplay(FrameContext & frameContext, const RenderParam & rp) {
	if(fakePrototype.isNull()) {
		Node::doDisplay(frameContext, rp);
		return;
	}

	auto camera = static_cast<AbstractCameraNode*>(frameContext.getCamera()->clone());
	const Geometry::Matrix4x4f & cameraMatrix = frameContext.getCamera()->getWorldTransformationMatrix();
	camera->setRelTransformation(	fakePrototype->getWorldTransformationMatrix() 
						* getWorldToLocalMatrix() 
						* cameraMatrix);

	frameContext.pushAndSetCamera(camera);
	frameContext.displayNode(fakePrototype.get(), rp);
	frameContext.popCamera();
}
Beispiel #4
0
void OccRenderer::updateNodeInformation(FrameContext & context,Node * rootNode)const{
	/***
	 ** Vis ---|> NodeVisitor
	 ***/
	struct Vis:public NodeVisitor {
		const OccRenderer & r;
		AbstractCameraNode * camera;
		const Node * rootNode;
		int insideFrustum;
		Geometry::Vec3 camPos;

		Vis(const OccRenderer & _r, const Node * _rootNode, AbstractCameraNode * _camera) :
				r(_r), camera(_camera), rootNode(_rootNode), insideFrustum(0), camPos(_camera->getWorldOrigin()) {}
		virtual ~Vis() {}

		// ---|> NodeVisitor
		NodeVisitor::status enter(Node * node) override {
			NodeInfo * info=r.getNodeInfo(node);
			info->setActualSubtreeComplexity(0);

			// the current subtree is completely inside the frustum, so we need not to test inside this subtree
			if(insideFrustum>0){
				info->setActualFrustumStatus(Geometry::Frustum::INSIDE);
				insideFrustum++;
			}else{
				int i=camera->testBoxFrustumIntersection( node->getWorldBB());
				info->setActualFrustumStatus(i);
				if(i==Geometry::Frustum::OUTSIDE){
					return NodeVisitor::BREAK_TRAVERSAL;
				}else if(i==Geometry::Frustum::INSIDE){
					insideFrustum++;
				}
			}
			if(node->isClosed() && node!=rootNode){
				unsigned int c = insideFrustum > 0 ? countTriangles(node) : countTrianglesInFrustum(node, camera->getFrustum());
				info->increaseActualSubtreeComplexity( c );
				return BREAK_TRAVERSAL;
			}
			return CONTINUE_TRAVERSAL;
		}
		// ---|> NodeVisitor
		NodeVisitor::status leave(Node * node) override {
			if(insideFrustum>0){
				insideFrustum--;
			}
			unsigned int complexity=r.getNodeInfo(node)->getActualSubtreeComplexity();
			if(complexity>0 && rootNode!=node && node->hasParent()){
				NodeInfo * pinfo=r.getNodeInfo(node->getParent());
				pinfo->increaseActualSubtreeComplexity(complexity);
			}
			return CONTINUE_TRAVERSAL;
		}
	} visitor(*this,rootNode,context.getCamera());
	rootNode->traverse(visitor);
	return;
}
Beispiel #5
0
State::stateResult_t SurfelRenderer::doEnableState(FrameContext & context, Node * node, const RenderParam & rp) {
	State::stateResult_t result = NodeRendererState::doEnableState(context,node,rp);
	if( result == State::STATE_OK ){
		CameraNode* camera = dynamic_cast<CameraNode*>( context.getCamera() );
		if(camera){ // else: an orthographic camera is used; just re-use the previous values.
			cameraOrigin = camera->getWorldOrigin();
			projectionScale = camera->getWidth() / (std::tan((camera->getRightAngle()-camera->getLeftAngle()).rad()*0.5f)*2.0f);
		}
	
	}
	return result;
}
Beispiel #6
0
State::stateResult_t OccRenderer::showCulled(FrameContext & context,Node * rootNode, const RenderParam & rp){
	std::deque<Node *> nodes;
	nodes.push_back(rootNode);
	while(!nodes.empty()){
		Node * node=nodes.front();
		nodes.pop_front();
		NodeInfo * nInfo=getNodeInfo(node);

		if(!conditionalFrustumTest(context.getCamera()->getFrustum(), node->getWorldBB(), rp))
			continue;
		else if(node->isClosed() ){
			if(nInfo->getVisibleFrameNumber()!=frameNumber)
				context.displayNode(node,rp);
		}else {
			const auto children = getChildNodes(node);
			nodes.insert(nodes.end(), children.begin(), children.end());
		}
	}
	return State::STATE_SKIP_RENDERING;
}
bool VisibilitySubdivisionRenderer::renderCellSubset(FrameContext & context, cell_ptr cell, uint32_t budgetBegin, uint32_t budgetEnd) {
	try {
		const auto & vv = getVV(cell);

		std::vector<std::pair<float, object_ptr>> displayObjects;
		const uint32_t maxIndex = vv.getIndexCount();
		for(uint_fast32_t index = 0; index < maxIndex; ++index) {
			if(vv.getBenefits(index) == 0) {
				continue;
			}
			const VisibilityVector::costs_t costs = vv.getCosts(index);
			const VisibilityVector::benefits_t benefits = vv.getBenefits(index);
			const float score = static_cast<float>(costs) / static_cast<float>(benefits);
			displayObjects.emplace_back(score, vv.getNode(index));
		}

		const Geometry::Frustum & frustum = context.getCamera()->getFrustum();
		uint32_t renderedTriangles = 0;
		std::sort(displayObjects.begin(), displayObjects.end());
		for(const auto & objectRatioPair : displayObjects) {
			object_ptr o = objectRatioPair.second;
			Geometry::Frustum::intersection_t result = frustum.isBoxInFrustum(o->getWorldBB());
			if (result == Geometry::Frustum::intersection_t::INSIDE || result == Geometry::Frustum::intersection_t::INTERSECT) {
				if(renderedTriangles >= budgetBegin) {
					context.displayNode(o, 0);
				}
				renderedTriangles += o->getTriangleCount();
			}

			if (budgetEnd != 0 && renderedTriangles >= budgetEnd) {
				break;
			}
		}
	} catch(...) {
		// Invalid information. => Fall back to standard rendering.
		return false;
	}
	return true;
}
void ColorVisibilityEvaluator::measure(FrameContext & context, Node & node, const Geometry::Rect & rect) {
	Rendering::RenderingContext & rCtxt = context.getRenderingContext();

	// ### Set up textures for the framebuffer object. ###
	const uint32_t width = static_cast<uint32_t> (rect.getWidth());
	const uint32_t height = static_cast<uint32_t> (rect.getHeight());
	if (colorTexture == nullptr || width != static_cast<uint32_t> (colorTexture->getWidth()) || height != static_cast<uint32_t> (colorTexture->getHeight())) {
		// (Re-)Create textures with correct dimension.
		rCtxt.pushAndSetFBO(fbo.get());
		fbo->detachColorTexture(context.getRenderingContext());
		fbo->detachDepthTexture(context.getRenderingContext());
		rCtxt.popFBO();

		colorTexture = Rendering::TextureUtils::createStdTexture(width, height, true);
		depthTexture = Rendering::TextureUtils::createDepthTexture(width, height);

		// Bind textures to FBO.
		rCtxt.pushAndSetFBO(fbo.get());
		fbo->attachColorTexture(context.getRenderingContext(),colorTexture.get());
		fbo->attachDepthTexture(context.getRenderingContext(),depthTexture.get());
		rCtxt.popFBO();
	}

	// ### Render the scene into a framebuffer object. ###
	rCtxt.pushAndSetFBO(fbo.get());

	rCtxt.pushAndSetShader(getShader());
	rCtxt.clearScreen(Util::Color4f(0.0f, 0.0f, 0.0f, 0.0f));


	// Color counter for assignment of unique colors to triangles.
	// Background is black (color 0).
	int32_t currentColor = 1;


	// Collect potentially visible geometry nodes.
	const auto geoNodes = collectNodesInFrustum<GeometryNode>(&node, context.getCamera()->getFrustum());
	for(const auto & geoNode : geoNodes) {
		getShader()->setUniform(rCtxt, Rendering::Uniform("colorOffset", currentColor));
		context.displayNode(geoNode, USE_WORLD_MATRIX | NO_STATES);
		currentColor += geoNode->getTriangleCount();
	}

	rCtxt.popShader();
	rCtxt.popFBO();


	// ### Read texture and analyze colors. ###

	// Map from colors to number of occurrences.
	std::map<uint32_t, uint32_t> colorUsage;


	// Current color is compared with the previous color. If they match, the local count variable is used as cache before insertion into map is performed.
	uint32_t lastColor = 0;
	uint32_t lastCount = 0;

	colorTexture->downloadGLTexture(rCtxt);
	const uint32_t * texData = reinterpret_cast<const uint32_t *> (colorTexture->openLocalData(rCtxt));
	const uint32_t numPixels = width * height;
	for (uint_fast32_t p = 0; p < numPixels; ++p) {
		const uint32_t & color = texData[p];

		if (color == 0) {
			// Ignore background.
			continue;
		}

		if (color == lastColor) {
			++lastCount;
			continue;
		} else {
			// Insert previous color.
			if (lastColor != 0) {
				increaseColorUsage(lastColor, lastCount, colorUsage);
			}

			lastColor = color;
			lastCount = 1;
		}
	}
	if (lastColor != 0) {
		increaseColorUsage(lastColor, lastCount, colorUsage);
	}

	if (mode == SINGLE_VALUE) {
		numTrianglesVisible += colorUsage.size();
	} else {
		values->push_back(Util::GenericAttribute::createNumber(colorUsage.size()));
	}
}
Beispiel #9
0
//! ---|> Evaluator
void OccOverheadEvaluator::measure(FrameContext & context,Node & node,const Geometry::Rect & /*r*/) {

	//float currentRenderingTime=0;
	//int numTests=0;
	//int numVBO=0;
	int numPoly=0;
	Util::Color4f clearColor(0.5f, 0.5f, 0.9f, 1.0f);
	{ // 1. normal render pass
//        rc.clearScreen(0.5,0.5,0.9);
//        context.getRenderingContext().finish();
//        node.display(rc,renderingFlags);
		context.getRenderingContext().clearScreen(clearColor);
		node.display(context,renderingFlags|USE_WORLD_MATRIX);

		context.getRenderingContext().clearScreen(clearColor);
		context.getRenderingContext().finish();
		context.getStatistics().beginFrame();
		node.display(context,renderingFlags|USE_WORLD_MATRIX);
		context.getRenderingContext().finish();
		context.getStatistics().endFrame();
		numPoly=static_cast<int>(context.getStatistics().getValueAsDouble(context.getStatistics().getTrianglesCounter()));
	}

	// 2. test all group nodes if their bb is visible and collect them
	std::deque<GroupNode *> visibleGroupNodes;

	{
		// collect geometry nodes in frustum
		const auto groupNodesInVFList = collectNodesInFrustum<GroupNode>(&node,context.getCamera()->getFrustum());

		// setup occlusion queries
		int numQueries=groupNodesInVFList.size();
		if (numQueries==0) {
			values->push_back(nullptr); // TODO!!!
			return; // TODO??
		}

		auto queries = new Rendering::OcclusionQuery[numQueries];

		//  test bounding boxes
		context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, true, Rendering::Comparison::LEQUAL));
		int i=0;
		// start queries
		Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
		for(const auto & groupNode : groupNodesInVFList) {
			queries[i].begin();
//            queries[i].fastBoxTest((*it)->getWorldBB());
			Rendering::drawAbsBox(context.getRenderingContext(), groupNode->getWorldBB() );
			queries[i].end();
			++i;
		}
		Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
		i=0;
		// get results
		for(const auto & groupNode : groupNodesInVFList) {
			Geometry::Box extendedBox=groupNode->getWorldBB();
			extendedBox.resizeAbs(context.getCamera()->getNearPlane());

			if (queries[i].getResult() > 0 || extendedBox.contains(context.getCamera()->getWorldOrigin()) ) {
				visibleGroupNodes.push_back(groupNode);
			}
			++i;
		}
		context.getRenderingContext().popDepthBuffer();

		delete [] queries;
	}
	std::deque<GeometryNode *> geoNodesInVisibleGroupNodes;

	// 3. collect all direct geometry-node children
	{
		struct GeoChildrenCollector:public NodeVisitor {
			GeoChildrenCollector(std::deque<GeometryNode*> & _geoNodes,FrameContext & _context):
				geoNodes(_geoNodes),firstNode(true),frameContext(_context) {}
			virtual ~GeoChildrenCollector() {}

			std::deque<GeometryNode*> & geoNodes;
			bool firstNode;
			FrameContext & frameContext;

			// ---|> NodeVisitor
			NodeVisitor::status enter(Node * _node) override {
				// if this is the first call, continue...
				if(firstNode) {
					firstNode=false;
					return CONTINUE_TRAVERSAL;
				}
				// else collect the geometry children and break the traversal.
				GeometryNode * gn=dynamic_cast<GeometryNode *>(_node);
				if(gn){
					if(frameContext.getCamera()->testBoxFrustumIntersection( _node->getWorldBB()) != Geometry::Frustum::intersection_t::OUTSIDE)
						geoNodes.push_back(gn);
				}
				return BREAK_TRAVERSAL;
			}
		};
		for (auto & visibleGroupNode : visibleGroupNodes) {
			GeoChildrenCollector vis(geoNodesInVisibleGroupNodes,context);
			(visibleGroupNode)->traverse(vis);
		}

	}

	// 4. clear screen and measure time drawing children
	float perfectRenderingTime=0;
	{
		context.getRenderingContext().clearScreen(clearColor);

		context.getRenderingContext().finish();
		Util::Timer timer;
		timer.reset();

		for (auto & geoNodesInVisibleGroupNode : geoNodesInVisibleGroupNodes) {
			context.displayNode((geoNodesInVisibleGroupNode),renderingFlags|USE_WORLD_MATRIX);
		}

		context.getRenderingContext().finish();
		timer.stop();
		perfectRenderingTime=timer.getMilliseconds();
	}

//    // Test-costs:
//    float result=numTests!=0?(currentRenderingTime-perfectRenderingTime)/numTests:0;

	// currentRenderingTime-perfRendering:
//    float result=currentRenderingTime-perfectRenderingTime;

	float result=numPoly>0?perfectRenderingTime*1000/numPoly:0;

//    std::cout <<currentRenderingTime<<"-"<<perfectRenderingTime<<"="<<result<<"\t"<<numTests<<"\n";
//    std::cout <<numVBO<<":"<<geoNodesInVisibleGroupNodes.size()<<"\n";

//   float result=perfectRenderingTime;
//    values.push_back(currentRenderingTime);
//    values.push_back(perfectRenderingTime);
	values->push_back(new Util::_NumberAttribute<float>(result));

//    if(mode==SINGLE_VALUE){
//        if(result>renderingTime || renderingTime==0)
//            renderingTime=result;
//    }else{
//        values.push_back(result);
//    }

//    renderingTime=0;
}
State::stateResult_t VisibilitySubdivisionRenderer::doEnableState(
																	FrameContext & context,
																	Node *,
																	const RenderParam & rp) {
	if (rp.getFlag(SKIP_RENDERER)) {
		return State::STATE_SKIPPED;
	}

	if (viSu == nullptr) {
		// Invalid information. => Fall back to standard rendering.
		return State::STATE_SKIPPED;
	}

	// [AccumRendering]
	if(accumRenderingEnabled){
		// camera moved? -> start new frame
		const Geometry::Matrix4x4 & newCamMat=context.getCamera()->getWorldTransformationMatrix();
		if(newCamMat!=lastCamMatrix){
			lastCamMatrix = newCamMat;
			startRuntime=0;
		}
	}else{
		startRuntime=0;
	}
	// ----

	uint32_t renderedTriangles = 0;
	if (hold) {
		for (const auto & object : holdObjects) {
			if (debugOutput) {
				debugDisplay(renderedTriangles, object, context, rp);
			} else {
				context.displayNode(object, rp);
			}
		}
		return State::STATE_SKIP_RENDERING;
	}

	Geometry::Vec3 pos = context.getCamera()->getWorldOrigin();
	bool refreshCache = false;
	// Check if cached cell can be used.
	if (currentCell == nullptr || !currentCell->getBB().contains(pos)) {
		currentCell = viSu->getNodeAtPosition(pos);
		refreshCache = true;
	}
	if (currentCell == nullptr || !currentCell->isLeaf()) {
		// Invalid information. => Fall back to standard rendering.
		return State::STATE_SKIPPED;
	}

	if (refreshCache) {
		try {
			const auto & vv = getVV(currentCell);

			const uint32_t maxIndex = vv.getIndexCount();
			objects.clear();
			objects.reserve(maxIndex);
			for(uint_fast32_t index = 0; index < maxIndex; ++index) {
				if(vv.getBenefits(index) == 0) {
					continue;
				}
				const VisibilityVector::costs_t costs = vv.getCosts(index);
				const VisibilityVector::benefits_t benefits = vv.getBenefits(index);
				const float score = static_cast<float>(costs) / static_cast<float>(benefits);
				objects.emplace_back(score, vv.getNode(index));
			}
		} catch(...) {
			// Invalid information. => Fall back to standard rendering.
			return State::STATE_SKIPPED;
		}

		if (displayTexturedDepthMeshes) {
#ifdef MINSG_EXT_OUTOFCORE
			for (const auto & depthMesh : depthMeshes) {
				OutOfCore::getCacheManager().setUserPriority(depthMesh.get(), 0);
			}
#endif /* MINSG_EXT_OUTOFCORE */
			depthMeshes.clear();
			depthMeshes.reserve(6);
			textures.clear();
			textures.reserve(6);

			const std::string dmDirectionStrings[6] = { "-dir_x1_y0_z0", "-dir_x-1_y0_z0",
														"-dir_x0_y1_z0", "-dir_x0_y-1_z0",
														"-dir_x0_y0_z1", "-dir_x0_y0_z-1" };
			for (auto & dmDirectionString : dmDirectionStrings) {
				Util::GenericAttribute * attrib = currentCell->getAttribute("DepthMesh" + dmDirectionString);
				if (attrib == nullptr) {
					continue;
				}
				Util::FileName dmMeshPath(attrib->toString());
				Util::Reference<Rendering::Mesh> dmMesh;
#ifdef MINSG_EXT_OUTOFCORE
				Util::GenericAttribute * bbAttrib = currentCell->getAttribute("DepthMesh" + dmDirectionString + "-bounds");
				if (bbAttrib == nullptr) {
					WARN("Found depth mesh with no bounding box.");
					continue;
				}

				std::vector<float> bbValues = Util::StringUtils::toFloats(bbAttrib->toString());
				FAIL_IF(bbValues.size() != 6);
				const Geometry::Box meshBB(Geometry::Vec3(bbValues[0], bbValues[1], bbValues[2]), bbValues[3], bbValues[4], bbValues[5]);

				dmMesh = OutOfCore::addMesh(dmMeshPath, meshBB);
#else /* MINSG_EXT_OUTOFCORE */
				dmMesh = Rendering::Serialization::loadMesh(dmMeshPath);
#endif /* MINSG_EXT_OUTOFCORE */
				depthMeshes.emplace_back(dmMesh);
				// Count the depth mesh here already.
				renderedTriangles += dmMesh->getPrimitiveCount();

				Util::GenericAttribute * texAttrib = currentCell->getAttribute("Texture" + dmDirectionString);
				if (texAttrib == nullptr) {
					continue;
				}
				Util::FileName texturePath(texAttrib->toString());
				Util::Reference<Rendering::Texture> texture = Rendering::Serialization::loadTexture(texturePath);
				if (texture.isNull()) {
					WARN("Loading texture for depth mesh failed.");
					continue;
				}
				textures.emplace_back(texture);
			}
		}
	}

	const Geometry::Frustum & frustum = context.getCamera()->getFrustum();
	holdObjects.clear();
	holdObjects.reserve(objects.size());

	std::sort(objects.begin(), objects.end());
	for(const auto & ratioObjectPair : objects) {
		object_ptr o = ratioObjectPair.second;
#ifdef MINSG_EXT_OUTOFCORE
		OutOfCore::getCacheManager().setUserPriority(o->getMesh(), 5);
#endif /* MINSG_EXT_OUTOFCORE */
		
		if (conditionalFrustumTest(frustum, o->getWorldBB(), rp)) {
			// [AccumRendering]
			// skip geometry rendered in the last frame
			if(renderedTriangles<startRuntime){
				renderedTriangles += o->getTriangleCount();
				continue;
			}
			// ----

			if (debugOutput) {
				debugDisplay(renderedTriangles, o, context, rp);
			} else {
				context.displayNode(o, rp);
				renderedTriangles += o->getTriangleCount();
			}
			holdObjects.push_back(o);
		}
		if (maxRuntime != 0 && renderedTriangles >= startRuntime+maxRuntime) {
			break;
		}
	}

	// Draw the textured depth meshes at the end.
	if (displayTexturedDepthMeshes) {
		context.getRenderingContext().pushAndSetPolygonOffset(Rendering::PolygonOffsetParameters(polygonOffsetFactor, polygonOffsetUnits));
		auto texIt = textures.cbegin();
		for (const auto & depthMesh : depthMeshes) {
			context.getRenderingContext().pushAndSetShader(getTDMShader());
			context.getRenderingContext().pushAndSetTexture(0,texIt->get());
			
			if (conditionalFrustumTest(frustum, depthMesh->getBoundingBox(), rp)) {
				context.displayMesh(depthMesh.get());
			}
			context.getRenderingContext().popTexture(0);
			context.getRenderingContext().popShader();
#ifdef MINSG_EXT_OUTOFCORE
			OutOfCore::getCacheManager().setUserPriority(depthMesh.get(), 2);
#endif /* MINSG_EXT_OUTOFCORE */
			++texIt;
		}
		context.getRenderingContext().popPolygonOffset();
	}
	// [AccumRendering]
	startRuntime=renderedTriangles;
	// ----
	return State::STATE_SKIP_RENDERING;
}
Beispiel #11
0
//! (internal) Main culling method
State::stateResult_t OccRenderer::performCulling(FrameContext & context,Node * rootNode, const RenderParam & rp){
	if(mode==MODE_UNCONDITIONED){ // destroy temporal coherence
		frameNumber++;
	}
	frameNumber++;

	updateNodeInformation(context,rootNode); // ???

	// used for statistics
	unsigned int tests=0;
	int testsVisible=0;
	int testsInvisible=0;
	int occludedGeometryNodes=0;


	Statistics & statistics = context.getStatistics();

	RenderParam childParam = rp + USE_WORLD_MATRIX;

	const Geometry::Vec3 camPos=context.getCamera()->getWorldOrigin();


//	NodeDistancePriorityQueue_F2B distanceQueue(camPos);
	NodeDistancePriorityQueue_F2B distanceQueue(camPos);

	{	// add root node's children
		const auto children = getChildNodes(rootNode);
		for(auto & child : children) {
			distanceQueue.push(child);
		}
	}

	std::queue<std::pair<Rendering::OcclusionQuery, Node *>> queryQueue;

//    bool wasIdle=true;
	int idleCount=0;
	while ( (!distanceQueue.empty()) || (!queryQueue.empty() ) ) {
		bool idle=true;

		while ( !queryQueue.empty() && queryQueue.front().first.isResultAvailable() ) {
			idle=false;

			const OcclusionQuery & currentQuery = queryQueue.front().first;
			unsigned int result = currentQuery.getResult();
			Node * node = queryQueue.front().second;

			queryQueue.pop();
			NodeInfo * nodeInfo = getNodeInfo(node);

			// Node is visible?
			if (result>0 ) {

				statistics.pushEvent(Statistics::EVENT_TYPE_END_TEST_VISIBLE,nodeInfo->getActualSubtreeComplexity());

				testsVisible++;
				if (node->isClosed()) {
					// mark parents as visible
					Node * n=node;
					NodeInfo * ni=nodeInfo;
					while( ni->getVisibleFrameNumber()!=frameNumber){
						ni->setVisibleFrameNumber(frameNumber);
						n=n->getParent();
						if(n==nullptr || n==rootNode) break;
						ni=getNodeInfo(n);
					}
				}
				nodeInfo->setVisibleFrameNumber(frameNumber);

				// haben wir schon bearbeitet? -> Weiter...
				if (nodeInfo->getProcessedFrameNumber()==frameNumber)
					continue;

////                if(node->visibleFrameNumber != (frameNumber-1)){ ????
				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);

////                }
			}// Node is fully occluded?
			else {
				testsInvisible++;


				statistics.pushEvent(Statistics::EVENT_TYPE_END_TEST_INVISIBLE, nodeInfo->getActualSubtreeComplexity());

				// not processed yet?
				if (nodeInfo->getProcessedFrameNumber()!=frameNumber) {
					// TODO: Store and propagate in tree.
					occludedGeometryNodes+=collectNodesInFrustum<GeometryNode>(node,context.getCamera()->getFrustum()).size();

					// mark the node as processed
					nodeInfo->setProcessedFrameNumber(frameNumber);
				}
				// In diesem Frame verdeckt worden? (dann haben wir nicht mit der Bearbeitung gewartet und
				// die Kinder liegen bereits in der distanceQueue; die sollten jetzt �bersprungen werden)
				if ( nodeInfo->getVisibleFrameNumber() == (frameNumber-1) ) {
					if (!node->isClosed()) {
						const auto children = getChildNodes(node);
						for(auto & child : children) {
							getNodeInfo(child)->setProcessedFrameNumber(frameNumber);
							// TODO: Check if ancestors have to be removed too.
						}
					}
				}
			}
		}
		// ...
		if ( ! distanceQueue.empty()) {

			idle=false;

			Node * node=distanceQueue.top();
			NodeInfo * nodeInfo=getNodeInfo(node);
			distanceQueue.pop();

			// If the current node has already been processed, then continue.
			if (nodeInfo->getProcessedFrameNumber()==frameNumber ) continue; // ||node->isEmpty()

//			// skip empty subtrees // does never happen (checked in processNode)
//			if( nodeInfo->getActualSubtreeComplexity() == 0){
//                nullBoxes++;
//                continue;
//			}

			// Kamera innerhalb der (um die nearplane vergroesserte) Box? -> immer sichtbar
			// [2008-01-04_CJ] Bugfix: added nearplane addition; could result in dissapearing scene-parts.
			Geometry::Box extendedBox=node->getWorldBB(); //node->getGeometryBB();
			extendedBox.resizeAbs(context.getCamera()->getNearPlane());
			if (extendedBox.contains(camPos)) {

				nodeInfo->setVisibleFrameNumber(frameNumber);

				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);
				continue;
			}

			// !IS_INSIDE_FRUSTUM(node)
			if ( nodeInfo->getActualFrustumStatus()== Geometry::Frustum::OUTSIDE)
				continue;

			// [MODE_OPT_CULLING] For optimal culling, skip all unnecessary tests
			if(mode==MODE_OPT_CULLING && nodeInfo->getVisibleFrameNumber() == (frameNumber-1)){
				nodeInfo->setVisibleFrameNumber(frameNumber);
				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);
				continue;
			}

			// if query reasonable
			// TODO: Something missing here?

			{ // start occlusion test for the current node
				Rendering::OcclusionQuery query;

				Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
				query.begin();
				Rendering::drawFastAbsBox(context.getRenderingContext(), node->getWorldBB());
				query.end();
				Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
				tests++;
				queryQueue.emplace(std::move(query), node);

				statistics.pushEvent(Statistics::EVENT_TYPE_START_TEST, nodeInfo->getActualSubtreeComplexity());
			}

			// if the current node was visible in the last frame,
			//  then assume that it is also visible in this frame and process it.
			if (nodeInfo->getVisibleFrameNumber() == (frameNumber-1) ) {
				// Process node
				processNode(context,node,nodeInfo,distanceQueue,childParam);
			}

		}
//		else{
			// waiting

//		}
		if (idle) {
			statistics.pushEvent(Statistics::EVENT_TYPE_IDLE, idleCount++);
		} else {
			idleCount = 0;
		}

	}

	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestCounter(), tests);
	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestVisibleCounter(), testsVisible);
	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestInvisibleCounter(), testsInvisible);
	statistics.addValue(OcclusionCullingStatistics::instance(statistics).getCulledGeometryNodeCounter(), occludedGeometryNodes);
	statistics.pushEvent(Statistics::EVENT_TYPE_FRAME_END,0.3);

	return State::STATE_SKIP_RENDERING;
}
State::stateResult_t TwinPartitionsRenderer::doEnableState(FrameContext & context, Node *, const RenderParam & rp) {
	if (rp.getFlag(SKIP_RENDERER)) {
		return State::STATE_SKIPPED;
	}

	if (data == nullptr) {
		// Invalid information. => Fall back to standard rendering.
		return State::STATE_SKIPPED;
	}

	const Geometry::Vec3f pos = context.getCamera()->getWorldOrigin();
	// Check if cached cell can be used.
	if (currentCell == INVALID_CELL || !data->cells[currentCell].bounds.contains(pos)) {
		// Search the cell that contains the camera position.
		bool cellFound = false;
		const uint32_t cellCount = data->cells.size();
		for (uint_fast32_t cell = 0; cell < cellCount; ++cell) {
			if (data->cells[cell].bounds.contains(pos)) {
// #ifdef MINSG_EXT_OUTOFCORE
// 				// Set new priorities if the current cell changes.
// 				if (currentCell != cell) {
// 					// Low priority for old depth mesh.
// 					if (currentCell != INVALID_CELL) {
// 						for(std::vector<uint32_t>::const_iterator it = data->cells[currentCell].surroundingIds.begin(); it != data->cells[currentCell].surroundingIds.end(); ++it) {
// 							Rendering::Mesh * depthMesh = data->depthMeshes[*it].get();
// 							OutOfCore::getCacheManager().setUserPriority(depthMesh, 0);
// 						}
// 					}
// 					// High priority for new depth mesh.
// 					{
// 						for(std::vector<uint32_t>::const_iterator it = data->cells[cell].surroundingIds.begin(); it != data->cells[cell].surroundingIds.end(); ++it) {
// 							Rendering::Mesh * depthMesh = data->depthMeshes[*it].get();
// 							OutOfCore::getCacheManager().setUserPriority(depthMesh, 20);
// 						}
// 					}
// 					// Low priority for meshes visible from the old cell.
// 					if (currentCell != INVALID_CELL) {
// 						const uint32_t oldVisibleSetIndex = data->cells[currentCell].visibleSetId;
// 						const PartitionsData::visible_set_t & oldVisibleSet = data->visibleSets[oldVisibleSetIndex];
// 						for (PartitionsData::visible_set_t::const_iterator it = oldVisibleSet.begin(); it != oldVisibleSet.end(); ++it) {
// 							Rendering::Mesh * mesh = data->objects[it->second].get();
// 							OutOfCore::getCacheManager().setUserPriority(mesh, 0);
// 						}
// 					}
// 					// High priority for meshes visible from the new cell.
// 					{
// 						const uint32_t visibleSetIndex = data->cells[cell].visibleSetId;
// 						const PartitionsData::visible_set_t & visibleSet = data->visibleSets[visibleSetIndex];
// 						for (PartitionsData::visible_set_t::const_iterator it = visibleSet.begin(); it != visibleSet.end(); ++it) {
// 							Rendering::Mesh * mesh = data->objects[it->second].get();
// 							OutOfCore::getCacheManager().setUserPriority(mesh, 10);
// 						}
// 					}
// 				}
// #endif /* MINSG_EXT_OUTOFCORE */
				// Load new textures.
				textures.clear();
				if(drawTexturedDepthMeshes) {
					textures.reserve(6);
					for(auto & elem : data->cells[cell].surroundingIds) {
						const std::string & textureFile = data->textureFiles[elem];
						Util::Reference<Rendering::Texture> texture = Rendering::Serialization::loadTexture(Util::FileName(textureFile));
						if(texture == nullptr) {
							WARN("Failed to load texture for depth mesh.");
						} else {
							textures.push_back(texture);
						}
					}
				}

				currentCell = cell;
				cellFound = true;
				break;
			}
		}
		if (!cellFound) {
			// Camera outside view space.
			currentCell = INVALID_CELL;
			return State::STATE_SKIPPED;
		}
	}

	uint32_t renderedTriangles = 0;

	const uint32_t visibleSetIndex = data->cells[currentCell].visibleSetId;
	const PartitionsData::visible_set_t & visibleSet = data->visibleSets[visibleSetIndex];

	if(drawTexturedDepthMeshes) {
		for(auto & elem : data->cells[currentCell].surroundingIds) {
			Rendering::Mesh * depthMesh = data->depthMeshes[elem].get();
			// Count the depth meshes here already.
			renderedTriangles += depthMesh->getPrimitiveCount();
		}
	}
	const Geometry::Frustum & frustum = context.getCamera()->getFrustum();

	/*float minDist = 9999999.0f;
	float maxDist = 0.0f;
	float prioSum = 0.0f;
	uint_fast32_t objectCounter = 0;
	for (PartitionsData::visible_set_t::const_iterator it = visibleSet.begin(); it != visibleSet.end(); ++it) {
		Rendering::Mesh * mesh = data->objects[it->second].get();
		float dist = mesh->getBoundingBox().getDistance(pos);
		minDist = std::min(dist, minDist);
		maxDist = std::max(dist, maxDist);
		if(objectCounter < 10) {
			prioSum += it->first;
			++objectCounter;
		}
	}

	std::ofstream output("twinOutput.tsv", ios_base::out | ios_base::app);
	output << currentCell << '\t' << data->cells[currentCell].bounds.getDiameter() << '\t' << (data->cells[currentCell].bounds.getCenter() - pos).length() << '\t'
	 << visibleSet.begin()->first << '\t'
	 << visibleSet.rbegin()->first << '\t'
	 << minDist << '\t' << maxDist << '\t' << prioSum << '\t';
	for(std::vector<uint32_t>::const_iterator it = data->cells[currentCell].surroundingIds.begin(); it != data->cells[currentCell].surroundingIds.end(); ++it) {
		Rendering::Mesh * depthMesh = data->depthMeshes[*it].get();
		const Geometry::Box & depthMeshBB = depthMesh->getBoundingBox();

		const Geometry::Vec3f originalDirection = (depthMeshBB.getCenter() - data->cells[currentCell].bounds.getCenter()).normalize();
		const Geometry::Vec3f currentDirection = (depthMeshBB.getCenter() - pos).normalize();
		const float angle = currentDirection.dot(originalDirection);
		const bool visible = (frustum.isBoxInFrustum(depthMeshBB) != Frustum::OUTSIDE);
		output << '\t';
		if(visible) {

			output << angle ;
		} else {
				output << "NA";
		}
	}
	for(uint_fast32_t i = data->cells[currentCell].surroundingIds.size(); i < 6; ++i) {
		output << "\tNA";
	}
	output << std::endl;
	output.close();*/


	for (auto & elem : visibleSet) {
		Rendering::Mesh * mesh = data->objects[elem.second].get();
		if (conditionalFrustumTest(frustum, mesh->getBoundingBox(), rp)) {
			context.displayMesh(mesh);
			renderedTriangles += mesh->getPrimitiveCount();
		}
		if(rp.getFlag(BOUNDING_BOXES)) {
			Rendering::drawWireframeBox(context.getRenderingContext(), mesh->getBoundingBox(), Util::ColorLibrary::RED);
		}
		if (maxRuntime != 0 && renderedTriangles >= maxRuntime) {
			break;
		}
	}
	// Draw the textured depth meshes at the end.
	if(drawTexturedDepthMeshes) {
		context.getRenderingContext().pushAndSetPolygonOffset(Rendering::PolygonOffsetParameters(polygonOffsetFactor, polygonOffsetUnits));
		context.getRenderingContext().pushAndSetShader(getTDMShader());
		context.getRenderingContext().pushTexture(0);
		auto texIt = textures.begin();
		for(auto & elem : data->cells[currentCell].surroundingIds) {
			Rendering::Mesh * depthMesh = data->depthMeshes[elem].get();
			Rendering::Texture * texture = texIt->get();

			context.getRenderingContext().setTexture(0, texture);

			if (conditionalFrustumTest(frustum, depthMesh->getBoundingBox(), rp)) {
				context.displayMesh(depthMesh);
			}

			++texIt;
		}
		context.getRenderingContext().popTexture(0);
		context.getRenderingContext().popShader();
		context.getRenderingContext().popPolygonOffset();
	}

	return State::STATE_SKIP_RENDERING;
}
Beispiel #13
0
//! ---|> [State]
State::stateResult_t CHCRenderer::doEnableState(FrameContext & context,Node * rootNode, const RenderParam & rp){
	if(rp.getFlag(SKIP_RENDERER))
		return State::STATE_SKIPPED;
	if(debugShowVisible){
		std::deque<Node *> nodes;
		{
			const auto children = getChildNodes(rootNode);
			nodes.insert(nodes.end(), children.begin(), children.end());
		}
		while(!nodes.empty()){
			Node& node = *nodes.front();
			nodes.pop_front();
			auto& nodeInfo = getNodeInfo(node);
			if(nodeInfo.frameNr == frameNr && nodeInfo.visible){
				if(node.isClosed())
					context.displayNode(&node,rp);
				else {
					const auto children = getChildNodes(&node);
					nodes.insert(nodes.end(), children.begin(), children.end());
				}
			}
		}
	}else{
		++frameNr;
		
		// used for statistics
		unsigned int stat_numTests = 0;
		unsigned int stat_numTestsInvisible = 0;
		unsigned int stat_numTestsVisible = 0;
		Statistics & statistics = context.getStatistics();

		RenderParam childParam = rp + USE_WORLD_MATRIX;

		const auto& camera = *context.getCamera();
		const Geometry::Vec3 camPos = camera.getWorldOrigin();
		const float bbEnlargement = camera.getNearPlane();
		NodeDistancePriorityQueue_F2B distanceQueue(camPos);
		std::queue<std::pair<Rendering::OcclusionQuery, Node*>> queryQueue;

		const auto traverseNode = [&](Node& node){
			if( node.isClosed() ){ // leaf node
				context.displayNode(&node, childParam );
			}else{
				for(auto & child : getChildNodes(&node))
					distanceQueue.push(child);
			}
		};
		const auto pullUpVisibility = [&](Node& node){
			for(Node* n=&node; n&&n!=rootNode; n = n->getParent()){
				auto& nodeInfo = getNodeInfo(*n);
				if(nodeInfo.frameNr == frameNr && nodeInfo.visible)
					break;
				nodeInfo.visible = true;
				nodeInfo.frameNr = frameNr;
				
			};
		};
		const auto startQuery = [&](Node& node,const Geometry::Box& worldBoundingBox){
			Rendering::OcclusionQuery query;
			Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
			query.begin();
			Rendering::drawAbsBox(context.getRenderingContext(), worldBoundingBox );
			query.end();
			Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
			return std::make_pair(std::move(query),&node);
		};
		
		traverseNode(*rootNode);
		while(!distanceQueue.empty() || !queryQueue.empty()){
				
			// ---- PART 1: process finished occlusion queries
			while( !queryQueue.empty() && (distanceQueue.empty() || queryQueue.front().first.isResultAvailable()) ){
				if( queryQueue.front().first.getResult()>0 ){
					++stat_numTestsVisible;
					statistics.pushEvent( Statistics::EVENT_TYPE_END_TEST_VISIBLE, 1);

					Node& node = *queryQueue.front().second;
					pullUpVisibility(node);
					auto& nodeInfo = getNodeInfo( node );
					if( !nodeInfo.wasVisible )
						traverseNode(node);
				}else{
					++stat_numTestsInvisible;
					statistics.pushEvent( Statistics::EVENT_TYPE_END_TEST_INVISIBLE, 1);
				}
				queryQueue.pop();
			}
			
			// ---- PART 2: tree traversal
			if( !distanceQueue.empty() ){
				Node& node = *distanceQueue.top();
				distanceQueue.pop();
				const Geometry::Box worldBoundingBox = node.getWorldBB();
				if (camera.testBoxFrustumIntersection( node.getWorldBB()) == Geometry::Frustum::intersection_t::OUTSIDE) {
					continue;
				}
				Geometry::Box enlargedBox = worldBoundingBox;
				enlargedBox.resizeAbs( bbEnlargement );
				if( enlargedBox.contains(camPos) ){
					pullUpVisibility(node);
					traverseNode(node);
					continue;
				}
				auto& nodeInfo = getNodeInfo( node );
				// identify previously visible nodes
				const bool wasVisible = nodeInfo.frameNr == frameNr-1 && nodeInfo.visible;
				nodeInfo.wasVisible = wasVisible;
				
				// reset node's visibility flag
				nodeInfo.visible = false;
				// update node's visited flag
				nodeInfo.frameNr = frameNr;
				
				// test leafs and previously invisible nodes
				if( node.isClosed() || !wasVisible){ // on testing front
					// start test
					++stat_numTests;
					statistics.pushEvent(Statistics::EVENT_TYPE_START_TEST, 1);
					queryQueue.push( std::move(startQuery(node,worldBoundingBox)) );
				}
				// traverse a node unless it was invisible
				if( wasVisible )
					traverseNode( node );
			}
		}

		statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestVisibleCounter(), stat_numTestsVisible);
		statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestInvisibleCounter(), stat_numTestsInvisible);
		statistics.addValue(OcclusionCullingStatistics::instance(statistics).getOccTestCounter(), stat_numTests);
	}
//			std::cout << std::endl;

	return State::STATE_SKIP_RENDERING;
}
//! ---|> Evaluator
void VisibilityEvaluator::measure(FrameContext & context,Node & node,const Geometry::Rect & /*r*/) {
	// first pass - fill depth buffer.
	context.getRenderingContext().clearScreen(Util::Color4f(0.9f, 0.9f, 0.9f, 1.0f));
	node.display(context,USE_WORLD_MATRIX|FRUSTUM_CULLING);

	if (getMaxValue()->toInt() == 0.0) {
		setMaxValue_i(collectNodes<GeometryNode>(&node).size());
	}

	if (mode==SINGLE_VALUE) {

		// collect geometry nodes in frustum
		auto objectsInVFList = collectNodesInFrustum<GeometryNode>(&node, context.getCamera()->getFrustum());
		for(const auto & geoNode : objectsInVFList) {
			objectsInVF[reinterpret_cast<uintptr_t>(geoNode)] = geoNode;
		}


		// setup occlusion queries
		int numQueries=objectsInVFList.size();
		if (numQueries==0) return;


		auto queries = new Rendering::OcclusionQuery[numQueries];

		{ // optional second pass: test bounding boxes
			context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, true, Rendering::Comparison::LEQUAL));
			context.getRenderingContext().pushAndSetPolygonOffset(Rendering::PolygonOffsetParameters(0.0f, -1.0f));
			int i=0;
			// start queries
			Rendering::OcclusionQuery::enableTestMode(context.getRenderingContext());
			for(const auto & geoNode : objectsInVFList) {
				queries[i].begin();
				Rendering::drawAbsBox(context.getRenderingContext(), geoNode->getWorldBB() );
				queries[i].end();
				++i;
			}
			Rendering::OcclusionQuery::disableTestMode(context.getRenderingContext());
			i=0;
			// get results
			for(auto & geoNode : objectsInVFList) {
				if (queries[i].getResult() == 0 && !geoNode->getWorldBB().contains(context.getCamera()->getWorldOrigin()) ) {
					geoNode=nullptr;
				}
				++i;
			}
			context.getRenderingContext().popPolygonOffset();
			context.getRenderingContext().popDepthBuffer();
		}


		{ // third pass: test if nodes are exactly visible
			context.getRenderingContext().pushAndSetDepthBuffer(Rendering::DepthBufferParameters(true, true, Rendering::Comparison::EQUAL));
			int i=0;
			// start queries
			for(const auto & geoNode : objectsInVFList) {
				if (!geoNode)
					continue;
				queries[i].begin();
				// render object i
				context.displayNode(geoNode, USE_WORLD_MATRIX);
				queries[i].end();
				++i;
			}
			i=0;
			// get results
			for(const auto & geoNode : objectsInVFList) {
				if (!geoNode)
					continue;
				if (queries[i].getResult() > 0) {
					visibleObjects[reinterpret_cast<uintptr_t>(geoNode)] = geoNode;
				}
				++i;
			}
			context.getRenderingContext().popDepthBuffer();
		}

		delete [] queries;
	} else {//mode == DIRECTION_VALUES
		const auto nodes = collectVisibleNodes(&node, context);
		if(doesCountPolygons()){
			uint32_t numPolys=0;
			for(const auto & n : nodes) {
				numPolys += n->getTriangleCount();
			}
			values->push_back(new Util::_NumberAttribute<float>(numPolys));
		}else{
			values->push_back(new Util::_NumberAttribute<float>(nodes.size()));
		}

	}
}