Beispiel #1
0
void Model::computeRuntimeData(const uint8* vertices)
{
	int index = 0;
	float bounding_radius_squared = 0;
	Vec3 min_vertex(0, 0, 0);
	Vec3 max_vertex(0, 0, 0);

	for (int i = 0; i < m_meshes.size(); ++i)
	{
		int mesh_vertex_count = m_meshes[i].getAttributeArraySize() /
								m_meshes[i].getVertexDefinition().getStride();
		int mesh_attributes_array_offset =
			m_meshes[i].getAttributeArrayOffset();
		int mesh_vertex_size = m_meshes[i].getVertexDefinition().getStride();
		int mesh_position_attribute_offset =
			m_meshes[i].getVertexDefinition().getOffset(bgfx::Attrib::Position);
		for (int j = 0; j < mesh_vertex_count; ++j)
		{
			m_vertices[index] =
				*(const Vec3*)&vertices[mesh_attributes_array_offset +
										j * mesh_vertex_size +
										mesh_position_attribute_offset];
			bounding_radius_squared = Math::maxValue(
				bounding_radius_squared,
				dotProduct(m_vertices[index], m_vertices[index]) > 0
					? m_vertices[index].squaredLength()
					: 0);
			min_vertex.x = Math::minValue(min_vertex.x, m_vertices[index].x);
			min_vertex.y = Math::minValue(min_vertex.y, m_vertices[index].y);
			min_vertex.z = Math::minValue(min_vertex.z, m_vertices[index].z);
			max_vertex.x = Math::maxValue(max_vertex.x, m_vertices[index].x);
			max_vertex.y = Math::maxValue(max_vertex.y, m_vertices[index].y);
			max_vertex.z = Math::maxValue(max_vertex.z, m_vertices[index].z);
			++index;
		}
	}

	m_bounding_radius = sqrt(bounding_radius_squared);
	m_aabb = AABB(min_vertex, max_vertex);
}
Beispiel #2
0
void management_base::
check_for_nodes_within_cells(const std::vector<std::vector<size_t>>& total_depths, const std::vector<std::vector<size_t>>& total_nums)
{
    lamure::ren::model_database* database = lamure::ren::model_database::get_instance();

    for(model_t model_index = 0; model_index < database->num_models(); ++model_index)
    {
        for(size_t cell_index = 0; cell_index < visibility_grid_->get_cell_count(); ++cell_index)
        {
            // Create bounding box of view cell.
            const view_cell* current_cell = visibility_grid_->get_cell_at_index(cell_index);
                
            vec3r min_vertex(current_cell->get_position_center() - (current_cell->get_size() * 0.5f));
            vec3r max_vertex(current_cell->get_position_center() + (current_cell->get_size() * 0.5f));
            bounding_box cell_bounds(min_vertex, max_vertex);

            // We can get the first and last index of the nodes on a certain depth inside the bvh.
            unsigned int average_depth = total_depth_rendered_nodes_[model_index][cell_index] / total_num_rendered_nodes_[model_index][cell_index];

            node_t start_index = database->get_model(model_index)->get_bvh()->get_first_node_id_of_depth(average_depth);
            node_t end_index = start_index + database->get_model(model_index)->get_bvh()->get_length_of_depth(average_depth);

            for(node_t node_index = start_index; node_index < end_index; ++node_index)
            {
                // Create bounding box of node.
                scm::gl::boxf node_bounding_box = database->get_model(model_index)->get_bvh()->get_bounding_boxes()[node_index];
                vec3r min_vertex = vec3r(node_bounding_box.min_vertex()) + database->get_model(model_index)->get_bvh()->get_translation();
                vec3r max_vertex = vec3r(node_bounding_box.max_vertex()) + database->get_model(model_index)->get_bvh()->get_translation();
                bounding_box node_bounds(min_vertex, max_vertex);

                // check if the bounding boxes collide.
                if(cell_bounds.intersects(node_bounds))
                {
                    visibility_grid_->set_cell_visibility(cell_index, model_index, node_index, true);
                }
            }
        }
    }
}
int visibility_test_id_histogram_renderer::
initialize(int& argc, char** argv)
{
 	namespace po = boost::program_options;
    namespace fs = boost::filesystem;

    const std::string exec_name = (argc > 0) ? fs::basename(argv[0]) : "";
    scm::shared_ptr<scm::core> scm_core(new scm::core(1, argv));

    putenv((char *)"__GL_SYNC_TO_VBLANK=0");

    std::string resource_file_path = "";

    // These value are read, but not used. Yet ignoring them in the terminal parameters would lead to misinterpretation.
    std::string pvs_output_file_path = "";
    std::string visibility_test_type = "";
    std::string grid_type = "";
    unsigned int grid_size = 1;
    unsigned int num_steps = 11;
    double oversize_factor = 1.5;
    float optimization_threshold = 1.0f;

	po::options_description desc("Usage: " + exec_name + " [OPTION]... INPUT\n\n"
                               "Allowed Options");
    desc.add_options()
      ("help", "print help message")
      ("width,w", po::value<int>(&resolution_x_)->default_value(1024), "specify window width (default=1024)")
      ("height,h", po::value<int>(&resolution_y_)->default_value(1024), "specify window height (default=1024)")
      ("resource-file,f", po::value<std::string>(&resource_file_path), "specify resource input-file")
      ("vram,v", po::value<unsigned>(&video_memory_budget_)->default_value(2048), "specify graphics memory budget in MB (default=2048)")
      ("mem,m", po::value<unsigned>(&main_memory_budget_)->default_value(4096), "specify main memory budget in MB (default=4096)")
      ("upload,u", po::value<unsigned>(&max_upload_budget_)->default_value(64), "specify maximum video memory upload budget per frame in MB (default=64)")
    // The following parameters are used by the main app only, yet must be identified nonetheless since otherwise they are dealt with as file paths.
      ("pvs-file,p", po::value<std::string>(&pvs_output_file_path), "specify output file of calculated pvs data")
      ("vistest", po::value<std::string>(&visibility_test_type)->default_value("histogramrenderer"), "specify type of visibility test to be used. ('histogramrenderer', 'randomhistogramrenderer')")
      ("gridtype", po::value<std::string>(&grid_type)->default_value("octree"), "specify type of grid to store visibility data ('regular', 'octree', 'hierarchical')")
      ("gridsize", po::value<unsigned int>(&grid_size)->default_value(1), "specify size/depth of the grid used for the visibility test (depends on chosen grid type)")
      ("oversize", po::value<double>(&oversize_factor)->default_value(1.5), "factor the grid bounds will be scaled by, default is 1.5 (grid bounds will exceed scene bounds by factor of 1.5)")
      ("optithresh", po::value<float>(&optimization_threshold)->default_value(1.0f), "specify the threshold at which common data are converged. Default is 1.0, which means data must be 100 percent equal.")
      ("numsteps,n", po::value<unsigned int>(&num_steps)->default_value(11), "specify the number of intervals the occlusion values will be split into (visibility analysis only)");
      ;

    po::variables_map vm;

    try
    {    
		auto parsed_options = po::command_line_parser(argc, argv).options(desc).allow_unregistered().run();
		po::store(parsed_options, vm);
		po::notify(vm);

		std::vector<std::string> to_pass_further = po::collect_unrecognized(parsed_options.options, po::include_positional);
		bool no_input = !vm.count("input") && to_pass_further.empty();

		if (resource_file_path == "")
		{
			if (vm.count("help") || no_input)
			{
				std::cout << desc;
				return 0;
			}
		}

		// no explicit input -> use unknown options
		if (!vm.count("input") && resource_file_path == "") 
		{
			resource_file_path = "auto_generated.rsc";
			std::fstream ofstr(resource_file_path, std::ios::out);
			if (ofstr.good()) 
			{
			for (auto argument : to_pass_further)
			{
				ofstr << argument << std::endl;
			}
		}
		else
		{
			throw std::runtime_error("Cannot open file");
		}
			ofstr.close();
		}
	}
	catch (std::exception& e)
	{
		std::cout << "Warning: No input file specified. \n" << desc;
		return 0;
	}

	lamure::pvs::glut_wrapper::initialize(argc, argv, resolution_x_, resolution_y_, nullptr);

    std::pair< std::vector<std::string>, std::vector<scm::math::mat4f> > model_attributes;
    std::set<lamure::model_t> visible_set;
    std::set<lamure::model_t> invisible_set;
    model_attributes = read_model_string(resource_file_path, &visible_set, &invisible_set);

    std::vector<scm::math::mat4f> & model_transformations = model_attributes.second;
    std::vector<std::string> const& model_filenames = model_attributes.first;

    lamure::ren::policy* policy = lamure::ren::policy::get_instance();
    policy->set_max_upload_budget_in_mb(max_upload_budget_);
    policy->set_render_budget_in_mb(video_memory_budget_);
    policy->set_out_of_core_budget_in_mb(main_memory_budget_);
    policy->set_window_width(resolution_x_);
    policy->set_window_height(resolution_y_);

	lamure::ren::model_database* database = lamure::ren::model_database::get_instance();
    management_ = new management_id_histogram_renderer(model_filenames, model_transformations, visible_set, invisible_set);
    glut_wrapper::set_management(management_);
    management_->set_pvs_file_path(pvs_output_file_path);

    // Calculate bounding box of whole scene.
    for(lamure::model_t model_id = 0; model_id < database->num_models(); ++model_id)
    {
        // Cast required from boxf to bounding_box.
        const scm::gl::boxf& box_model_root = database->get_model(model_id)->get_bvh()->get_bounding_boxes()[0];
        vec3r min_vertex(box_model_root.min_vertex() + database->get_model(model_id)->get_bvh()->get_translation());
        vec3r max_vertex(box_model_root.max_vertex() + database->get_model(model_id)->get_bvh()->get_translation());
        bounding_box model_root_box(min_vertex, max_vertex);

        if(model_id == 0)
        {
            scene_bounds_ = bounding_box(model_root_box);
        }
        else
        {
            scene_bounds_.expand(model_root_box);
        }  
    }

    return 0;
}
Beispiel #4
0
bool Model::parseMeshesOld(bgfx::VertexDecl global_vertex_decl, FS::IFile& file, FileVersion version, u32 global_flags)
{
	int object_count = 0;
	file.read(&object_count, sizeof(object_count));
	if (object_count <= 0) return false;

	m_meshes.reserve(object_count);
	char model_dir[MAX_PATH_LENGTH];
	PathUtils::getDir(model_dir, MAX_PATH_LENGTH, getPath().c_str());
	struct Offsets
	{
		i32 attribute_array_offset;
		i32 attribute_array_size;
		i32 indices_offset;
		i32 mesh_tri_count;
	};
	Array<Offsets> mesh_offsets(m_allocator);
	for (int i = 0; i < object_count; ++i)
	{
		i32 str_size;
		file.read(&str_size, sizeof(str_size));
		char material_name[MAX_PATH_LENGTH];
		file.read(material_name, str_size);
		if (str_size >= MAX_PATH_LENGTH) return false;

		material_name[str_size] = 0;

		char material_path[MAX_PATH_LENGTH];
		copyString(material_path, model_dir);
		catString(material_path, material_name);
		catString(material_path, ".mat");

		auto* material_manager = m_resource_manager.getOwner().get(Material::TYPE);
		Material* material = static_cast<Material*>(material_manager->load(Path(material_path)));

		Offsets& offsets = mesh_offsets.emplace();
		file.read(&offsets.attribute_array_offset, sizeof(offsets.attribute_array_offset));
		file.read(&offsets.attribute_array_size, sizeof(offsets.attribute_array_size));
		file.read(&offsets.indices_offset, sizeof(offsets.indices_offset));
		file.read(&offsets.mesh_tri_count, sizeof(offsets.mesh_tri_count));

		file.read(&str_size, sizeof(str_size));
		if (str_size >= MAX_PATH_LENGTH)
		{
			material_manager->unload(*material);
			return false;
		}

		char mesh_name[MAX_PATH_LENGTH];
		mesh_name[str_size] = 0;
		file.read(mesh_name, str_size);

		bgfx::VertexDecl vertex_decl = global_vertex_decl;
		if (version <= FileVersion::SINGLE_VERTEX_DECL)
		{
			parseVertexDecl(file, &vertex_decl);
			if (i != 0 && global_vertex_decl.m_hash != vertex_decl.m_hash)
			{
				g_log_error.log("Renderer") << "Model " << getPath().c_str()
					<< " contains meshes with different vertex declarations.";
			}
			if(i == 0) global_vertex_decl = vertex_decl;
		}


		m_meshes.emplace(material,
			vertex_decl,
			mesh_name,
			m_allocator);
		addDependency(*material);
	}

	i32 indices_count = 0;
	file.read(&indices_count, sizeof(indices_count));
	if (indices_count <= 0) return false;

	u32 INDICES_16BIT_FLAG = 1;
	int index_size = global_flags & INDICES_16BIT_FLAG ? 2 : 4;
	Array<u8> indices(m_allocator);
	indices.resize(indices_count * index_size);
	file.read(&indices[0], indices.size());

	i32 vertices_size = 0;
	file.read(&vertices_size, sizeof(vertices_size));
	if (vertices_size <= 0) return false;

	Array<u8> vertices(m_allocator);
	vertices.resize(vertices_size);
	file.read(&vertices[0], vertices.size());

	int vertex_count = 0;
	for (const Offsets& offsets : mesh_offsets)
	{
		vertex_count += offsets.attribute_array_size / global_vertex_decl.getStride();
	}

	if (version > FileVersion::BOUNDING_SHAPES_PRECOMPUTED)
	{
		file.read(&m_bounding_radius, sizeof(m_bounding_radius));
		file.read(&m_aabb, sizeof(m_aabb));
	}

	float bounding_radius_squared = 0;
	Vec3 min_vertex(0, 0, 0);
	Vec3 max_vertex(0, 0, 0);

	int vertex_size = global_vertex_decl.getStride();
	int position_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Position);
	int uv_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::TexCoord0);
	int weights_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Weight);
	int bone_indices_attribute_offset = global_vertex_decl.getOffset(bgfx::Attrib::Indices);
	bool keep_skin = global_vertex_decl.has(bgfx::Attrib::Weight) && global_vertex_decl.has(bgfx::Attrib::Indices);
	for (int i = 0; i < m_meshes.size(); ++i)
	{
		Offsets& offsets = mesh_offsets[i];
		Mesh& mesh = m_meshes[i];
		mesh.indices_count = offsets.mesh_tri_count * 3;
		mesh.indices.resize(mesh.indices_count * index_size);
		copyMemory(&mesh.indices[0], &indices[offsets.indices_offset * index_size], mesh.indices_count * index_size);

		int mesh_vertex_count = offsets.attribute_array_size / global_vertex_decl.getStride();
		int mesh_attributes_array_offset = offsets.attribute_array_offset;
		mesh.vertices.resize(mesh_vertex_count);
		mesh.uvs.resize(mesh_vertex_count);
		if (keep_skin) mesh.skin.resize(mesh_vertex_count);
		for (int j = 0; j < mesh_vertex_count; ++j)
		{
			int offset = mesh_attributes_array_offset + j * vertex_size;
			if (keep_skin)
			{
				mesh.skin[j].weights = *(const Vec4*)&vertices[offset + weights_attribute_offset];
				copyMemory(mesh.skin[j].indices,
					&vertices[offset + bone_indices_attribute_offset],
					sizeof(mesh.skin[j].indices));
			}
			mesh.vertices[j] = *(const Vec3*)&vertices[offset + position_attribute_offset];
			mesh.uvs[j] = *(const Vec2*)&vertices[offset + uv_attribute_offset];
			float sq_len = mesh.vertices[j].squaredLength();
			bounding_radius_squared = Math::maximum(bounding_radius_squared, sq_len > 0 ? sq_len : 0);
			min_vertex.x = Math::minimum(min_vertex.x, mesh.vertices[j].x);
			min_vertex.y = Math::minimum(min_vertex.y, mesh.vertices[j].y);
			min_vertex.z = Math::minimum(min_vertex.z, mesh.vertices[j].z);
			max_vertex.x = Math::maximum(max_vertex.x, mesh.vertices[j].x);
			max_vertex.y = Math::maximum(max_vertex.y, mesh.vertices[j].y);
			max_vertex.z = Math::maximum(max_vertex.z, mesh.vertices[j].z);
		}
	}

	if (version <= FileVersion::BOUNDING_SHAPES_PRECOMPUTED)
	{
		m_bounding_radius = sqrt(bounding_radius_squared);
		m_aabb = AABB(min_vertex, max_vertex);
	}

	for (int i = 0; i < m_meshes.size(); ++i)
	{
		Mesh& mesh = m_meshes[i];
		Offsets offsets = mesh_offsets[i];
		
		ASSERT(!bgfx::isValid(mesh.index_buffer_handle));
		if (global_flags & INDICES_16BIT_FLAG)
		{
			mesh.flags.set(Mesh::Flags::INDICES_16_BIT);
		}
		int indices_size = index_size * mesh.indices_count;
		const bgfx::Memory* mem = bgfx::copy(&indices[offsets.indices_offset * index_size], indices_size);
		mesh.index_buffer_handle = bgfx::createIndexBuffer(mem, index_size == 4 ? BGFX_BUFFER_INDEX32 : 0);
		if (!bgfx::isValid(mesh.index_buffer_handle)) return false;

		ASSERT(!bgfx::isValid(mesh.vertex_buffer_handle));
		const bgfx::Memory* vertices_mem = bgfx::copy(&vertices[offsets.attribute_array_offset], offsets.attribute_array_size);
		mesh.vertex_buffer_handle = bgfx::createVertexBuffer(vertices_mem, mesh.vertex_decl);
		if (!bgfx::isValid(mesh.vertex_buffer_handle)) return false;
	}

	return true;
}
Beispiel #5
0
management_base::
management_base(std::vector<std::string> const& model_filenames,
    std::vector<scm::math::mat4f> const& model_transformations,
    std::set<lamure::model_t> const& visible_set,
    std::set<lamure::model_t> const& invisible_set)
    :   renderer_(nullptr),
        model_filenames_(model_filenames),
        model_transformations_(model_transformations),

        test_send_rendered_(true),
        active_camera_(nullptr),
        num_models_(0),
        dispatch_(true),
        error_threshold_(LAMURE_DEFAULT_THRESHOLD),
        near_plane_(0.001f),
        far_plane_(1000.f),
        importance_(1.f)

{
    visibility_threshold_ = 0.0001f;
    first_frame_ = true;
    visibility_grid_ = nullptr;
    current_grid_index_ = 0;
    direction_counter_ = 0;
    update_position_for_pvs_ = true;

#ifdef LAMURE_PVS_MEASURE_PERFORMANCE
    total_cut_update_time_ = 0.0;
    total_render_time_ = 0.0;
    total_histogram_evaluation_time_ = 0.0;
#endif

#ifndef LAMURE_PVS_USE_AS_RENDERER
    lamure::pvs::pvs_database::get_instance()->activate(false);
#endif

    lamure::ren::model_database* database = lamure::ren::model_database::get_instance();

    for (const auto& filename : model_filenames_)
    {
        database->add_model(filename, std::to_string(num_models_));
        ++num_models_;
    }

    total_depth_rendered_nodes_.resize(num_models_);
    total_num_rendered_nodes_.resize(num_models_);

    float scene_diameter = far_plane_;
    for (lamure::model_t model_id = 0; model_id < database->num_models(); ++model_id)
    {
        const auto& bb = database->get_model(model_id)->get_bvh()->get_bounding_boxes()[0];
        scene_diameter = std::max(scm::math::length(bb.max_vertex()-bb.min_vertex()), scene_diameter);
        model_transformations_[model_id] = model_transformations_[model_id] * scm::math::make_translation(database->get_model(model_id)->get_bvh()->get_translation());
    }
    far_plane_ = 2.0f * scene_diameter;

    auto root_bb = database->get_model(0)->get_bvh()->get_bounding_boxes()[0];
    scm::math::vec3 center = model_transformations_[0] * root_bb.center();
    scm::math::mat4f reset_matrix = scm::math::make_look_at_matrix(center + scm::math::vec3f(0.0f, 0.0f, 0.1f), center, scm::math::vec3f(0.0f, 1.0f,0.0f));
    float reset_diameter = scm::math::length(root_bb.max_vertex()-root_bb.min_vertex());

    std::cout << "model center : " << center << std::endl;
    std::cout << "model size : " << reset_diameter << std::endl;

    active_camera_ = new lamure::ren::camera(0, reset_matrix, reset_diameter, false, false);

    // Increase camera movement speed for debugging purpose.
    active_camera_->set_dolly_sens_(20.5f);

    renderer_ = new Renderer(model_transformations_, visible_set, invisible_set);
}