Ejemplo n.º 1
0
VisibilityVector Helper::getMaximumVisibility(const list_ptr list) {
    if(list->size() == 1) {
        return getVV(list->front());
    } else {
        VisibilityVector vv(getVV(list->front()));
        // Go over list containing elements for different directions.
        for(Util::GenericAttributeList::const_iterator it = std::next(list->begin()); it != list->end(); ++it) {
            vv = VisibilityVector::makeMax(vv, getVV(it->get()));
        }
        return vv;
    }
}
Ejemplo n.º 2
0
costs_t Helper::getRuntime(const list_ptr list) {
    // Check if value is cached.
    const auto cacheIt = runtimeCache.find(list);
    if(cacheIt != runtimeCache.end()) {
        // Return cached value.
        return cacheIt->second;
    }

    costs_t totalCosts = 0;

    if(list->size() == 1) {
        const auto & vv = getVV(list->front());
        totalCosts = vv.getTotalCosts();
    } else {
        std::vector<object_ptr> visibleObjects;

        // Go over list containing elements for different directions.
        for(const auto & attrib : *list) {
            const auto & vv = getVV(attrib.get());
            const uint32_t maxIndex = vv.getIndexCount();
            for(uint_fast32_t index = 0; index < maxIndex; ++index) {
                if(vv.getBenefits(index) > 0) {
                    visibleObjects.push_back(vv.getNode(index));
                }
            }
        }
        // Make sure we use every object only once.
        std::sort(visibleObjects.begin(), visibleObjects.end());
        visibleObjects.erase(std::unique(visibleObjects.begin(), visibleObjects.end()),
                             visibleObjects.end());

        for(const auto & object : visibleObjects) {
            totalCosts += object->getTriangleCount();
        }
    }

    // Insert value into cache.
    runtimeCache.insert(std::make_pair(list, totalCosts));

    return totalCosts;
}
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;
}
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;
}