Example #1
0
void PLODRessource::ray_test(Ray const& ray,
                             PickResult::Options options,
                             node::Node* owner,
                             std::set<PickResult>& hits) {

  if (!is_pickable_)
    return;

  const auto* tree =
      pbr::ren::ModelDatabase::GetInstance()->GetModel(model_id_)->kdn_tree();
  const uint32_t num_nodes = tree->num_nodes();
  const uint32_t fan_factor = tree->fan_factor();
  const uint32_t first_leaf = num_nodes - pow(fan_factor, tree->depth());

  const auto owner_transform = owner->get_world_transform();
  const auto world_origin = owner_transform * ray.origin_;

  bool has_hit = false;
  PickResult pick = PickResult(0.f,
                               owner,
                               ray.origin_,
                               math::vec3(0.f, 0.f, 0.f),
                               math::vec3(0.f, 1.f, 0.f),
                               math::vec3(0.f, 1.f, 0.f),
                               math::vec2(0.f, 0.f));

  std::stack<pbr::node_t> candidates;

  // there is always an intersection with root node
  candidates.push(0);

  while (!candidates.empty()) {
    pbr::node_t current = candidates.top();
    candidates.pop();

    for (pbr::node_t k = 0; k < fan_factor; ++k) {
      pbr::node_t n = tree->GetChildId(current, k);
      if (n >= num_nodes)
        break;
      Ray hit_ray(ray.intersection(tree->bounding_boxes()[n]));
      if (hit_ray.t_max_ >= 0.f) {
        if (n >= first_leaf) {
          // leaf with intersecion, check if frontmost
          float dist = scm::math::length(owner_transform * hit_ray.origin_ -
                                         world_origin);
          if (!has_hit || dist < pick.distance) {
            pick.distance = dist;
            pick.position = hit_ray.origin_;
            has_hit = true;
          }
        } else {
          // add to stack if not leaf
          candidates.push(n);
        }
      }
    }
  }
  if (has_hit)
    hits.insert(pick);
}
Example #2
0
void LodResource::ray_test(Ray const& ray,
                             int options,
                             node::Node* owner,
                             std::set<PickResult>& hits) {

  if (!is_pickable_)
    return;

  bool has_hit = false;
  PickResult pick = PickResult(
    0.f,
    owner,
    ray.origin_,
    math::vec3(0.f, 0.f, 0.f),
    math::vec3(0.f, 1.f, 0.f),
    math::vec3(0.f, 1.f, 0.f),
    math::vec2(0.f, 0.f));

  const auto model_transform = owner->get_cached_world_transform();
  const auto world_origin = ray.origin_;
  const auto world_direction = scm::math::normalize(ray.direction_);
  
  lamure::ren::ray lod_ray(math::vec3f(world_origin), math::vec3f(world_direction), scm::math::length(ray.direction_));
  lamure::ren::ray::intersection intersection;

  auto lod_node = reinterpret_cast<node::PLodNode*>(owner);

  float aabb_scale = 9.0f;
  unsigned int max_depth = 255;
  unsigned int surfel_skip = 1;
  bool wysiwyg = true;
 
  lamure::ren::controller* controller = lamure::ren::controller::get_instance();
  lamure::model_t model_id = controller->deduce_model_id(lod_node->get_geometry_description());
  
  if (lod_ray.intersect_model(model_id, math::mat4f(model_transform), aabb_scale, max_depth, surfel_skip, wysiwyg, intersection)) {
    has_hit = true;
    pick.distance = intersection.distance_;

    pick.world_position = intersection.position_;
    auto object_position = scm::math::inverse(model_transform) * gua::math::vec4(intersection.position_.x, intersection.position_.y, intersection.position_.z, 1.0);
    pick.position = math::vec3(object_position.x, object_position.y, object_position.z);
    pick.normal = intersection.normal_;
  }

  if (has_hit) {
    if (hits.empty()) {
      hits.insert(pick);
    }
    else if (pick.distance < hits.begin()->distance) {
      hits.insert(pick);
    }
  }

}