Cesium开发&osgb倾斜数据发布工具开发数据解析遇到的问题

今天在写到osgb数据解析,用到的tinygltf是高版本的,模型类Model带有扩展属性。其中扩展数据需要相应的键值解析json,这里使用的是tinygltf2.2,该版本需要std_img_write.h v1.11的支持,目前我使用的是这个版本。这事起于,自己想解决3dtile中不需要修改前端代码,而是修改3dtile的数据格式,这样的一个想法。那么这里着重是要解决扩展数据json的拼接。而这里使用到了tinygltf的相关函数。

这里要是说明的是使用json键值解析时候原来的函数有点问题,其中源函数是这样定义的。

static bool ValueToJson(const Value &value, json *ret) {
  json obj;
  switch (value.Type()) {
    case NUMBER_TYPE:
      obj = json(value.Get<double>());
      break;
    case INT_TYPE:
      obj = json(value.Get<int>());
      break;
    case BOOL_TYPE:
      obj = json(value.Get<bool>());
      break;
    case STRING_TYPE:
      obj = json(value.Get<std::string>());
      break;
    case ARRAY_TYPE: {
      for (unsigned int i = 0; i < value.ArrayLen(); ++i) {
        Value elementValue = value.Get(int(i));
        json elementJson;
        if (ValueToJson(value.Get(int(i)), &elementJson))
          obj.push_back(elementJson);
      }
      break;
    }
    case BINARY_TYPE:
      // TODO
      // obj = json(value.Get<std::vector<unsigned char>>());
      return false;
      break;
    case OBJECT_TYPE: {
      Value::Object objMap = value.Get<Value::Object>();
      for (auto &it : objMap) {
        json elementJson;
        if (ValueToJson(it.second, &elementJson)) obj[it.first] = elementJson;
      }
      break;
    }
    case NULL_TYPE:
    default:
      return false;
  }
  if (ret) *ret = obj;
  return true;
}

但是在ValueToJson递归中出现了很大的问题,首先我们来说明一下类型为string值的键值,形如下面的形式。

				tinygltf::ExtensionMap exu_modelViewMatrix;
				exu_modelViewMatrix["semantic"] = tinygltf::Value("MODELVIEW");

在json应该解析为"semantic":"MODELVIES",可是事实在上面的函数中返回的是这样的结果:"semantic":true,这下惊呆了小伙伴。而如果我们使用如下的方式来赋值。干脆就不返回了"semantic"的值了。

				string str = "_BATCHID";
				exA_batchid["semantic"]= tinygltf::Value(str);

可能我们会去查看,tinygltf::Value是如何定义的,是的,我们来看一下该类的结构。

class Value {
 public:
  typedef std::vector<Value> Array;
  typedef std::map<std::string, Value> Object;

  Value() : type_(NULL_TYPE) {}

  explicit Value(bool b) : type_(BOOL_TYPE) { 
	  boolean_value_ = b; }
  explicit Value(int i) : type_(INT_TYPE) { 
	  int_value_ = i; }
  explicit Value(double n) : type_(NUMBER_TYPE) { 
	  number_value_ = n; }
  explicit Value(const std::string &s) : type_(STRING_TYPE) {
    string_value_ = s;
  }
  explicit Value(const unsigned char *p, size_t n) : type_(BINARY_TYPE) {
    binary_value_.resize(n);
    memcpy(binary_value_.data(), p, n);
  }
  explicit Value(const Array &a) : type_(ARRAY_TYPE) {
    array_value_ = Array(a);
  }
  explicit Value(const Object &o) : type_(OBJECT_TYPE) {
    object_value_ = Object(o);
  }

  char Type() const { return static_cast<const char>(type_); }

  bool IsBool() const { return (type_ == BOOL_TYPE); }

  bool IsInt() const { return (type_ == INT_TYPE); }

  bool IsNumber() const { return (type_ == NUMBER_TYPE); }

  bool IsString() const { return (type_ == STRING_TYPE); }

  bool IsBinary() const { return (type_ == BINARY_TYPE); }

  bool IsArray() const { return (type_ == ARRAY_TYPE); }

  bool IsObject() const { return (type_ == OBJECT_TYPE); }

  // Accessor
  template <typename T>
  const T &Get() const;
  template <typename T>
  T &Get();

  // Lookup value from an array
  const Value &Get(int idx) const {
    static Value null_value;
    assert(IsArray());
    assert(idx >= 0);
    return (static_cast<size_t>(idx) < array_value_.size())
               ? array_value_[static_cast<size_t>(idx)]
               : null_value;
  }

  // Lookup value from a key-value pair
  const Value &Get(const std::string &key) const {
    static Value null_value;
    assert(IsObject());
    Object::const_iterator it = object_value_.find(key);
    return (it != object_value_.end()) ? it->second : null_value;
  }

  size_t ArrayLen() const {
    if (!IsArray()) return 0;
    return array_value_.size();
  }

  // Valid only for object type.
  bool Has(const std::string &key) const {
    if (!IsObject()) return false;
    Object::const_iterator it = object_value_.find(key);
    return (it != object_value_.end()) ? true : false;
  }

  // List keys
  std::vector<std::string> Keys() const {
    std::vector<std::string> keys;
    if (!IsObject()) return keys;  // empty

    for (Object::const_iterator it = object_value_.begin();
         it != object_value_.end(); ++it) {
      keys.push_back(it->first);
    }

    return keys;
  }

  size_t Size() const { return (IsArray() ? ArrayLen() : Keys().size()); }

  bool operator==(const tinygltf::Value &other) const;

 protected:
  int type_;

  int int_value_;
  double number_value_;
  std::string string_value_;
  std::vector<unsigned char> binary_value_;
  Array array_value_;
  Object object_value_;
  bool boolean_value_;
};

Value类提供了几个构造函数,另外就是类型的判断,以及一个模板函数返回值,大家在使用的时候特别要注意对于类似"ok":[1,2,3]这样键值的json,使用的是形如下面这种方式来构造。

				std::vector<tinygltf::Value> exEnble{ tinygltf::Value(2884) ,tinygltf::Value(2929)};
				exEnbles["enable"] = tinygltf::Value(exEnble);

好了,回到上面的问题。解析出来的并不是预期的。这是什么原因呢。在源码中可以做相应的修改,我在这里修改了序列化函数,具体修改成下面的方式。

static bool ValueToJson(const Value &value, json *ret) {
  json obj;
   value.Type();
   std::string t;
  switch (value.Type()) {
    case NUMBER_TYPE:
      obj = json(value.Get<double>());
      break;
    case INT_TYPE:
      obj = json(value.Get<int>());
      break;
    case BOOL_TYPE:
      obj = json(value.Get<bool>());
      break;
    case STRING_TYPE:
      obj = json(value.Get<std::string>());
	  t= obj.dump();
      return true;
    case ARRAY_TYPE: {
      for (unsigned int i = 0; i < value.ArrayLen(); ++i) {
        Value elementValue = value.Get(int(i));
		elementValue.getString();
        json elementJson;
        if (ValueToJson(value.Get(int(i)), &elementJson))
			
		 switch (elementValue.Type())
		 {
		  case NUMBER_TYPE:
			  obj.push_back(elementValue.getINT());
			 break;
		  case INT_TYPE:
			  obj.push_back(elementValue.getINT());
			  break;
		  case STRING_TYPE:
			  obj.push_back(elementValue.getString());
			  break;
		   default:
			   obj.push_back(elementJson);
			break;
		 }
      }
      break;
    }
    case BINARY_TYPE:
      // TODO
      // obj = json(value.Get<std::vector<unsigned char>>());
      return false;
      break;
    case OBJECT_TYPE: {
      Value::Object objMap = value.Get<Value::Object>();
      for (auto &it : objMap) {
        json elementJson;
		
		if (it.first=="semantic")
		{
			int ex = 0;

		}
		if (ValueToJson(it.second, &elementJson)) { 
			
			switch (it.second.Type())
			{
			case NUMBER_TYPE:
				obj[it.first] = it.second.getNumber();
				break;
			case INT_TYPE:
				obj[it.first] = it.second.getINT();
				break;
			case STRING_TYPE:
				obj[it.first] = it.second.getString();
				break;
			default:
				obj[it.first] = elementJson;
				break;
			}
		};
      }
      break;
    }
    case NULL_TYPE:
    default:
      return false;
  }
  if (ret) *ret = obj;
  return true;
}

最后在visual studio中查看了json解析数据,应该是正确的,目前还没有完整的拼接为gltf数据。

Cesium开发&osgb倾斜数据发布工具开发数据解析遇到的问题