| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | #include "SceneLoader.h" |
|---|
| 9 | |
|---|
| 10 | #include <osg/Notify> |
|---|
| 11 | #include <osg/PositionAttitudeTransform> |
|---|
| 12 | #include <osg/AnimationPath> |
|---|
| 13 | #include <osg/io_utils> |
|---|
| 14 | |
|---|
| 15 | #include <osgDB/FileUtils> |
|---|
| 16 | #include <osgDB/FileNameUtils> |
|---|
| 17 | #include <osgDB/fstream> |
|---|
| 18 | #include <osgDB/ReadFile> |
|---|
| 19 | #include <osgDB/WriteFile> |
|---|
| 20 | |
|---|
| 21 | #include <sstream> |
|---|
| 22 | |
|---|
| 23 | using namespace lwosg; |
|---|
| 24 | |
|---|
| 25 | namespace |
|---|
| 26 | { |
|---|
| 27 | |
|---|
| 28 | int str_to_int(const std::string &s) |
|---|
| 29 | { |
|---|
| 30 | std::istringstream iss(s); |
|---|
| 31 | int n; |
|---|
| 32 | iss >> n; |
|---|
| 33 | return n; |
|---|
| 34 | } |
|---|
| 35 | |
|---|
| 36 | int hex_to_int(const std::string &s) |
|---|
| 37 | { |
|---|
| 38 | std::istringstream iss(s); |
|---|
| 39 | int n; |
|---|
| 40 | iss >> std::hex >> n; |
|---|
| 41 | return n; |
|---|
| 42 | } |
|---|
| 43 | |
|---|
| 44 | osg::Quat rotate_ypr(const osg::Vec3 &ypr, const osg::Vec3 pivot_rot = osg::Vec3(0, 0, 0)) |
|---|
| 45 | { |
|---|
| 46 | osg::Quat Q1(ypr.z(), osg::Vec3(0, -1, 0)); |
|---|
| 47 | osg::Quat Q2(ypr.y(), osg::Vec3(-1, 0, 0)); |
|---|
| 48 | osg::Quat Q3(ypr.x(), osg::Vec3(0, 0, -1)); |
|---|
| 49 | osg::Quat Q4(pivot_rot.z(), osg::Vec3(0, -1, 0)); |
|---|
| 50 | osg::Quat Q5(pivot_rot.y(), osg::Vec3(-1, 0, 0)); |
|---|
| 51 | osg::Quat Q6(pivot_rot.x(), osg::Vec3(0, 0, -1)); |
|---|
| 52 | return Q1 * Q2 * Q3 * Q4 * Q5 * Q6; |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | void trim(std::string& str) |
|---|
| 56 | { |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | while (!str.empty() && str[str.size()-1]<32) |
|---|
| 60 | { |
|---|
| 61 | |
|---|
| 62 | |
|---|
| 63 | str.erase(str.size()-1); |
|---|
| 64 | } |
|---|
| 65 | |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | } |
|---|
| 69 | |
|---|
| 70 | |
|---|
| 71 | SceneLoader::SceneLoader() |
|---|
| 72 | : capture_obj_motion_(false), |
|---|
| 73 | capture_cam_motion_(false) |
|---|
| 74 | { |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | SceneLoader::SceneLoader(const Options &options) |
|---|
| 78 | : capture_obj_motion_(false), |
|---|
| 79 | capture_cam_motion_(false), |
|---|
| 80 | options_(options) |
|---|
| 81 | { |
|---|
| 82 | } |
|---|
| 83 | |
|---|
| 84 | osg::Group *SceneLoader::load(const std::string &filename, const osgDB::ReaderWriter::Options *options, bool search) |
|---|
| 85 | { |
|---|
| 86 | std::string fname; |
|---|
| 87 | |
|---|
| 88 | if (search) { |
|---|
| 89 | fname = osgDB::findDataFile(filename, options); |
|---|
| 90 | if (fname.empty()) return 0; |
|---|
| 91 | } else { |
|---|
| 92 | fname = filename; |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | osgDB::ifstream ifs(fname.c_str()); |
|---|
| 96 | if (!ifs.is_open()) return 0; |
|---|
| 97 | |
|---|
| 98 | clear(); |
|---|
| 99 | |
|---|
| 100 | std::string identifier; |
|---|
| 101 | while (ifs >> identifier) { |
|---|
| 102 | if (identifier == "{") { |
|---|
| 103 | ifs >> identifier; |
|---|
| 104 | std::ws(ifs); |
|---|
| 105 | std::vector<std::string> data; |
|---|
| 106 | std::string data_line; |
|---|
| 107 | while (std::getline(ifs, data_line)) { |
|---|
| 108 | trim(data_line); |
|---|
| 109 | if (data_line == "}") { |
|---|
| 110 | std::ws(ifs); |
|---|
| 111 | break; |
|---|
| 112 | } |
|---|
| 113 | data.push_back(data_line); |
|---|
| 114 | std::ws(ifs); |
|---|
| 115 | } |
|---|
| 116 | if (!data.empty()) { |
|---|
| 117 | if (!parse_block(identifier, data)) { |
|---|
| 118 | return 0; |
|---|
| 119 | } |
|---|
| 120 | } |
|---|
| 121 | } else { |
|---|
| 122 | std::string data; |
|---|
| 123 | std::getline(ifs, data); |
|---|
| 124 | trim(data); |
|---|
| 125 | std::istringstream iss(data); |
|---|
| 126 | std::ws(iss); |
|---|
| 127 | std::getline(iss, data); |
|---|
| 128 | trim(data); |
|---|
| 129 | if (!parse_block(identifier, data)) { |
|---|
| 130 | return 0; |
|---|
| 131 | } |
|---|
| 132 | } |
|---|
| 133 | } |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | for (Scene_camera_list::iterator ci=scene_cameras_.begin(); ci!=scene_cameras_.end(); ++ci) { |
|---|
| 137 | if (!ci->motion.keys.empty()) { |
|---|
| 138 | osg::ref_ptr<osg::AnimationPath> ap = new osg::AnimationPath; |
|---|
| 139 | for (Motion_envelope::Key_map::const_iterator j=ci->motion.keys.begin(); j!=ci->motion.keys.end(); ++j) { |
|---|
| 140 | osg::Vec3 pos(options_.csf->fix_point(j->second.position)); |
|---|
| 141 | |
|---|
| 142 | osg::AnimationPath::ControlPoint cp(pos, osg::Quat(osg::PI_2, osg::Vec3(1, 0, 0)) * rotate_ypr(j->second.ypr), j->second.scale); |
|---|
| 143 | OSG_NOTICE<<"scale = "<<j->second.scale<<std::endl; |
|---|
| 144 | ap->insert(j->first, cp); |
|---|
| 145 | } |
|---|
| 146 | camera_animations_.push_back(ap.get()); |
|---|
| 147 | } |
|---|
| 148 | } |
|---|
| 149 | |
|---|
| 150 | |
|---|
| 151 | typedef std::map<int, osg::ref_ptr<osg::PositionAttitudeTransform> > PAT_map; |
|---|
| 152 | PAT_map pats; |
|---|
| 153 | int j = 0; |
|---|
| 154 | for (Scene_object_list::iterator i=scene_objects_.begin(); i!=scene_objects_.end(); ++i, ++j) { |
|---|
| 155 | osg::ref_ptr<osg::PositionAttitudeTransform> pat = pats[j]; |
|---|
| 156 | if (!pat.valid()) { |
|---|
| 157 | pat = new osg::PositionAttitudeTransform; |
|---|
| 158 | pats[j] = pat; |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | pat->setName(i->name); |
|---|
| 162 | pat->addChild(i->layer_node.get()); |
|---|
| 163 | pat->setPivotPoint(options_.csf->fix_point(i->pivot)); |
|---|
| 164 | |
|---|
| 165 | |
|---|
| 166 | if (!i->motion.keys.empty()) { |
|---|
| 167 | pat->setPosition(options_.csf->fix_point(i->motion.keys.begin()->second.position)); |
|---|
| 168 | pat->setAttitude(rotate_ypr(i->motion.keys.begin()->second.ypr, i->pivot_rot)); |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | |
|---|
| 172 | if (i->motion.keys.size() > 1) { |
|---|
| 173 | osg::ref_ptr<osg::AnimationPath> ap = new osg::AnimationPath; |
|---|
| 174 | for (Motion_envelope::Key_map::const_iterator j=i->motion.keys.begin(); j!=i->motion.keys.end(); ++j) { |
|---|
| 175 | osg::Vec3 pos(options_.csf->fix_point(j->second.position)); |
|---|
| 176 | osg::AnimationPath::ControlPoint cp(pos, rotate_ypr(j->second.ypr, i->pivot_rot), j->second.scale); |
|---|
| 177 | ap->insert(j->first, cp); |
|---|
| 178 | } |
|---|
| 179 | osg::ref_ptr<osg::AnimationPathCallback> apc = new osg::AnimationPathCallback(ap.get()); |
|---|
| 180 | apc->setPivotPoint(options_.csf->fix_point(i->pivot)); |
|---|
| 181 | pat->setUpdateCallback(apc.get()); |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | if (i->parent == -1) { |
|---|
| 185 | root_->addChild(pat.get()); |
|---|
| 186 | } else { |
|---|
| 187 | if (i->parent < static_cast<int>(scene_objects_.size())) { |
|---|
| 188 | osg::ref_ptr<osg::PositionAttitudeTransform> parent = pats[i->parent]; |
|---|
| 189 | if (!parent.valid()) { |
|---|
| 190 | parent = new osg::PositionAttitudeTransform; |
|---|
| 191 | pats[i->parent] = parent; |
|---|
| 192 | } |
|---|
| 193 | parent->addChild(pat.get()); |
|---|
| 194 | } else { |
|---|
| 195 | OSG_WARN << "Warning: lwosg::SceneLoader: invalid parent" << std::endl; |
|---|
| 196 | } |
|---|
| 197 | } |
|---|
| 198 | } |
|---|
| 199 | |
|---|
| 200 | return root_.get(); |
|---|
| 201 | } |
|---|
| 202 | |
|---|
| 203 | bool SceneLoader::parse_block(const std::string &name, const std::string &data) |
|---|
| 204 | { |
|---|
| 205 | std::istringstream iss(data); |
|---|
| 206 | |
|---|
| 207 | if (name == "AddCamera") { |
|---|
| 208 | scene_cameras_.push_back(Scene_camera()); |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | if (name == "AddNullObject") { |
|---|
| 212 | osg::ref_ptr<osg::Group> nullobjnode = new osg::Group; |
|---|
| 213 | nullobjnode->setName(data); |
|---|
| 214 | objects_[data] = nullobjnode; |
|---|
| 215 | Scene_object so; |
|---|
| 216 | so.layer_node = nullobjnode.get(); |
|---|
| 217 | scene_objects_.push_back(so); |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | if (name == "LoadObjectLayer") { |
|---|
| 221 | unsigned layer; |
|---|
| 222 | iss >> layer; |
|---|
| 223 | std::ws(iss); |
|---|
| 224 | std::string filename; |
|---|
| 225 | std::getline(iss, filename); |
|---|
| 226 | |
|---|
| 227 | |
|---|
| 228 | trim(filename); |
|---|
| 229 | |
|---|
| 230 | if (!filename.empty()) |
|---|
| 231 | { |
|---|
| 232 | |
|---|
| 233 | |
|---|
| 234 | osg::ref_ptr<osg::Group> objnode; |
|---|
| 235 | |
|---|
| 236 | Object_map::const_iterator i = objects_.find(filename); |
|---|
| 237 | |
|---|
| 238 | if (i == objects_.end()) { |
|---|
| 239 | |
|---|
| 240 | OSG_NOTICE << "Loading object \"" << filename << "\"" << std::endl; |
|---|
| 241 | |
|---|
| 242 | objnode = dynamic_cast<osg::Group *>(osgDB::readNodeFile(filename)); |
|---|
| 243 | if (!objnode.valid()) return false; |
|---|
| 244 | |
|---|
| 245 | objects_[filename] = objnode; |
|---|
| 246 | |
|---|
| 247 | } else { |
|---|
| 248 | objnode = i->second; |
|---|
| 249 | } |
|---|
| 250 | |
|---|
| 251 | if (layer > objnode->getNumChildren()) { |
|---|
| 252 | OSG_WARN << "Warning: lwosg::SceneLoader: layer " << layer << " does not exist in object " << filename << std::endl; |
|---|
| 253 | return 0; |
|---|
| 254 | } |
|---|
| 255 | |
|---|
| 256 | Scene_object so; |
|---|
| 257 | std::ostringstream oss; |
|---|
| 258 | oss << filename << "." << layer; |
|---|
| 259 | so.name = oss.str(); |
|---|
| 260 | so.layer_node = objnode->getChild(layer-1); |
|---|
| 261 | if (so.layer_node.valid()) { |
|---|
| 262 | scene_objects_.push_back(so); |
|---|
| 263 | } |
|---|
| 264 | } |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | if (name == "PivotPosition") { |
|---|
| 268 | if (!scene_objects_.empty()) { |
|---|
| 269 | osg::Vec3 pivot; |
|---|
| 270 | iss >> pivot.x() >> pivot.y() >> pivot.z(); |
|---|
| 271 | scene_objects_.back().pivot = pivot; |
|---|
| 272 | } |
|---|
| 273 | } |
|---|
| 274 | |
|---|
| 275 | if (name == "PivotRotation") { |
|---|
| 276 | if (!scene_objects_.empty()) { |
|---|
| 277 | osg::Vec3 pivot; |
|---|
| 278 | iss >> pivot.x() >> pivot.y() >> pivot.z(); |
|---|
| 279 | scene_objects_.back().pivot_rot = pivot * (osg::PI / 180.0f); |
|---|
| 280 | } |
|---|
| 281 | } |
|---|
| 282 | |
|---|
| 283 | if (name == "ParentItem") { |
|---|
| 284 | if (!scene_objects_.empty()) { |
|---|
| 285 | std::string id; |
|---|
| 286 | iss >> id; |
|---|
| 287 | if (id.length() == 8) { |
|---|
| 288 | if (id[0] == '1') { |
|---|
| 289 | id.erase(0, 1); |
|---|
| 290 | scene_objects_.back().parent = hex_to_int(id); |
|---|
| 291 | } |
|---|
| 292 | } else { |
|---|
| 293 | scene_objects_.back().parent = str_to_int(id); |
|---|
| 294 | } |
|---|
| 295 | } |
|---|
| 296 | } |
|---|
| 297 | |
|---|
| 298 | if (name == "NumChannels") { |
|---|
| 299 | iss >> channel_count_; |
|---|
| 300 | } |
|---|
| 301 | |
|---|
| 302 | if (name == "Channel") { |
|---|
| 303 | iss >> current_channel_; |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | if (name == "ObjectMotion") { |
|---|
| 307 | capture_obj_motion_ = true; |
|---|
| 308 | } |
|---|
| 309 | |
|---|
| 310 | if (name == "CameraMotion") { |
|---|
| 311 | capture_cam_motion_ = true; |
|---|
| 312 | } |
|---|
| 313 | |
|---|
| 314 | return true; |
|---|
| 315 | } |
|---|
| 316 | |
|---|
| 317 | bool SceneLoader::parse_block(const std::string &name, const std::vector<std::string> &data) |
|---|
| 318 | { |
|---|
| 319 | if (name == "Envelope") { |
|---|
| 320 | if (((capture_obj_motion_ && !scene_objects_.empty()) || |
|---|
| 321 | (capture_cam_motion_ && !scene_cameras_.empty())) && |
|---|
| 322 | (data.size() >= 2)) { |
|---|
| 323 | |
|---|
| 324 | Motion_envelope::Key_map &keys = capture_obj_motion_ ? scene_objects_.back().motion.keys : scene_cameras_.back().motion.keys; |
|---|
| 325 | |
|---|
| 326 | if (current_channel_ >= (channel_count_ - 1)) { |
|---|
| 327 | capture_obj_motion_ = false; |
|---|
| 328 | capture_cam_motion_ = false; |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | for (unsigned i=1; i<data.size(); ++i) { |
|---|
| 332 | std::istringstream iss(data[i]); |
|---|
| 333 | std::string key_id; |
|---|
| 334 | iss >> key_id; |
|---|
| 335 | if (key_id == "Key") { |
|---|
| 336 | float value; |
|---|
| 337 | double time; |
|---|
| 338 | if (iss >> value >> time) { |
|---|
| 339 | switch (current_channel_) { |
|---|
| 340 | case 0: keys[time].position.x() = value; break; |
|---|
| 341 | case 1: keys[time].position.y() = value; break; |
|---|
| 342 | case 2: keys[time].position.z() = value; break; |
|---|
| 343 | case 3: keys[time].ypr.x() = value; break; |
|---|
| 344 | case 4: keys[time].ypr.y() = value; break; |
|---|
| 345 | case 5: keys[time].ypr.z() = value; break; |
|---|
| 346 | case 6: keys[time].scale.x() = value; break; |
|---|
| 347 | case 7: keys[time].scale.y() = value; break; |
|---|
| 348 | case 8: keys[time].scale.z() = value; break; |
|---|
| 349 | default: ; |
|---|
| 350 | } |
|---|
| 351 | } |
|---|
| 352 | } |
|---|
| 353 | } |
|---|
| 354 | } |
|---|
| 355 | } |
|---|
| 356 | return true; |
|---|
| 357 | } |
|---|
| 358 | |
|---|
| 359 | void SceneLoader::clear() |
|---|
| 360 | { |
|---|
| 361 | root_ = new osg::Group; |
|---|
| 362 | objects_.clear(); |
|---|
| 363 | scene_objects_.clear(); |
|---|
| 364 | scene_cameras_.clear(); |
|---|
| 365 | camera_animations_.clear(); |
|---|
| 366 | channel_count_ = 0; |
|---|
| 367 | current_channel_ = 0; |
|---|
| 368 | } |
|---|