Exemple #1
0
Meshes::UID revolved_sphere(unsigned int longitude_quads, unsigned int latitude_quads, unsigned char buffer_bitmask) {
    if (longitude_quads < 3 || latitude_quads < 2)
        return Meshes::UID::invalid_UID();

    unsigned int latitude_size = latitude_quads + 1;
    unsigned int longitude_size = longitude_quads + 1;
    unsigned int vertex_count = latitude_size * longitude_size;
    unsigned int quad_count = latitude_quads * longitude_quads;
    unsigned int index_count = (quad_count - longitude_quads) * 2;
    float radius = 0.5f;

    Mesh mesh = Meshes::create("RevolvedSphere", index_count, vertex_count, buffer_bitmask);

    { // Vertex attributes.
        Vector3f* positions = mesh.get_positions();
        Vector3f* normals = mesh.get_normals();
        Vector2f* texcoords = mesh.get_texcoords();

        Vector2f tc_normalizer = Vector2f(1.0f / longitude_quads, 1.0f / latitude_quads);
        for (unsigned int y = 0; y < latitude_size; ++y) {
            for (unsigned int x = 0; x < longitude_size; ++x) {
                unsigned int vertex_index = y * longitude_size + x;
                Vector2f tc = Vector2f(float(x), float(y)) * tc_normalizer;
                if (texcoords)
                    texcoords[vertex_index] = tc;
                positions[vertex_index] = spherical_to_direction(tc.y * Math::PI<float>(),
                                                                 tc.x * 2.0f * Math::PI<float>()) * radius;
                if (normals)
                    normals[vertex_index] = normalize(positions[vertex_index]);
            }
        }

        // Hard set the poles to [0,1,0] and [0,-1,0].
        for (unsigned int x = 0; x < longitude_size; ++x) {
            positions[x] = Vector3f(0, radius, 0);
            positions[(latitude_size - 1) * longitude_size + x] = Vector3f(0, -radius, 0);
        }
    }

    { // Primitives.
        Vector3ui* primitives = mesh.get_primitives();
        for (unsigned int y = 0; y < latitude_quads; ++y) {
            for (unsigned int x = 0; x < longitude_quads; ++x) {
                unsigned int base_vertex_index = x + y * longitude_size;
                if (y != 0)
                    *primitives++ = Vector3ui(0, 1, longitude_size) + base_vertex_index;
                if (y != latitude_quads - 1)
                    *primitives++ = Vector3ui(1, longitude_size + 1, longitude_size) + base_vertex_index;
            }
        }
    }

    mesh.set_bounds(AABB(Vector3f(-radius), Vector3f(radius)));

    return mesh.get_ID();
}
Exemple #2
0
bool VisVoxelMap::visualize(const bool force_repaint)
{
  if (force_repaint)
  {
    openOrCreateSegment();
    uint32_t shared_mem_id;
    if (m_shm_memHandle == NULL)
    {
      // there should only be one segment of number_of_voxelmaps
      std::pair<uint32_t*, std::size_t> r = m_segment.find<uint32_t>(
          shm_variable_name_number_of_voxelmaps.c_str());
      if (r.second == 0)
      { // if it doesn't exists ..
        m_segment.construct<uint32_t>(shm_variable_name_number_of_voxelmaps.c_str())(1);
        shared_mem_id = 0;
      }
      else
      { // if it exists increase it by one
        shared_mem_id = *r.first;
        (*r.first)++;
      }
      // get shared memory pointer
      std::stringstream id;
      id << shared_mem_id;
      m_shm_memHandle = m_segment.find_or_construct<cudaIpcMemHandle_t>(
          std::string(shm_variable_name_voxelmap_handler_dev_pointer + id.str()).c_str())(
          cudaIpcMemHandle_t());
      m_shm_mapDim = m_segment.find_or_construct<Vector3ui>(
          std::string(shm_variable_name_voxelmap_dimension + id.str()).c_str())(Vector3ui(0));
      m_shm_VoxelSize = m_segment.find_or_construct<float>(
          std::string(shm_variable_name_voxel_side_length + id.str()).c_str())(0.0f);
      m_shm_mapName = m_segment.find_or_construct_it<char>(
          std::string(shm_variable_name_voxelmap_name + id.str()).c_str())[m_map_name.size()](
          m_map_name.data());
      m_shm_voxelmap_type = m_segment.find_or_construct<MapType>(
          std::string(shm_variable_name_voxelmap_type + id.str()).c_str())(m_voxelmap->getMapType());

      m_shm_voxelmap_changed = m_segment.find_or_construct<bool>(
          std::string(shm_variable_name_voxelmap_data_changed + id.str()).c_str())(true);

    }
    // first open or create and the set the values
    HANDLE_CUDA_ERROR(cudaIpcGetMemHandle(m_shm_memHandle, m_voxelmap->getVoidDeviceDataPtr()));
    *m_shm_mapDim = m_voxelmap->getDimensions();
    *m_shm_VoxelSize = m_voxelmap->getVoxelSideLength();
    *m_shm_voxelmap_changed = true;

//    // wait till data was read by visualizer. Otherwise a
//    while(*m_shm_voxelmap_changed)
//      usleep(10000); // sleep 10 ms

    return true;
  }
  return false;
}
Exemple #3
0
Meshes::UID plane(unsigned int quads_pr_edge, unsigned char buffer_bitmask) {
    if (quads_pr_edge == 0)
        return Meshes::UID::invalid_UID();

    unsigned int size = quads_pr_edge + 1;
    unsigned int vertex_count = size * size;
    unsigned int quad_count = quads_pr_edge * quads_pr_edge;
    unsigned int index_count = quad_count * 2;
    
    Mesh mesh = Meshes::create("Plane", index_count, vertex_count, buffer_bitmask);

    // Vertex attributes.
    float tc_normalizer = 1.0f / quads_pr_edge;
    for (unsigned int z = 0; z < size; ++z) {
        for (unsigned int x = 0; x < size; ++x) {
            mesh.get_positions()[z * size + x] = Vector3f(x - quads_pr_edge * 0.5f, 0.0f, z - quads_pr_edge * 0.5f);
            if (mesh.get_normals() != nullptr)
                mesh.get_normals()[z * size + x] = Vector3f(0.0f, 1.0f, 0.0f);
            if (mesh.get_texcoords() != nullptr)
                mesh.get_texcoords()[z * size + x] = Vector2f(float(x), float(z)) * tc_normalizer;
        }
    }

    // Primitives.
    for (unsigned int z = 0; z < quads_pr_edge; ++z) {
        for (unsigned int x = 0; x < quads_pr_edge; ++x) {
            Vector3ui* primitives = mesh.get_primitives() + (z * quads_pr_edge + x) * 2;
            unsigned int base_index = x + z * size;
            primitives[0] = Vector3ui(base_index, base_index + size, base_index + 1);
            primitives[1] = Vector3ui(base_index + 1, base_index + size, base_index + size + 1);
        }
    }

    mesh.compute_bounds();

    return mesh.get_ID();
}
Exemple #4
0
Vector3ui NodeId::getPosition() const
{
    return Vector3ui(_blockPosX, _blockPosY, _blockPosZ);
}
void VoxelMapProvider::init(Provider_Parameter& parameter)
{
  m_mutex.lock();

  const string prefix = "VoxelMapProvider::" + string(__FUNCTION__);
  const string temp_timer = prefix + "_temp";
  PERF_MON_START(prefix);
  PERF_MON_START(temp_timer);

  Provider::init(parameter);

  // get shared memory pointer
  m_shm_memHandle = m_segment.find_or_construct<cudaIpcMemHandle_t>(
      std::string(shm_variable_name_voxelmap_handler_dev_pointer + m_shared_mem_id).c_str())(
      cudaIpcMemHandle_t());
  m_shm_mapDim = m_segment.find_or_construct<Vector3ui>(
      std::string(shm_variable_name_voxelmap_dimension + m_shared_mem_id).c_str())(Vector3ui(0));
  m_shm_VoxelSize = m_segment.find_or_construct<float>(
      std::string(shm_variable_name_voxel_side_length + m_shared_mem_id).c_str())(0.0f);

  // there should only be one segment of number_of_voxelmaps
  std::pair<uint32_t*, std::size_t> r = m_segment.find<uint32_t>(
      shm_variable_name_number_of_voxelmaps.c_str());
  if (r.second == 0)
  {
    // if it doesn't exist ..
    m_segment.construct<uint32_t>(shm_variable_name_number_of_voxelmaps.c_str())(1);
  }
  else
  {
    // if it exit increase it by one
    (*r.first)++;
  }

  Vector3ui map_dim;
  std::vector<Vector3f> insert_points;
  float voxel_map_res = 1.0f;
  if (parameter.points.size() != 0)
  {
    Vector3f offset;
    Vector3ui point_data_bounds = getMapDimensions(parameter.points, offset);
    map_dim = point_data_bounds;
    printf("point cloud dimension %u %u %u\n", map_dim.x, map_dim.y, map_dim.z);

    if (parameter.plan_size.x != 0.0f && parameter.plan_size.y != 0.0f && parameter.plan_size.z != 0.0f)
    {
      Vector3f tmp = parameter.plan_size * 1000.0f;
      map_dim = Vector3ui(uint32_t(tmp.x), uint32_t(tmp.y), uint32_t(tmp.z));
      printf("dim in cm %u %u %u\n", map_dim.x, map_dim.y, map_dim.z);
    }

    uint64_t map_voxel = uint64_t(map_dim.x) * uint64_t(map_dim.y) * uint64_t(map_dim.z);

    float scaling = 1.0;
    if (parameter.max_memory == 0)
    {
      // compute scaling factor based on voxel size
      scaling = 1.0f / parameter.resolution_tree;
    }
    else
    {
      // compute max scaling factor based on memory restriction
      uint64_t max_voxel = uint64_t(parameter.max_memory) / sizeof(ProbabilisticVoxel);
      printf("max_voxel %lu map_voxel %lu\n", max_voxel, map_voxel);
      if (max_voxel <= map_voxel)
        scaling = float(pow(max_voxel / double(map_voxel), 1.0 / 3));
    }

    printf("scaling %f\n", scaling);

    std::vector<Vector3ui> points;
    Vector3ui map_dim_tmp;
    transformPointCloud(parameter.points, points, map_dim_tmp, scaling * 1000.0f);

    map_dim = Vector3ui(uint32_t(ceil(map_dim.x * scaling)), uint32_t(ceil(map_dim.y * scaling)),
                        uint32_t(ceil(map_dim.z * scaling)));
    printf("voxel map dimension %u %u %u\n", map_dim.x, map_dim.y, map_dim.z);

    // center data at the middle of the map, just like for NTree
    point_data_bounds = Vector3ui(uint32_t(ceil(point_data_bounds.x * scaling)),
                                  uint32_t(ceil(point_data_bounds.y * scaling)),
                                  uint32_t(ceil(point_data_bounds.z * scaling)));
    Vector3ui tmp_offset = (map_dim - point_data_bounds) / Vector3ui(2);
    insert_points.resize(points.size());
    printf("scaling %f\n", scaling);

    voxel_map_res = (1.0f / scaling) / 1000.0f;;
    printf("mapres %f\n", voxel_map_res);
    for (int i = 0; i < int(points.size()); ++i)
    {
      points[i] = points[i] + tmp_offset;
      insert_points[i].x = points[i].x * voxel_map_res + voxel_map_res / 2;
      insert_points[i].y = points[i].y * voxel_map_res + voxel_map_res / 2;
      insert_points[i].z = points[i].z * voxel_map_res + voxel_map_res / 2;
    }
    PERF_MON_START(temp_timer);
  }
  else
  {
    // VoxelMap with same size as octree
    uint32_t dim = (uint32_t) pow(pow(BRANCHING_FACTOR, 1.0 / 3), parameter.resolution_tree);
    map_dim = Vector3ui(dim);
    voxel_map_res = parameter.resolution_tree * 0.001f; // voxel size in meter
  }

  switch(m_parameter->model_type)
  {
    case Provider_Parameter::eMT_Probabilistic:
    {
      m_voxelMap = new gpu_voxels::voxelmap::ProbVoxelMap(map_dim.x, map_dim.y, map_dim.z, voxel_map_res, MT_PROBAB_VOXELMAP);
      break;
    }
    case Provider_Parameter::eMT_BitVector:
    {
      m_voxelMap = new gpu_voxels::voxelmap::BitVectorVoxelMap(map_dim.x, map_dim.y, map_dim.z, voxel_map_res, MT_BITVECTOR_VOXELMAP);
      break;
    }
    default:
    {
      printf("ERROR: Unknown 'model_type'\n");
    }
  }
  m_segment.find_or_construct<MapType>(std::string(shm_variable_name_voxelmap_type + m_shared_mem_id).c_str())(m_voxelMap->getMapType());

  if (insert_points.size() != 0)
  {
    m_voxelMap->insertPointCloud(insert_points, gpu_voxels::eBVM_OCCUPIED);

//    if (m_parameter->model_type == Provider_Parameter::eMT_BitVector)
//    {
//      Vector3f offset(1, 1, 1);
//      for (uint32_t k = 1; k < 4; ++k)
//      {
//        std::vector<Vector3f> tmp = insert_points;
//        for (int i = 0; i < int(tmp.size()); ++i)
//          tmp[i] = tmp[i] + offset * k;
//
//        m_voxelMap->insertPointCloud(tmp, gpu_voxels::eBVM_UNDEFINED + k);
//      }
//    }

    PERF_MON_PRINT_INFO_P(temp_timer, "Build", prefix);
  }

  PERF_MON_ADD_DATA_NONTIME_P("UsedMemory", m_voxelMap->getMemoryUsage(), prefix);

  m_sensor_orientation = gpu_voxels::Vector3f(0, 0, 0);
  m_sensor_position = gpu_voxels::Vector3f(
      (m_voxelMap->getDimensions().x * m_voxelMap->getVoxelSideLength()) / 2,
      (m_voxelMap->getDimensions().y * m_voxelMap->getVoxelSideLength()) / 2,
      (m_voxelMap->getDimensions().z * m_voxelMap->getVoxelSideLength()) / 2) * 0.001f; // in meter

  printf("VoxelMap created!\n");

  m_mutex.unlock();
}
void DataManager::Initialize(itk::SmartPointer<LabelMapType> labelMap, std::shared_ptr<Coordinates> coordinates, std::shared_ptr<Metadata> metadata)
{
  m_orientationData = coordinates;
  auto spacing      = m_orientationData->GetImageSpacing();
  auto imageorigin  = m_orientationData->GetImageOrigin();
  auto imagesize    = m_orientationData->GetImageSize();

  // insert background label info, initially all voxels are background, we'll subtract later
  auto object = std::make_shared<ObjectInformation>();
  object->scalar   = 0;
  object->centroid = Vector3d((imagesize[0] / 2.0) * spacing[0], (imagesize[1] / 2.0) * spacing[1], (imagesize[2] / 2.0) / spacing[2]);
  object->size     = imagesize[0] * imagesize[1] * imagesize[2];
  object->min      = Vector3ui(0, 0, 0);
  object->max      = Vector3ui(imagesize[0], imagesize[1], imagesize[2]);

  ObjectVector.insert(std::pair<unsigned short, std::shared_ptr<ObjectInformation>>(0, object));

  // evaluate shapelabelobjects to get the centroid of the object
  auto evaluator = itk::ShapeLabelMapFilter<LabelMapType>::New();
  evaluator->SetInput(labelMap);
  evaluator->ComputePerimeterOff();
  evaluator->ComputeFeretDiameterOff();
  evaluator->SetInPlace(true);
  evaluator->Update();

  // get voxel count for each label for statistics and "flatten" the labelmap (make all labels consecutive starting from 1)
  auto labelChanger = ChangeType::New();
  labelChanger->SetInput(evaluator->GetOutput());
  labelChanger->SetInPlace(true);

  ImageRegionType region;
  unsigned short i = 1;
  itk::Point<double, 3> centroid;

  for (int i = 0; i < evaluator->GetOutput()->GetNumberOfLabelObjects(); ++i)
  {
    auto labelObject = evaluator->GetOutput()->GetNthLabelObject(i);
    auto scalar = labelObject->GetLabel();
    centroid = labelObject->GetCentroid();
    region = labelObject->GetBoundingBox();
    auto regionOrigin = region.GetIndex();
    auto regionSize = region.GetSize();

    object = std::make_shared<ObjectInformation>();
    object->scalar   = scalar;
    object->centroid = Vector3d(centroid[0] / spacing[0], centroid[1] / spacing[1], centroid[2] / spacing[2]);
    object->size     = labelObject->Size();
    object->min      = Vector3ui(regionOrigin[0], regionOrigin[1], regionOrigin[2]);
    object->max      = Vector3ui(regionSize[0] + regionOrigin[0], regionSize[1] + regionOrigin[1], regionSize[2] + regionOrigin[2]) - Vector3ui(1, 1, 1);

    ObjectVector.insert(std::pair<unsigned short, std::shared_ptr<ObjectInformation>>(i, object));

    // substract the voxels of this object from the background label
    ObjectVector[0]->size -= labelObject->Size();

    // need to mark object label as used to correct errors in the segmha metadata (defined labels but empty objects)
    metadata->markAsUsed(scalar);

    // flatten label
    labelChanger->SetChange(scalar, i);
  }

  // start entering new labels at the end of the scalar range
  m_firstFreeValue = GetScalarForLabel(GetNumberOfLabels() - 1) + 1;

  // apply all the changes made to labels
  labelChanger->Update();

  m_labelMap = LabelMapType::New();
  m_labelMap = labelChanger->GetOutput();
  m_labelMap->Optimize();
  m_labelMap->Update();

  // generate the initial vtkLookupTable
  m_lookupTable = vtkSmartPointer<vtkLookupTable>::New();
  GenerateLookupTable();
  m_lookupTable->Modified();
}
void DataManager::SetVoxelScalar(const Vector3ui &point, const unsigned short scalar)
{
  int extent[6];
  m_structuredPoints->GetExtent(extent);
  if(extent[0] > point[0] || extent[1] < point[0] || extent[2] > point[1] || extent[3] < point[1] || extent[4] > point[2] || extent[5] < point[2])
  {
    qWarning() << "point out of range - point[" << point[0] << point[1] << point[2] << "] extent[" << extent[0] << extent[1] << extent[2] << extent[3] << extent[4] << extent[5] << "]";
    return;
  }

  auto x = point[0];
  auto y = point[1];
  auto z = point[2];
  auto pixel = static_cast<unsigned short*>(m_structuredPoints->GetScalarPointer(x,y,z));

  if (scalar == *pixel) return;

  if (ActionInformationVector.find(*pixel) == ActionInformationVector.end())
  {
    auto action = std::make_shared<ActionInformation>();
    ActionInformationVector[*pixel] = action;
    action->min = Vector3ui(x, y, z);
    action->max = Vector3ui(x, y, z);
  }
  ActionInformationVector[*pixel]->size -= 1;
  ActionInformationVector[*pixel]->centroid[0] -= x;
  ActionInformationVector[*pixel]->centroid[1] -= y;
  ActionInformationVector[*pixel]->centroid[2] -= z;

  if (ActionInformationVector.find(scalar) == ActionInformationVector.end())
  {
    auto action = std::make_shared<ActionInformation>();
    ActionInformationVector[scalar] = action;
    action->min = Vector3ui(x, y, z);
    action->max = Vector3ui(x, y, z);
  }
  ActionInformationVector[scalar]->size += 1;
  ActionInformationVector[scalar]->centroid[0] += x;
  ActionInformationVector[scalar]->centroid[1] += y;
  ActionInformationVector[scalar]->centroid[2] += z;

  // have to check if the added voxel is out of the object region to make the bounding box grow
  Vector3ui min = ActionInformationVector[scalar]->min;
  Vector3ui max = ActionInformationVector[scalar]->max;

  if (x < min[0]) min[0] = x;

  if (x > max[0]) max[0] = x;

  if (y < min[1]) min[1] = y;

  if (y > max[1]) max[1] = y;

  if (z < min[2]) min[2] = z;

  if (z > max[2]) max[2] = z;

  ActionInformationVector[scalar]->min = min;
  ActionInformationVector[scalar]->max = max;

  m_actionsBuffer->storePoint(Vector3ui(x, y, z), *pixel);
  *pixel = scalar;
}
Exemple #8
0
Meshes::UID cube(unsigned int quads_pr_edge, unsigned char buffer_bitmask) {
    if (quads_pr_edge == 0)
        return Meshes::UID::invalid_UID();

    unsigned int sides = 6;

    unsigned int verts_pr_edge = quads_pr_edge + 1;
    float scale = 1.0f / quads_pr_edge;
    float halfsize = 0.5f; // verts_pr_edge * 0.5f;
    unsigned int quad_count = quads_pr_edge * quads_pr_edge * sides;
    unsigned int index_count = quad_count * 2;
    unsigned int verts_pr_side = verts_pr_edge * verts_pr_edge;
    unsigned int vertex_count = verts_pr_side * sides;

    Mesh mesh = Meshes::create("Cube", index_count, vertex_count, buffer_bitmask);

    // Create the vertices.
    // [..TOP.. ..BOTTOM.. ..LEFT.. ..RIGHT.. ..FRONT.. ..BACK..]
    Vector3f* position_iterator = mesh.get_positions();
    for (unsigned int i = 0; i < verts_pr_edge; ++i) // Top
        for (unsigned int j = 0; j < verts_pr_edge; ++j)
            *position_iterator++ = Vector3f(halfsize - i * scale, halfsize, j * scale - halfsize);
    for (unsigned int i = 0; i < verts_pr_edge; ++i) // Bottom
        for (unsigned int j = 0; j < verts_pr_edge; ++j)
            *position_iterator++ = Vector3f(halfsize - i * scale, -halfsize, halfsize - j * scale);
    for (unsigned int i = 0; i < verts_pr_edge; ++i) // Left
        for (unsigned int j = 0; j < verts_pr_edge; ++j)
            *position_iterator++ = Vector3f(-halfsize, halfsize - i * scale, j * scale - halfsize);
    for (unsigned int i = 0; i < verts_pr_edge; ++i) // Right
        for (unsigned int j = 0; j < verts_pr_edge; ++j)
            *position_iterator++ = Vector3f(halfsize, i * scale - halfsize, j * scale - halfsize);
    for (unsigned int i = 0; i < verts_pr_edge; ++i) // Front
        for (unsigned int j = 0; j < verts_pr_edge; ++j)
            *position_iterator++ = Vector3f(halfsize - i * scale, halfsize - j * scale, halfsize);
    for (unsigned int i = 0; i < verts_pr_edge; ++i) // Back
        for (unsigned int j = 0; j < verts_pr_edge; ++j)
            *position_iterator++ = Vector3f(i * scale - halfsize, halfsize - j * scale, -halfsize);

    if (mesh.get_normals() != nullptr) {
        Vector3f* normal_iterator = mesh.get_normals();
        while (normal_iterator < mesh.get_normals() + verts_pr_side) // Top
            *normal_iterator++ = Vector3f(0, 1, 0);
        while (normal_iterator < mesh.get_normals() + verts_pr_side * 2) // Bottom
            *normal_iterator++ = Vector3f(0, -1, 0);
        while (normal_iterator < mesh.get_normals() + verts_pr_side * 3) // Left
            *normal_iterator++ = Vector3f(-1, 0, 0);
        while (normal_iterator < mesh.get_normals() + verts_pr_side * 4) // Right
            *normal_iterator++ = Vector3f(1, 0, 0);
        while (normal_iterator < mesh.get_normals() + verts_pr_side * 5) // Front
            *normal_iterator++ = Vector3f(0, 0, 1);
        while (normal_iterator < mesh.get_normals() + verts_pr_side * 6) // Back
            *normal_iterator++ = Vector3f(0, 0, -1);
    }

    if (mesh.get_texcoords() != nullptr) {
        Vector2f* texcoords = mesh.get_texcoords();
        float tc_normalizer = 1.0f / quads_pr_edge;
        for (unsigned int i = 0; i < verts_pr_edge; ++i)
            for (unsigned int j = 0; j < verts_pr_edge; ++j)
                texcoords[i * verts_pr_edge + j] =
                texcoords[i * verts_pr_edge + j + verts_pr_side] =
                texcoords[i * verts_pr_edge + j + verts_pr_side * 2] =
                texcoords[i * verts_pr_edge + j + verts_pr_side * 3] =
                texcoords[i * verts_pr_edge + j + verts_pr_side * 4] =
                texcoords[i * verts_pr_edge + j + verts_pr_side * 5] = Vector2f(float(i), float(j)) * tc_normalizer;
    }

    // Set indices.
    Vector3ui* primitives = mesh.get_primitives();
    for (unsigned int side_offset = 0; side_offset < vertex_count; side_offset += verts_pr_side)
        for (unsigned int i = 0; i < quads_pr_edge; ++i)
            for (unsigned int j = 0; j < quads_pr_edge; ++j) {
                *primitives++ = Vector3ui(j + i * verts_pr_edge,
                                       j + (i + 1) * verts_pr_edge,
                                       j + 1 + i * verts_pr_edge) + side_offset;

                *primitives++ = Vector3ui(j + 1 + i * verts_pr_edge,
                                       j + (i + 1) * verts_pr_edge,
                                       j + 1 + (i + 1) * verts_pr_edge) + side_offset;
            }

    mesh.set_bounds(AABB(Vector3f(-halfsize), Vector3f(halfsize)));

    return mesh.get_ID();
}
Exemple #9
0
Meshes::UID cylinder(unsigned int vertical_quads, unsigned int circumference_quads, unsigned char buffer_bitmask) {
    if (vertical_quads == 0 || circumference_quads == 0)
        return Meshes::UID::invalid_UID();

    unsigned int lid_vertex_count = circumference_quads + 1;
    unsigned int side_vertex_count = (vertical_quads + 1) * circumference_quads;
    unsigned int vertex_count = 2 * lid_vertex_count + side_vertex_count;
    unsigned int lid_index_count = circumference_quads;
    unsigned int side_index_count = 2 * vertical_quads * circumference_quads;
    unsigned int index_count = 2 * lid_index_count + side_index_count;
    float radius = 0.5f;

    Mesh mesh = Meshes::create("Cylinder", index_count, vertex_count, buffer_bitmask);

    // Vertex layout is
    // [..TOP.. ..BOTTOM.. ..SIDE..]

    { // Positions.
        Vector3f* positions = mesh.get_positions();
        // Create top positions.
        positions[0] = Vector3f(0.0f, radius, 0.0f);
        for (unsigned int v = 0; v < circumference_quads; ++v) {
            float radians = v / float(circumference_quads) * 2.0f * Math::PI<float>();
            positions[v + 1] = Vector3f(cos(radians) * radius, radius, sin(radians) * radius);
        }

        // Mirror top to create bottom positions.
        for (unsigned int v = 0; v < lid_vertex_count; ++v) {
            positions[lid_vertex_count + v] = positions[v];
            positions[lid_vertex_count + v].y = -radius;
        }

        // Create side positions.
        for (unsigned int i = 0; i < vertical_quads + 1; ++i) {
            float l = i / float(vertical_quads);
            for (unsigned int j = 0; j < circumference_quads; ++j) {
                unsigned int vertex_index = 2 * lid_vertex_count + i * circumference_quads + j;
                positions[vertex_index] = positions[j+1];
                positions[vertex_index].y = lerp(radius, -radius, l);
            }
        }
    }

    if (mesh.get_normals() != nullptr) {
        Vector3f* normal_iterator = mesh.get_normals();
        while (normal_iterator < mesh.get_normals() + lid_vertex_count) // Top
            *normal_iterator++ = Vector3f(0, 1, 0);
        while (normal_iterator < mesh.get_normals() + 2 * lid_vertex_count) // Bottom
            *normal_iterator++ = Vector3f(0, -1, 0);
        Vector3f* side_position_iterator = mesh.get_positions() + 2 * lid_vertex_count;
        while (normal_iterator < mesh.get_normals() + vertex_count) { // Side
            Vector3f position = *side_position_iterator++;
            *normal_iterator++ = normalize(Vector3f(position.x, 0.0f, position.z));
        }
    }

    if (mesh.get_texcoords() != nullptr) {
        Vector2f* texcoords = mesh.get_texcoords();

        // Top and bottom.
        for (unsigned int i = 0; i < 2 * lid_vertex_count; ++i) {
            Vector3f position = mesh.get_positions()[i];
            texcoords[i] = Vector2f(position.x, position.z) + 0.5f;
        }

        // Side.
        for (unsigned int i = 0; i < vertical_quads + 1; ++i) {
            float v = i / float(vertical_quads);
            for (unsigned int j = 0; j < circumference_quads; ++j) {
                unsigned int vertex_index = 2 * lid_vertex_count + i * circumference_quads + j;
                float u = abs(-2.0f * j / float(circumference_quads) + 1.0f); // Magic u mapping. Mirror repeat mapping of the texture coords.
                texcoords[vertex_index] = Vector2f(u, v);
            }
        }
    }

    { // Primitives.
        Vector3ui* primitives = mesh.get_primitives();

        // Top.
        for (unsigned int i = 0; i < lid_index_count; ++i)
            primitives[i] = Vector3ui(0, i + 2, i + 1);
        primitives[lid_index_count - 1].y = 1;

        // Bottom.
        for (unsigned int i = 0; i < lid_index_count; ++i)
            primitives[i + lid_index_count] = Vector3ui(0, i + 1, i + 2) + lid_vertex_count;
        primitives[2 * lid_index_count - 1].z = 1 + lid_vertex_count;

        // Side.
        unsigned int side_vertex_offset = 2 * lid_vertex_count;
        for (unsigned int i = 0; i < vertical_quads; ++i) {
            for (unsigned int j = 0; j < circumference_quads; ++j) {
                unsigned int side_index = 2 * lid_index_count + 2 * (i * circumference_quads + j);

                unsigned int i0 = i * circumference_quads + j;
                unsigned int i1 = (i + 1) * circumference_quads + j;
                unsigned int j_plus_1 = (j + 1) < circumference_quads ? (j + 1) : 0; // Handle wrap around.
                unsigned int i2 = i * circumference_quads + j_plus_1;
                unsigned int i3 = (i + 1) * circumference_quads + j_plus_1;

                primitives[side_index + 0] = Vector3ui(i0, i3, i1) + side_vertex_offset;
                primitives[side_index + 1] = Vector3ui(i0, i2, i3) + side_vertex_offset;
            }
        }
    }

    mesh.set_bounds(AABB(Vector3f(-radius), Vector3f(radius)));

    return mesh.get_ID();
}