| 213 | } |
| 214 | |
| 215 | sibr::Matrix4f parseTransform(const rapidxml::xml_node<>* nodeTrans) |
| 216 | { |
| 217 | sibr::Matrix4f objectToWorld = sibr::Matrix4f::Identity(); |
| 218 | if (nodeTrans) |
| 219 | { |
| 220 | // Helper functions |
| 221 | const auto getfValue = [&](rapidxml::xml_node<>* n, std::string const& name, float& value) { |
| 222 | if (n && n->first_attribute(name.c_str())) { |
| 223 | value = std::stof(n->first_attribute(name.c_str())->value()); |
| 224 | } |
| 225 | }; |
| 226 | const auto getVector = [&](rapidxml::xml_node<>* n, std::string const& name, sibr::Vector3f& vec) { |
| 227 | const auto isNonFloat = [](const char c) { |
| 228 | return c == ',' || c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '"' || c == 0; |
| 229 | }; |
| 230 | const auto eatNonFloat = [&](const char* str, int& i) { |
| 231 | while (isNonFloat(str[i])) ++i; |
| 232 | }; |
| 233 | const auto eatFloat = [&](const char* str, int& i) { |
| 234 | while (!isNonFloat(str[i])) ++i; |
| 235 | }; |
| 236 | if (n && n->first_attribute(name.c_str())) { |
| 237 | int index = 0; |
| 238 | const char* value = n->first_attribute(name.c_str())->value(); |
| 239 | for (int i = 0; i < vec.size(); ++i) { |
| 240 | eatNonFloat(value, index); |
| 241 | vec[i] = std::atof(value + index); |
| 242 | eatFloat(value, index); |
| 243 | } |
| 244 | } |
| 245 | }; |
| 246 | const auto getAxesValues = [&](rapidxml::xml_node<>* n, float& x, float& y, float& z) { |
| 247 | getfValue(n, "x", x); |
| 248 | getfValue(n, "y", y); |
| 249 | getfValue(n, "z", z); |
| 250 | }; |
| 251 | |
| 252 | // Loop through all the transform commands, |
| 253 | // and "accumulate" the transform matrices into "objectToWorld" |
| 254 | for (rapidxml::xml_node<>* node = nodeTrans->first_node(); node; node = node->next_sibling()) { |
| 255 | sibr::Matrix4f nodeMatrix = sibr::Matrix4f::Identity(); |
| 256 | const char* transformType = node->name(); |
| 257 | if (strcmp(transformType, "matrix") == 0) { |
| 258 | std::string matrixValue = node->first_attribute("value")->value(); |
| 259 | std::istringstream issMatrix(matrixValue); |
| 260 | std::vector<std::string> split( |
| 261 | std::istream_iterator<std::string>{issMatrix}, |
| 262 | std::istream_iterator<std::string>()); |
| 263 | nodeMatrix << |
| 264 | std::stof(split[0]), std::stof(split[1]), std::stof(split[2]), std::stof(split[3]), |
| 265 | std::stof(split[4]), std::stof(split[5]), std::stof(split[6]), std::stof(split[7]), |
| 266 | std::stof(split[8]), std::stof(split[9]), std::stof(split[10]), std::stof(split[11]), |
| 267 | std::stof(split[12]), std::stof(split[13]), std::stof(split[14]), std::stof(split[15]); |
| 268 | } |
| 269 | else if (strcmp(transformType, "translate") == 0) { |
| 270 | getAxesValues(node, nodeMatrix(0, 3), nodeMatrix(1, 3), nodeMatrix(2, 3)); |
| 271 | } |
| 272 | else if (strcmp(transformType, "scale") == 0) { |