// // Copyright 2016 Pixar // // Licensed under the Apache License, Version 2.0 (the "Apache License") // with the following modification; you may not use this file except in // compliance with the Apache License and the following modification to it: // Section 6. Trademarks. is deleted and replaced with: // // 6. Trademarks. This License does not grant permission to use the trade // names, trademarks, service marks, or product names of the Licensor // and its affiliates, except as required to comply with Section 4(c) of // the License and to reproduce the content of the NOTICE file. // // You may obtain a copy of the Apache License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the Apache License with the above modification is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the Apache License for the specific // language governing permissions and limitations under the Apache License. // #include "pxr/pxr.h" #include "streamIO.h" #include "stream.h" #include "pxr/base/tf/stringUtils.h" #include #include #include #include #include #include using std::string; using std::vector; PXR_NAMESPACE_OPEN_SCOPE bool UsdObjReadDataFromFile(std::string const &fileName, UsdObjStream *stream, std::string *error) { // try and open the file std::ifstream fin(fileName.c_str()); if (!fin.is_open()) { if (error) { *error = TfStringPrintf("Could not open file: (%s)\n", fileName.c_str()); } return false; } return UsdObjReadDataFromStream(fin, stream, error); } static UsdObjStream::Point _ParsePoint(string const &str) { using boost::iterator_range; using boost::make_iterator_range; using boost::lexical_cast; UsdObjStream::Point result; // Break the string up into up to 3 segments separated by slashes. iterator_range ranges[3]; int numRanges = 0; char const *from = str.data(), *pos = str.data(), *end = str.data() + strlen(str.data()); while (numRanges != 3) { pos = std::find(from, end, '/'); ranges[numRanges++] = make_iterator_range(from, pos); if (pos == end) break; from = pos + 1; } // Now pull indexes out of the segments. Subtract one since indexes are // 1-based in the file, but we store them 0-based in the data structure. int *indexes[] = {&result.vertIndex, &result.uvIndex, &result.normalIndex}; for (int i = 0; i != numRanges; ++i) { if (!ranges[i].empty()) *indexes[i] = lexical_cast(ranges[i]) - 1; } return result; } bool UsdObjReadDataFromStream(std::istream &input, UsdObjStream *stream, std::string *error) { string line; std::istringstream lineStream; UsdObjStream::Group curGroup; while (getline(input, line)) { if (line.empty()) continue; // check the first character for the type lineStream.clear(); lineStream.str(line); string type; lineStream >> type; if (type == "v") { GfVec3f newVert; lineStream >> newVert[0] >> newVert[1] >> newVert[2]; stream->AddVert(newVert); } else if (type == "vt") { GfVec2f newUV; lineStream >> newUV[0] >> newUV[1]; stream->AddUV(newUV); } else if (type == "vn") { GfVec3f newNormal; lineStream >> newNormal[0] >> newNormal[1] >> newNormal[2]; stream->AddNormal(newNormal); } else if (type == "f") { int pointsBegin = int(stream->GetPoints().size()), pointsEnd; std::string indexStr; while (lineStream >> indexStr) stream->AddPoint(_ParsePoint(indexStr)); pointsEnd = int(stream->GetPoints().size()); stream->AddFace(UsdObjStream::Face(pointsBegin, pointsEnd)); } else if (type == "g") { // Create new group. string groupName; lineStream >> groupName; stream->AddGroup(groupName); } else { // Add arbitrary text (or comment). stream->AppendArbitraryText(line); } } return true; } PXR_NAMESPACE_CLOSE_SCOPE