当前位置: 首页 > news >正文

【大坐标处理】

大坐标处理

  • Cesium
  • UE
  • 总结

Cesium

首先想到的就是查看Cesium的代码看看他是怎么解决的对吧
这里有个最简代码片段,我们顺着往里找

* void main()
 * {
 *   vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);
 *   gl_Position = czm_modelViewProjectionRelativeToEye * p;
 * }
vec4 czm_translateRelativeToEye(vec3 high, vec3 low)
{
    vec3 highDifference = high - czm_encodedCameraPositionMCHigh;
    // This check handles the case when NaN values have gotten into `highDifference`.
    // Such a thing could happen on devices running iOS.
    if (length(highDifference) == 0.0) {  
        highDifference = vec3(0);  
    }
    vec3 lowDifference = low - czm_encodedCameraPositionMCLow;

    return vec4(highDifference + lowDifference, 1.0);
}

这里可以看见他把camera的坐标也传进来了,然后high low分别和camera的high low减一下再合并到一起,就得到了相对相机的坐标系

也就是说,他不仅把坐标拆成了high low,还减去了相机坐标,也就是减去相机之后的坐标还拆,这确实是能支持很大的数据了

czm_modelViewProjectionRelativeToEye 这个值的创建就是普通的modelViewMatirx只是把translate清空了,如下代码

czm_modelViewRelativeToEye: new AutomaticUniform({
    size: 1,
    datatype: WebGLConstants.FLOAT_MAT4,
    getValue: function (uniformState) {
      return uniformState.modelViewRelativeToEye;
    },
}),

modelViewRelativeToEye: {
    get: function () {
      cleanModelViewRelativeToEye(this);
      return this._modelViewRelativeToEye;
    },
  }
function cleanModelViewRelativeToEye(uniformState) {
  if (uniformState._modelViewRelativeToEyeDirty) {
    uniformState._modelViewRelativeToEyeDirty = false;

    const mv = uniformState.modelView;
    const mvRte = uniformState._modelViewRelativeToEye;
    mvRte[0] = mv[0];
    mvRte[1] = mv[1];
    mvRte[2] = mv[2];
    mvRte[3] = mv[3];
    mvRte[4] = mv[4];
    mvRte[5] = mv[5];
    mvRte[6] = mv[6];
    mvRte[7] = mv[7];
    mvRte[8] = mv[8];
    mvRte[9] = mv[9];
    mvRte[10] = mv[10];
    mvRte[11] = mv[11];
    mvRte[12] = 0.0;
    mvRte[13] = 0.0;
    mvRte[14] = 0.0;
    mvRte[15] = mv[15];
  }
}

modelViewProjectionRelativeToEye只是一并在CPU做完几个乘法

modelViewProjectionRelativeToEye: {
    get: function () {
      cleanModelViewProjectionRelativeToEye(this);
      return this._modelViewProjectionRelativeToEye;
    },
},
function cleanModelViewProjectionRelativeToEye(uniformState) {
  if (uniformState._modelViewProjectionRelativeToEyeDirty) {
    uniformState._modelViewProjectionRelativeToEyeDirty = false;

    Matrix4.multiply(
      uniformState._projection,
      uniformState.modelViewRelativeToEye,
      uniformState._modelViewProjectionRelativeToEye,
    );
  }
}

这个是high low的解释
https://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm
这是Cesium里的实现

EncodedCartesian3.encode = function (value, result) {
  //>>includeStart('debug', pragmas.debug);
  Check.typeOf.number("value", value);
  //>>includeEnd('debug');

  if (!defined(result)) {
    result = {
      high: 0.0,
      low: 0.0,
    };
  }

  let doubleHigh;
  if (value >= 0.0) {
    doubleHigh = Math.floor(value / 65536.0) * 65536.0;
    result.high = doubleHigh;
    result.low = value - doubleHigh;
  } else {
    doubleHigh = Math.floor(-value / 65536.0) * 65536.0;
    result.high = -doubleHigh;
    result.low = value + doubleHigh;
  }

  return result;
};

这是CPP代码

void CDoubleToTwoFloats::Convert(double doubleValue,
    float& floatHigh, float& floatLow)
{
    if (doubleValue >= 0.0)
    {
        double doubleHigh = floor(doubleValue / 65536.0) * 65536.0;
        floatHigh = (float)doubleHigh;
        floatLow = (float)(doubleValue - doubleHigh);
    }
    else
    {
        double doubleHigh = floor(-doubleValue / 65536.0) * 65536.0;
        floatHigh = (float)-doubleHigh;
        floatLow = (float)(doubleValue + doubleHigh);
    }
}

UE

https://dev.epicgames.com/documentation/en-us/unreal-engine/large-world-coordinates-rendering-in-unreal-engine-5
这里是UE的文档
之前就听说UE有这个支持,好奇他怎么搞的
这里是文档里最后一段话,看起来也是类似Cesium的解法
不过他还有一个空间,是纠正了旋转不只是减去offset,建议能做就做,那估计就是没做:)

FDFScalar(double Input)
{
	float High = (float)Input;
	float  Low = (float)(Input - High);
}

总结

这种做法每个坐标都需要存储两倍大小的坐标信息high low两个vector3,但是似乎如果要支持double的话,没有其他好法子

相关文章:

  • MyBatis plus详解
  • 使用BootStrap 3的原创的模态框组件,没法弹出!估计是原创的bug
  • day-110 下降路径最小和 II
  • filebeat和logstash区别
  • reCAPTCHA 打码平台
  • CCBCISCN复盘
  • Ubuntu检查并启用 Nginx 的stream模块或重新安装支持stream模块的Nginx
  • MacOS下的IntelliJ IDEA突然无法访问本机的虚拟机
  • Ubuntu上查看GPU使用情况并释放内存
  • 【C++】C++类
  • Java集合操作三剑客:Collection、collect与Collectors的协奏曲
  • 【高德】-下载路径规划数据-无代码
  • conda create之后,以前的conda env list 只能看到环境路径 没有环境名称了
  • slq-labs日志
  • C++和标准库速成(十)——类型别名、类型定义、类型推断和标准库简介
  • HarmonyOS Next~鸿蒙系统功耗优化体系解析:前台交互与后台任务的全场景节能设计
  • AI Agent系列(七) -思维链(Chain of Thought,CoT)
  • 北斗导航 | 北斗三号区域短报文相关知识总结
  • 01. Linux嵌入式系统学习笔记(一)
  • 生物化学笔记:医学免疫学原理 免疫系统的组成与功能+克隆选择学说
  • 洞天寻隐·学林纪丨玉洞桃源:仇英青绿山水画中的洞天与身体
  • 售卖自制外挂交易额超百万元,一男子因提供入侵计算机系统程序被抓
  • 两国战机均未侵入对方领空,巴方公布对印回击细节
  • 吴清:加强监管的同时传递监管温度,尽力帮助受影响企业应对美加征关税的冲击
  • 上海市委常委会扩大会议传达学习习近平总书记考察上海重要讲话和在部分省区市“十五五”时期经济社会发展座谈会上的重要讲话精神
  • 人民日报今日谈:坚决克服麻痹思想,狠抓工作落实