坐标系转换
- OpenGL 坐标系
右手坐标系,X 轴水平向右,Y 轴竖直向上,Z 轴指向屏幕外面。
Y(绿色,朝上)
^
|
|
|
*----> X(红色,向右)
/
/
Z(蓝色,向前)
(指向屏幕外)
- 3D Tiles 坐标系
右手坐标系, Z 轴朝上
Z(蓝色,朝上)
^
|
| / Y(绿色,朝屏幕内)
|/
*----> X(红色,朝右)

- 3D Tiles 和 OpenGL 坐标系上方向存在差异,实际绘制是在 OpenGL 坐标系下进行,需要调整。
CesiumGeospatial::LocalHorizontalCoordinateSystem CesiumGeoreference::createCoordinateSystem() {
double scaleToMeters = 1.0 / scale;
if (originPlacement == CesiumGeoreferenceOriginPlacement::TrueOrigin) {
glm::dmat4 localToEcef(
glm::dvec4(scaleToMeters, 0.0, 0.0, 0.0),
glm::dvec4(0.0, 0.0, scaleToMeters, 0.0),
glm::dvec4(0.0, -scaleToMeters, 0.0, 0.0),
glm::dvec4(0.0, 0.0, 0.0, 1.0)
);
return CesiumGeospatial::LocalHorizontalCoordinateSystem(localToEcef);
}
if (originAuthority == CesiumGeoreferenceOriginAuthority::EarthCenteredEarthFixed) {
return CesiumGeospatial::LocalHorizontalCoordinateSystem(glm::dvec3(ecefX, ecefY, ecefZ),
CesiumGeospatial::LocalDirection::East,
CesiumGeospatial::LocalDirection::Up,
CesiumGeospatial::LocalDirection::South,
scaleToMeters,
ellipsoid->getNativeEllipsoid());
}
return CesiumGeospatial::LocalHorizontalCoordinateSystem(glm::dvec3(longitude, latitude, height),
CesiumGeospatial::LocalDirection::East,
CesiumGeospatial::LocalDirection::Up,
CesiumGeospatial::LocalDirection::South,
scaleToMeters,
ellipsoid->getNativeEllipsoid());
}
void *PrepareRendererResources::prepareInMainThread(Cesium3DTilesSelection::Tile &tile, void *pLoadThreadResult_) {
const Cesium3DTilesSelection::TileContent &content = tile.getContent();
const Cesium3DTilesSelection::TileRenderContent *pRenderContent = content.getRenderContent();
if (!pRenderContent) {
return nullptr;
}
std::unique_ptr<LoadThreadResult> pLoadThreadResult(static_cast<LoadThreadResult *>(pLoadThreadResult_));
std::vector<std::shared_ptr<Mesh>> meshes = pLoadThreadResult->meshes;
const std::vector<CesiumPrimitiveInfo> &primitiveInfos = pLoadThreadResult->primitiveInfos;
const CesiumGltf::Model &model = pRenderContent->getModel();
glm::dmat4 tileTransform = tile.getTransform();
tileTransform = CesiumGltfContent::GltfUtilities::applyRtcCenter(model, tileTransform);
tileTransform = CesiumGltfContent::GltfUtilities::applyGltfUpAxisTransform(model, tileTransform);
tileTransform = tileTransform * CesiumGeometry::Transforms::Y_UP_TO_Z_UP;
int32_t meshSize = meshes.size();
if (!meshSize) {
return nullptr;
}
std::string name = "glTF";
auto urlIt = model.extras.find("Cesium3DTiles_TileUrl");
if (urlIt != model.extras.end()) {
name = urlIt->second.getStringOrDefault("glTF");
}
size_t meshIndex = 0;
GameComponent* tilesetComponentPtr = pTileset;
CesiumGeoreference* georeferencePtr = pTileset->getGeoreference();
model.forEachPrimitiveInScene(
-1,
[tilesetComponentPtr, georeferencePtr, &meshes, &primitiveInfos, &meshIndex, &tile, &tileTransform](const CesiumGltf::Model &gltf,
const CesiumGltf::Node &node,
const CesiumGltf::Mesh &mesh,
const CesiumGltf::MeshPrimitive &primitive,
const glm::dmat4 &transform) {
auto positionAccessorIt = primitive.attributes.find("POSITION");
if (positionAccessorIt == primitive.attributes.end()) {
return;
}
int32_t positionAccessorID = positionAccessorIt->second;
CesiumGltf::AccessorView<glm::vec3> positionView(gltf, positionAccessorID);
if (positionView.status() != CesiumGltf::AccessorViewStatus::Valid) {
return;
}
const CesiumPrimitiveInfo &primitiveInfo = primitiveInfos[meshIndex];
glm::dmat4 modelToEcef = tileTransform * transform;
auto meshInstancePtr = meshes[meshIndex];
meshInstancePtr->setParent(tilesetComponentPtr);
CesiumGlobeAnchor* anchor= new CesiumGlobeAnchor(georeferencePtr);
meshInstancePtr->addGlobeAnchor(anchor);
anchor->setDetectTransformChanges(false);
anchor->setAdjustOrientationForGlobeWhenMoving(false);
anchor->updateLocalToGlobeFixedMatrixAndEcef(modelToEcef);
anchor->setParent(meshInstancePtr.get());
const CesiumGltf::Material *pMaterial = CesiumGltf::Model::getSafe(&gltf.materials, primitive.material);
if (pMaterial) {
setGltfMaterialParameterValues(gltf, primitiveInfo, pMaterial, meshes[meshIndex++]);
}
});
return new CesiumGltfObject{std::move(meshes), std::move(pLoadThreadResult->primitiveInfos)};
}
void PrepareRendererResources::attachRasterInMainThread(const Cesium3DTilesSelection::Tile &tile,
int32_t overlayTextureCoordinateID,
const CesiumRasterOverlays::RasterOverlayTile &rasterTile,
void *pMainThreadRendererResources,
const glm::dvec2 &translation,
const glm::dvec2 &scale) {
const Cesium3DTilesSelection::TileContent &content = tile.getContent();
const Cesium3DTilesSelection::TileRenderContent *pRenderContent = content.getRenderContent();
if (!pRenderContent) {
return;
}
CesiumGltfObject *pCesiumGltfObj = static_cast<CesiumGltfObject *>(pRenderContent->getRenderResources());
Texture *pTexture = static_cast<Texture *>(pMainThreadRendererResources);
if (!pCesiumGltfObj || pCesiumGltfObj->meshes.empty() || !pTexture) {
return;
}
std::string key = rasterTile.getOverlay().getName();
size_t primitiveIndex = 0;
std::vector<std::shared_ptr<Mesh>> meshes = pCesiumGltfObj->meshes;
std::vector<CesiumPrimitiveInfo> primitiveInfos = pCesiumGltfObj->primitiveInfos;
for (size_t i = 0, len = meshes.size(); i < len; ++i) {
const CesiumPrimitiveInfo &primitiveInfo = primitiveInfos[primitiveIndex++];
auto texCoordIndexIt = primitiveInfo.rasterOverlayUvIndexMap.find(overlayTextureCoordinateID);
if (texCoordIndexIt == primitiveInfo.rasterOverlayUvIndexMap.end()) {
continue;
}
pTexture->offset = translation;
pTexture->scale = scale;
pTexture->flipY = true;
std::vector<Texture> textures{*pTexture};
meshes[i]->setTextures(textures);
}
};

