xeokit / xeokit-sdk

Open source JavaScript SDK for viewing high-detail, full-precision 3D BIM and AEC models in the Web browser.
https://xeokit.io
Other
728 stars 287 forks source link

What is the best way to encode coordinates in GLTF? #106

Closed Amoki closed 4 years ago

Amoki commented 5 years ago

BCF requires WorldCoordinates in meters for camera positions.

Meaning coordinates in Europe look like [3458214.879635, 5125369.158789, 12.125874]. Xeokit uses Float32 to handle coordinates and they are very imprecise with big numbers (up to ~40cm with coordinates around 5.000.000). image

Which could be the best method to handle this: 1) Use Float64? I have no idea about the performances 2) Encode geometries with their world coordinates and quantization do some magic? 3) Encode geometries with local coordinates (small values easily handled by Float32) and set the offset in the root matrix. It does not behave well with Xeokit (the screenshot comes from this). We use a hack where we reset the root matrix to 0 before the load and apply the offet after the BCF export. 4) Encode geometries with local coordinates and define the offset in metadata. It's non standard. 5) Some other stuff

Amoki commented 5 years ago

I did some experimentation. Currently, we're doing stuff like:

const scene = gltf.scenes[0];
if (!scene) {
  return;
}
const nodeId = scene.nodes[0];
const node = gltf.nodes[nodeId];
const originOffset = [node.matrix[12], node.matrix[13], node.matrix[14]]
node.matrix[12] = 0;
node.matrix[13] = 0;
node.matrix[14] = 0;
gltfLoader.load({
  gltf: this.gltf,
  edges: true,
});

During getViewpoint() and setViewpoint(), I apply the offset. But it don't work with Xeokit format, it don't work if multiple models are loaded and they don't share the same origin.

I also tried


const originOffset = [node.matrix[12], node.matrix[13], node.matrix[14]]
gltfLoader.load({
  gltf: this.gltf,
  edges: true,
  position: [-node.matrix[12], -node.matrix[13], -node.matrix[14]]
});

The model is not bugged but the BCF viewpoint is still in Local Coordinates and not in World Coordinates. I don't know if I can set the position during GLTF-> Xeokit conversion. Multi models handling seems doable with this solution.

On the other hand, we don't need geometries to be in World Coordinates. Just the Camera needs it.

The needed features would be:

xeolabs commented 5 years ago

This issue is related: https://github.com/xeokit/xeokit-sdk/issues/116

I need to prioritise client work at the moment, but I will be circling back to get in a solution to this issue soon.

xeolabs commented 5 years ago

This might help - I'm thinking of:

  1. Adding a global realWorldScale property on the xeokit Scene, which is the number of real-world units (ie meters) per unit within the 3D world-space coordinate system.
  2. Adding a global realWorldOffset 3D vector property on the xeokit Scene, which is the distance of the xeokit world-space origin from the real-world origin, in real-world units (ie meters).
  3. Adding realToWorld(coord3d) and worldToReal(coord3d) utility methods to Scene to help map back and forth between real-world units and xeokit world-space coordinates.

Then the BCFViewpointsPlugin setViewpoint and getViewpoint methods could use those methods somehow to map to and from real-world coordinates.

Does that sound like a useful approach?

Amoki commented 5 years ago

The realWorldScale doesn't seem that useful in the BCF use case. realWorldOffset and related methods are good! Unfortunately, this is a custom method and nothing append in the GLTF but if there is no other way, it is the right way!

xeolabs commented 5 years ago

Just a heads-up that I've almost finished ability to position/scale/rotate XKT models as we load them. Just one small BIMServer-related bug to fix. Will be in master next week. Screenshot from 2019-08-30 12-47-26