bool Parser::parseGeometry()

in src/esp/io/URDFParser.cpp [711:816]


bool Parser::parseGeometry(Geometry& geom, const XMLElement* g) {
  if (g == nullptr)
    return false;

  const XMLElement* shape = g->FirstChildElement();
  if (!shape) {
    ESP_VERY_VERBOSE() << "Geometry tag contains no child element.";
    return false;
  }

  // const std::string type_name = shape->ValueTStr().c_str();
  const std::string type_name = shape->Value();
  if (type_name == "sphere") {
    geom.m_type = GEOM_SPHERE;

    if (!shape->Attribute("radius")) {
      ESP_VERY_VERBOSE() << "Sphere shape must have a radius attribute";
      return false;
    } else {
      geom.m_sphereRadius = std::stod(shape->Attribute("radius"));
    }
  } else if (type_name == "box") {
    geom.m_type = GEOM_BOX;
    if (!shape->Attribute("size")) {
      ESP_VERY_VERBOSE() << "Box requires a size attribute";
      return false;
    } else {
      parseVector3(geom.m_boxSize, shape->Attribute("size"));
    }
  } else if (type_name == "cylinder") {
    geom.m_type = GEOM_CYLINDER;
    geom.m_capsuleRadius = 0.1;
    geom.m_capsuleHeight = 0.1;

    if (!shape->Attribute("length") || !shape->Attribute("radius")) {
      ESP_VERY_VERBOSE()
          << "Cylinder shape must have both length and radius attributes";
      return false;
    }
    geom.m_capsuleRadius = std::stod(shape->Attribute("radius"));
    geom.m_capsuleHeight = std::stod(shape->Attribute("length"));

  } else if (type_name == "capsule") {
    geom.m_type = GEOM_CAPSULE;

    if (!shape->Attribute("length") || !shape->Attribute("radius")) {
      ESP_VERY_VERBOSE()
          << "Capsule shape must have both length and radius attributes";
      return false;
    }
    geom.m_capsuleRadius = std::stod(shape->Attribute("radius"));
    geom.m_capsuleHeight = std::stod(shape->Attribute("length"));

  } else if (type_name == "mesh") {
    geom.m_type = GEOM_MESH;
    geom.m_meshScale = Mn::Vector3(1.0, 1.0, 1.0);
    std::string fn;

    if (shape->Attribute("filename")) {
      fn = shape->Attribute("filename");
    }
    if (shape->Attribute("scale")) {
      if (!parseVector3(geom.m_meshScale, shape->Attribute("scale"))) {
        ESP_VERY_VERBOSE() << "W - Scale should be a vector3, not "
                              "single scalar. Workaround activated.";
        std::string scalar_str = shape->Attribute("scale");
        double scaleFactor = std::stod(scalar_str);
        if (scaleFactor != 0.0) {
          geom.m_meshScale = Mn::Vector3(scaleFactor);
        }
      }
    }

    if (fn.empty()) {
      ESP_VERY_VERBOSE() << "Mesh filename is empty";
      return false;
    }

    geom.m_meshFileName = fn;

    // load the mesh and modify the filename to full path to reference loaded
    // asset
    bool success = validateMeshFile(geom.m_meshFileName);

    if (!success) {
      // warning already printed
      return false;
    }
  } else {
    if (type_name == "plane") {
      geom.m_type = GEOM_PLANE;

      if (!shape->Attribute("normal")) {
        ESP_VERY_VERBOSE() << "Plane requires a normal attribute";
        return false;
      } else {
        parseVector3(geom.m_planeNormal, shape->Attribute("normal"));
      }
    } else {
      ESP_VERY_VERBOSE() << "Unknown geometry type:" << type_name;
      return false;
    }
  }

  return true;
}