Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Support federated models #991

Closed
xeolabs opened this issue Jan 19, 2023 · 0 comments
Closed

Feature: Support federated models #991

xeolabs opened this issue Jan 19, 2023 · 0 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@xeolabs
Copy link
Member

xeolabs commented Jan 19, 2023

Add new behaviours to MetaScene and TreeViewPlugin:

  • each instance of a MetaObject in a MetaScene will be be shared by multiple MetaModels
  • as we load a MetaModel,, whenever a MetaObject with the element's ID already exists in the MetaScene, the existing MetaObject is "reused" and we increment a use-count on that MetaObject.
  • when we destroy a MetaModel, we decrement the use count on each of the MetaObjects it uses, deleting the MetaObject when that count is zero

Expected use case is when we load a BIM building model that is composed of several IFC files, one for each storey.

Each of the IFC files will therefore contain certain elements that are the same, with the same IDs, such as the IfcSite and IfcBuilding.

If we've converted the IFC files to a set of XKT files, then after these changes, we can load all those XKT files in a set, and end up with a single, unified graph of MetaObjects for the IFC element hierarchy.

Next, extend the TreeViewPlugin with the option to build a single tree from the MetaObjects on MetaScene. Then we'll have the unified tree view of all the objects in the model, without them being split into a tree for each model, which defeats federated model viewing.

I'm thinking we'll add that as a new "federated" boolean mode property for TreeViewPlugin, and keep its current unfederated mode (tree for each model) as default.

  //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {
        Viewer,
        VBOSceneModel,
        TreeViewPlugin
    } from "./../dist/xeokit-sdk.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer and arrange the camera
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true
    });

    viewer.scene.camera.eye = [-21.80, 4.01, 6.56];
    viewer.scene.camera.look = [0, -5.75, 0];
    viewer.scene.camera.up = [0.37, 0.91, -0.11];

    viewer.cameraFlight.fitFOV = 35;

    viewer.scene.highlightMaterial.edgeColor = [0, 0, 0];

    //------------------------------------------------------------------------------------------------------------------
    // First geometry model, containing table legs
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel1 = new VBOSceneModel(viewer.scene, {
        id: "furniture1",
        isModel: true, // <--------------------- Represents a model, registers VBOSceneModel by ID on viewer.scene.models
        position: [0, 0, 0],
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    sceneModel1.createGeometry({
        id: "myBoxGeometry",
        primitive: "triangles",
        positions: [
            1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
            1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right
            1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top
            -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
            -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1,// v7-v4-v3-v2 bottom
            1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back
        ],
        normals: [
            0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,// v0-v1-v2-v3 front
            1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,// v0-v3-v4-v5 right
            0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,// v0-v5-v6-v1 top
            -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,// v1-v6-v7-v2 left
            0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,// v7-v4-v3-v2 bottom
            0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1// v4-v7-v6-v5 back
        ],
        indices: [
            0, 1, 2, 0, 2, 3,            // front
            4, 5, 6, 4, 6, 7,            // right
            8, 9, 10, 8, 10, 11,         // top
            12, 13, 14, 12, 14, 15,      // left
            16, 17, 18, 16, 18, 19,      // bottom
            20, 21, 22, 20, 22, 23
        ]
    });

    sceneModel1.createMesh({
        id: "redLegMesh",
        geometryId: "myBoxGeometry",
        position: [-4, -6, -4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [1, 0.3, 0.3]
    });

    sceneModel1.createEntity({
        id: "redLeg",
        meshIds: ["redLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.createMesh({
        id: "greenLegMesh",
        geometryId: "myBoxGeometry",
        position: [4, -6, -4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [0.3, 1.0, 0.3]
    });

    sceneModel1.createEntity({
        id: "greenLeg",
        meshIds: ["greenLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.createMesh({
        id: "blueLegMesh",
        geometryId: "myBoxGeometry",
        position: [4, -6, 4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [0.3, 0.3, 1.0]
    });

    sceneModel1.createEntity({
        id: "blueLeg",
        meshIds: ["blueLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.createMesh({
        id: "yellowLegMesh",
        geometryId: "myBoxGeometry",
        position: [-4, -6, 4],
        scale: [1, 3, 1],
        rotation: [0, 0, 0],
        color: [1.0, 1.0, 0.0]
    });

    sceneModel1.createEntity({ // Create object
        id: "yellowLeg",
        meshIds: ["yellowLegMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel1.finalize();

    //------------------------------------------------------------------------------------------------------------------
    // Second geometry model, containing table top
    //------------------------------------------------------------------------------------------------------------------

    const sceneModel2 = new VBOSceneModel(viewer.scene, {
        id: "furniture2",
        isModel: true, // <--------------------- Represents a model, registers VBOSceneModel by ID on viewer.scene.models
        position: [0, 0, 0],
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    sceneModel2.createGeometry({
        id: "myBoxGeometry",
        primitive: "triangles",
        positions: [
            1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, // v0-v1-v2-v3 front
            1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, // v0-v3-v4-v1 right
            1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, // v0-v1-v6-v1 top
            -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, // v1-v6-v7-v2 left
            -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1,// v7-v4-v3-v2 bottom
            1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1 // v4-v7-v6-v1 back
        ],
        normals: [
            0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,// v0-v1-v2-v3 front
            1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,// v0-v3-v4-v5 right
            0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,// v0-v5-v6-v1 top
            -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,// v1-v6-v7-v2 left
            0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,// v7-v4-v3-v2 bottom
            0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1// v4-v7-v6-v5 back
        ],
        indices: [
            0, 1, 2, 0, 2, 3,            // front
            4, 5, 6, 4, 6, 7,            // right
            8, 9, 10, 8, 10, 11,         // top
            12, 13, 14, 12, 14, 15,      // left
            16, 17, 18, 16, 18, 19,      // bottom
            20, 21, 22, 20, 22, 23
        ]
    });

    sceneModel2.createMesh({
        id: "tableTopMesh",
        geometryId: "myBoxGeometry",
        position: [0, -3, 0],
        scale: [6, 0.5, 6],
        rotation: [0, 0, 0],
        color: [1.0, 0.3, 1.0]
    });

    sceneModel2.createEntity({ // Create object
        id: "tableTop",
        meshIds: ["tableTopMesh"],
        isObject: true // <----------------- Represents an object, registers Entity by ID on viewer.scene.objects
    });

    sceneModel2.finalize();


    //------------------------------------------------------------------------------------------------------------------
    // First metadata model, containing elements for table and legs
    //------------------------------------------------------------------------------------------------------------------

    viewer.metaScene                            // This is the MetaScene for the Viewer
        .createMetaModel("furniture1", {         // Creates a MetaModel in the MetaScene
            "metaObjects": [                    // Creates MetaObjects in the MetaModel
                {
                    "id": "table",              // Does not match any Entity
                    "name": "Table",
                    "type": "furniture",        // Arbitrary type
                    "properties": {             // Arbitrary properties
                        "cost": "200"
                    }
                },
                {
                    "id": "redLeg",
                    "name": "Red table Leg",    // Same ID as red leg Entity
                    "type": "leg",
                    "parent": "table",          // References first MetaObject as parent
                    "properties": {
                        "material": "wood"
                    }
                },
                {
                    "id": "greenLeg",           // Same ID as green leg Entity
                    "name": "Green table leg",
                    "type": "leg",
                    "parent": "table",
                    "properties": {
                        "material": "wood"
                    }
                },
                {
                    "id": "blueLeg",            // Same ID as blue leg Entity
                    "name": "Blue table leg",
                    "type": "leg",
                    "parent": "table",
                    "properties": {
                        "material": "wood"
                    }
                },
                {
                    "id": "yellowLeg",         // Same ID as yellow leg Entity
                    "name": "Yellow table leg",
                    "type": "leg",
                    "parent": "table",
                    "properties": {
                        "material": "wood"
                    }
                }
            ]
        });

    //------------------------------------------------------------------------------------------------------------------
    // First metadata model, containing elements for table and top
    //------------------------------------------------------------------------------------------------------------------

    viewer.metaScene                            // This is the MetaScene for the Viewer
        .createMetaModel("furniture2", {         // Creates a MetaModel in the MetaScene
            "metaObjects": [                    // Creates MetaObjects in the MetaModel
                {
                    "id": "table",              // Does not match any Entity
                    "name": "Table",
                    "type": "furniture",        // Arbitrary type
                    "properties": {             // Arbitrary properties
                        "cost": "200"
                    }
                },
                {
                    "id": "tableTop",         // Same ID as purple table top Entity
                    "name": "Purple table top",
                    "type": "surface",
                    "parent": "table",
                    "properties": {
                        "material": "formica",
                        "width": "60",
                        "depth": "60",
                        "thickness": "5"
                    }
                }
            ]
        });
xeolabs added a commit that referenced this issue Jan 19, 2023
xeolabs added a commit that referenced this issue Mar 11, 2023
xeolabs added a commit that referenced this issue Mar 16, 2023
xeolabs added a commit that referenced this issue Mar 16, 2023
xeolabs added a commit that referenced this issue Mar 16, 2023
xeolabs added a commit that referenced this issue Mar 16, 2023
@xeolabs xeolabs added this to the 2.4.0 milestone Apr 27, 2023
@xeolabs xeolabs closed this as completed Apr 27, 2023
@xeolabs xeolabs self-assigned this Apr 27, 2023
@xeolabs xeolabs added the enhancement New feature or request label Apr 27, 2023
Kurtil added a commit to Amoki/xeokit-sdk that referenced this issue May 16, 2023
* Install the CodeSee workflow. Learn more at https://docs.codesee.io

* Support federated metamodels xeokit#991

* Fix Angle and Distance measurement failure to set second point xeokit#998

* Skip inactive section planes in BCF getViewpoint

* Support federated metamodels xeokit#991

* Support federated metamodels xeokit#991

* Support federated metamodels xeokit#991

* npm bump

* Support federated metamodels xeokit#991

* fi typo in LineBatchingLayer

* fix imports to make them ES valid

* Fix loaders.gl import

* Fix imports

* more fixes

* fix las loader import

* z-index

* Optimization: avoid unneeded DOM layout calculations due to the obtention of Client Bounding Rect.

* Optimization: avoid to create 1 anonymous function instance every time a scene render happens.

* Optimization: avoid to bind same texture to same texture unit if was already bound.

* Improved WebGL2 compatibility.

(this does not make all xeokit code compatible with WebGL2)

* Introducing `DataTexturePeformanceModel`

This is a variation of `PeformanceModel` where all the GPU data is stored in data textures.

GPU memory savings are bigger than 80% (both with instanced and non-instanced geometries) when using the `DataTexturePerformanceModel`.

It requires WebGL2 to run properly.

* GPU-Optimised support for per-Entity Offsets.

* Fix management of deferred-flags in data-textures model

* Add GPU-optimized support for per-object coloring.

Plus minor refactors to make to code more readable.

* Bugfix: take into account `transparent` flag for entities in `TrianglesDataTextureLayer`.

* Introduce a toggle-able LOD mechanism.

This will keep hiding the most complex objects in the scene to be able to keep up with a `target frame rate`.

This is an extension to the `DataTexturesPerformanceModel`.

* Introduce a toggle-able View Frustum Culling mechanism.

This will cull the objects outside of the camera frustum, by making use of an `r*tree` data structure to speed up containement queries.

This is an extension to the `DataTexturesPerformanceModel`.

* Fix shader normal calculation in `data-textures Renderers.

* Fix normal picking in `TrianglesDataTexturePickNormalsRenderer`

* Fix in `ViewFrustumCullingManager.js` when there is no geometry in the AABB tree

* Increase the precision of per-object matrices from HALF_FLOAT to FLOAT.

* Avoid to draw triangles if the object `alpha` is zero.

* Replace wrong usage of `Float16` textures with `Float32` textures

* When finalizing data-texture Models, make sure to update flags for portion in batched mode,

This saves 1/3rd of model load time.

* Update data-textures initializtion with latest changes in `master`

Fix after rebase

data-textures: fix initialization of AABB's

* data-textures: avoid the need to store entity-normal matrices

* data-textures: register number of created data-textures in DataTextureRamStats

* data-textures: Increase max geometry texture size to 4096x4096 indices and vertices

* data-textures: Increase max colors texture size to 512 objects per row

* data-textures: remove temporary log

* data-textures: Increase positions+entity matrices texture size to 512 objects per row

* data-textures: Increase offsets texture size to 512 objects per row

* data-textures: raise the limit from 4096 objects/layer to 65536

* data-texture: add support for double-sided gometry

This introduces a novel way of doing it when geometries are non-solid.

In the Vertex Shader, non-geometries' triangles will have its winding flipped in case they would be culled.

* data-textures: more efficient double-side management

This is done by transforming the camera=>polygon vector to quantized space instead of transforming the normal to de-quantized space.

* data-textures: fix shading

This is done by taking into account the portion positioning matrix (entity * positions-decode) when obtaining the view-normal

* data-textures: add support for arbitrary ray-picking

(both for `ortho` and `perspective` camera modes)

* data-textures: use WebGLv2 syntax for section plane clipping code

* data-texture: add support for `TrianglesDataTextureSilhouetteRenderer`

* data-textures: add support for `TrianglesDataTextureEdgesRenderer`

* data-textures: clean-up temporary debug code

* data-textures: use `instanceof` instead of string comparison for `drawable.constructor.name`

* data-textures: temporarily disable shaders related to SAO

* data-textures: protect access to the update of pick-view-matrix

* data-textures: split initialization of camera-matrix and pick-camera-matrix in data-tex-perf-model

* Refactorings xeokit#824

* Refactorings xeokit#824

* Improvements in the LOD mechanism

* Fix missing DistanceMeasurement "measurementEnd" event for touch xeokit#1019

* npm bump

* xeokit#1022

* npm bump

* Make Frustum class public

* Added examples

* Fix unwanted SAO depth render for DataTextureSceneModel xeokit#824

* Add examples

* npm bump

* Make `VFC` mechanism support `model.worldMatrix` != ' identity'

This fixes a problem where View Frustum Culling would not work well for models loaded with e.g. the `cfg.position` parameter different from the zero vector.

This fix is based on the fact that it is the same (during `VFC`):

- to pre-process the AABB's so they include the `model.worldMatrix` and this the culling considers final world-AABB's. Then the clipping happens in world-space.
- to instead transform the camera `eye`/`look` with the inverse transform, so the AABB's are kept the same. Then the clipping happens in model-space.

* Add `useDataTextures.disableVertexWelding` option to the `XKTLoaderPlugin`

This allows to disable welding geometry vertices when loading the data into the GPU.

* Add `useDataTextures.disableIndexRebucketing` option to the `XKTLoaderPlugin`

This allows to disable adaptive demotion of triangles indices' bitness.

* Implement Depth Renderer for data-textures

* Allow SAO in `DataTextureSceneModel`

* Mitigation for what looks like a bug in Chrome for Mac

When using data-textures, unless those `Unit8Array`'s are converted to `Unit16Array`'s, the geometry is corrupted in Chrome for Mac after using the SAO renderers for the 1st time.

* When SAO-rendering triangles in data-textures, use a GL texture unit different from 0

This prevents additional texture re-binds as texture unit 0 is used frequently to update camera matrices, and portion flags.

* SAO-rendering for data-textures triangles: make sure the renderer is WebGLv2-compatible

* Chrome-for-Mac mitigation for data-textures when SAO enabled

Improvement over a previous mitigation where models containing objects with > 2^16 triangles, when using data-textures, got corrupted in Chrome for Mac when enabling SAO.

* Fix sticky DistanceMeasurementsControl xeokit#1030

* Enable masking in datatex depth vert shader & tweaks xeokit#811

* Removed redundant ScratchMemory from DataTextureSceneModel xeokit#811

* Rename some internal classes xeokit#811

* npm bump

* npm bump

* Fix broken TreeViewPlugin checkbox synchronization xeokit#1031

* npm bump

* add properties for nav cube to be able to turn on/off the usage of project north / true north,
and set the offset angle to align the nav cube to the used north. the default is using true north, and when setting the project north offset angle - it will rotate the nav cube to align it.

* remove duplicated line in Component.js

The removed line is identical to the line `170` which is always executed.

* [data-textures]: implement a smart deferred flags update mechanism

If the number of updated per-object properties in a frame is less than a threshold, they will be updated directly.

If the number of updates is instead bigger than a threshold (by default 10), the ones above the threshold will be batched, and the batch flushed just before rendering the frame.

This completely solves xeokit#1033

* Enable SAO rendering in Safari.

* npm bump

* Fix broken TreeViewPlugin checkbox synchronization xeokit#1031

* npm bump

* Unmerge PR with syntax errors
xeokit#1017

* npm bump

* Added examples

* Fix broken TreeViewPlugin checkbox synchronization xeokit#1031

* Fix Viewer.getSnapshot custom width and height params xeokit#1040

* npm bump

* Make annotation dots and labels ignore mouse wheel events xeokit#1041

* npm bump

* Add NavCubePlugin option to align with project/true North xeokit#1042

* npm bump

* Add NavCubePlugin option to align with project/true North - fix top & bottom clicks xeokit#1042

* npm bump

* Add NavCubePlugin option to align with project/true North - customize example xeokit#1042

* Enable mouse wheel zooming while hovering over measurements xeokit#1043

* npm bump

* Fix stuck pan/rotate/dolly keypresses over annotations and measurements xeokit#965

* npm bump

* [fix]: make sure to restore `gl.pixelStatei` changes in `Texture2D` class

---------

Co-authored-by: codesee-maps[bot] <86324825+codesee-maps[bot]@users.noreply.github.com>
Co-authored-by: lindsay <lindsay.kay@xeolabs.com>
Co-authored-by: Hugo Duroux <hugo@bimdata.io>
Co-authored-by: Hugo Duroux <hugo.duroux@gmail.com>
Co-authored-by: Christophe B <christophe.bellec@kwarto.immo>
Co-authored-by: Toni Martí <toni.marti.coll@tribia.com>
Co-authored-by: Elyran Kogan <elyran.kogan@versatile.ai>
@xeolabs xeolabs changed the title Support federated metamodels Feature: Support federated metamodels Jun 1, 2023
@xeolabs xeolabs changed the title Feature: Support federated metamodels Feature: Support federated models Jun 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

1 participant