Example #1
0
NodeRendererResult SurfelRenderer::displayNode(FrameContext & context, Node * node, const RenderParam & /*rp*/){
	
	static const Util::StringIdentifier SURFEL_ATTRIBUTE("surfels");
	auto surfelAttribute = dynamic_cast<Util::ReferenceAttribute<Rendering::Mesh>*>(node->findAttribute( SURFEL_ATTRIBUTE ));
		
	if( !surfelAttribute || !surfelAttribute->get())
		return NodeRendererResult::PASS_ON;

	Rendering::Mesh& surfelMesh = *surfelAttribute->get();
	
	
	const Geometry::Rect projection = context.getProjectedRect(node);
	const float approxProjectedSideLength =  std::sqrt(projection.getHeight() * projection.getWidth());

//	const auto& worldBB = node->getWorldBB();
//	const float approxProjectedSideLength = projectionScale * worldBB.getDiameter() / (worldBB.getCenter()-cameraOrigin).length();
	
	if(approxProjectedSideLength > maxSideLength)
		return NodeRendererResult::PASS_ON;

	static const Util::StringIdentifier REL_COVERING_ATTRIBUTE("surfelRelCovering");
	auto surfelCoverageAttr = node->findAttribute(REL_COVERING_ATTRIBUTE);
	const float relCovering = surfelCoverageAttr ? surfelCoverageAttr->toFloat() : 0.5;

	const float approxProjectedArea = approxProjectedSideLength * approxProjectedSideLength * relCovering;
	
	uint32_t surfelCount = std::min(	surfelMesh.isUsingIndexData() ?  surfelMesh.getIndexCount() : surfelMesh.getVertexCount(),
										static_cast<uint32_t>(approxProjectedArea * countFactor) + 1);
										
	float surfelSize = std::min(sizeFactor * approxProjectedArea / surfelCount,maxSurfelSize);

	bool handled = true;
	if(approxProjectedSideLength > minSideLength && minSideLength<maxSideLength){
		const float f = 1.0f -(approxProjectedSideLength-minSideLength) / (maxSideLength-minSideLength);
		surfelCount =  std::min(	surfelMesh.isUsingIndexData() ?  surfelMesh.getIndexCount() : surfelMesh.getVertexCount(),
										static_cast<uint32_t>(f * surfelCount) + 1);
		surfelSize *= f;
		handled = false;
//		std::cout << approxProjectedSideLength<<"\t"<<f<<"\n";
		
	}
//	std::cout << surfelSize<<"\t"<<"\n";
//	if( node->getRenderingLayers()&0x02 )
//		std::cout << "pSize"<<approxProjectedSideLength << "\t#:"<<surfelCount<<"\ts:"<<surfelSize<<"\n";
	auto& renderingContext = context.getRenderingContext();
	
	static Rendering::Uniform enableSurfels("renderSurfels", true);
	static Rendering::Uniform disableSurfels("renderSurfels", false);
	
	renderingContext.setGlobalUniform(enableSurfels);
	renderingContext.pushAndSetPointParameters( Rendering::PointParameters(std::min(surfelSize,32.0f) ));
	renderingContext.pushAndSetMatrix_modelToCamera( renderingContext.getMatrix_worldToCamera() );
	renderingContext.multMatrix_modelToCamera(node->getWorldTransformationMatrix());
	context.displayMesh(&surfelMesh,	0, surfelCount );
	renderingContext.popMatrix_modelToCamera();
	renderingContext.popPointParameters();
	renderingContext.setGlobalUniform(disableSurfels);
	
	return handled ? NodeRendererResult::NODE_HANDLED : NodeRendererResult::PASS_ON;
}
Example #2
0
void ParticlePointRenderer::operator()(ParticleSystemNode* psys, FrameContext & context, const RenderParam & rp /* = 0 */) {
	if ( (rp.getFlag(NO_GEOMETRY)) )
		return;

	// render particles
	std::vector<Particle> & particles = psys->getParticles();
	uint32_t count = psys->getParticleCount();

	Rendering::VertexDescription vertexDesc;
	const Rendering::VertexAttribute & posAttrib = vertexDesc.appendPosition3D();
	const Rendering::VertexAttribute & colorAttrib = vertexDesc.appendColorRGBAByte();
	// The usage of a cache for the mesh has been tested. Reusing a preallocated mesh is not faster.
	Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, count, count);
	mesh->setDataStrategy(Rendering::SimpleMeshDataStrategy::getPureLocalStrategy());
	mesh->setDrawMode(Rendering::Mesh::DRAW_POINTS);
//	mesh->setUseIndexData(false);
	Rendering::MeshIndexData & indexData = mesh->openIndexData();
	Rendering::MeshVertexData & vertexData = mesh->openVertexData();
	Util::Reference<Rendering::PositionAttributeAccessor> positionAccessor = Rendering::PositionAttributeAccessor::create(vertexData, posAttrib.getNameId());
	Util::Reference<Rendering::ColorAttributeAccessor> colorAccessor = Rendering::ColorAttributeAccessor::create(vertexData, colorAttrib.getNameId());
	uint32_t * indices = indexData.data();

	for(uint_fast32_t index = 0; index < count; ++index) {
		const Particle & p = particles[index];

		colorAccessor->setColor(index, p.color);
		positionAccessor->setPosition(index, p.position);

		*indices++ = index;
	}

	indexData.markAsChanged();
	indexData.updateIndexRange();
	vertexData.markAsChanged();
	vertexData.updateBoundingBox();
	context.displayMesh(mesh.get());
}
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;
}
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;
}
Example #5
0
void ParticleBillboardRenderer::operator()(ParticleSystemNode * psys, FrameContext & context, const RenderParam & rp) {
	if(rp.getFlag(NO_GEOMETRY)) {
		return;
	}

	const auto & worldToCamera = context.getRenderingContext().getMatrix_worldToCamera();
	const auto cameraToWorld = worldToCamera.inverse();

	const auto halfRight = cameraToWorld.transformDirection(context.getWorldRightVector() * 0.5f);
	const auto halfUp = cameraToWorld.transformDirection(context.getWorldUpVector() * 0.5f);

	// 2. just update position for each particle and render
	// render particles
	const uint32_t count = psys->getParticleCount();

	Rendering::VertexDescription vertexDesc;
	const Rendering::VertexAttribute & posAttrib = vertexDesc.appendPosition3D();
	const Rendering::VertexAttribute & colorAttrib = vertexDesc.appendColorRGBAByte();
	const Rendering::VertexAttribute & texCoordAttrib = vertexDesc.appendTexCoord();
	// The usage of a cache for the mesh has been tested. Reusing a preallocated mesh is not faster.
	Util::Reference<Rendering::Mesh> mesh = new Rendering::Mesh(vertexDesc, 4 * count, 6 * count);
	mesh->setDataStrategy(Rendering::SimpleMeshDataStrategy::getPureLocalStrategy());
	Rendering::MeshIndexData & indexData = mesh->openIndexData();
	Rendering::MeshVertexData & vertexData = mesh->openVertexData();
	Util::Reference<Rendering::PositionAttributeAccessor> positionAccessor = Rendering::PositionAttributeAccessor::create(vertexData, posAttrib.getNameId());
	Util::Reference<Rendering::ColorAttributeAccessor> colorAccessor = Rendering::ColorAttributeAccessor::create(vertexData, colorAttrib.getNameId());
	Util::Reference<Rendering::TexCoordAttributeAccessor> texCoordAccessor = Rendering::TexCoordAttributeAccessor::create(vertexData, texCoordAttrib.getNameId());
	uint32_t * indices = indexData.data();

	uint_fast32_t index = 0;
	for(const auto & p : psys->getParticles()) {
		const Geometry::Vec3f upOffset = halfUp * p.size.getHeight();
		const Geometry::Vec3f rightOffset = halfRight * p.size.getWidth();

		colorAccessor->setColor(index + 0, p.color);
		texCoordAccessor->setCoordinate(index + 0, Geometry::Vec2f(0.0f, 0.0f));
		positionAccessor->setPosition(index + 0, p.position + upOffset - rightOffset);

		colorAccessor->setColor(index + 1, p.color);
		texCoordAccessor->setCoordinate(index + 1, Geometry::Vec2f(0.0f, 1.0f));
		positionAccessor->setPosition(index + 1, p.position - upOffset - rightOffset);

		colorAccessor->setColor(index + 2, p.color);
		texCoordAccessor->setCoordinate(index + 2, Geometry::Vec2f(1.0f, 1.0f));
		positionAccessor->setPosition(index + 2, p.position - upOffset + rightOffset);

		colorAccessor->setColor(index + 3, p.color);
		texCoordAccessor->setCoordinate(index + 3, Geometry::Vec2f(1.0f, 0.0f));
		positionAccessor->setPosition(index + 3, p.position + upOffset + rightOffset);

		*indices++ = index + 0;
		*indices++ = index + 1;
		*indices++ = index + 3;

		*indices++ = index + 1;
		*indices++ = index + 2;
		*indices++ = index + 3;

		index += 4;
	}

	indexData.markAsChanged();
	indexData.updateIndexRange();
	vertexData.markAsChanged();
	vertexData.updateBoundingBox();
	context.displayMesh(mesh.get());
}