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
736 stars 291 forks source link

[QUESTION] Is it possible to rotate an entity in an XKT model within the Viewer? #1193

Open AXONE-IO opened 1 year ago

AXONE-IO commented 1 year ago

I want to animate some Entity in my xkt model. Is there a way of assigning a rotation to a single entity in a model ?

xeolabs commented 1 year ago

Hi,

For XKT, we are limited to being able to translate and rotate the entire model, or just translate the individual objects along the coordinate axis (useful for exploding parts views). Explanation below:

We have two ways to represent model in xeokit:

  1. the SceneModel class, which is a container of geometries, meshes, materials and entities, that only allows you to rotate and translate the whole SceneModel, and to translate the individual entities along the coordinate axis
  2. the "scene graph", which is a structure of Node, Mesh, Material and Geometry classes, where Meshes are the entities, which allows us to rotate, translate and scale each entity independently.

We use (1) for big models. Transformation is limited in (1) in order to optimize it for minimal memory usage, and make it render as fast as possible.

We use (2) for 3D helper objects, like NavCube, section plane controls etc, which only use a small number of these components, and for which it's efficient to then support full transformations.

(1) is much more efficient than (2), which should only be used for simple 3D objects/models.

Here are our collection of usage examples for (2):

https://xeokit.github.io/xeokit-sdk/examples/scenegraph/

And a live demo of (2):

https://xeokit.github.io/xeokit-sdk/examples/scenegraph/#sceneGraph

Screencast from 26.10.2023 12:00:21.webm

Source code for that live demo - note that Node classes are branch nodes in the scene graph, with Mesh classes at the leaves. Meshes can share materials and geometries between them.

    import {Viewer, Mesh, Node, PhongMaterial, buildBoxGeometry, ReadableGeometry} from "../../dist/xeokit-sdk.min.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];

    //------------------------------------------------------------------------------------------------------------------
    // Build a simple scene graph representing a table with four legs
    //------------------------------------------------------------------------------------------------------------------

    const boxGeometry = new ReadableGeometry(viewer.scene, buildBoxGeometry({
        xSize: 1,
        ySize: 1,
        zSize: 1
    }));

    new Node(viewer.scene, {
        id: "table",
        isModel: true, // <--------------------- Node represents a model
        rotation: [0, 50, 0],
        position: [0, 0, 0],
        scale: [1, 1, 1],

        children: [

            new Mesh(viewer.scene, { // Red table leg
                id: "redLeg",
                isObject: true, // <---------- Node represents an object
                position: [-4, -6, -4],
                scale: [1, 3, 1],
                rotation: [0, 0, 0],
                geometry: boxGeometry,
                material: new PhongMaterial(viewer.scene, {
                    diffuse: [1, 0.3, 0.3]
                })
            }),

            new Mesh(viewer.scene, { // Green table leg
                id: "greenLeg",
                isObject: true, // <---------- Node represents an object
                position: [4, -6, -4],
                scale: [1, 3, 1],
                rotation: [0, 0, 0],
                geometry: boxGeometry,
                material: new PhongMaterial(viewer.scene, {
                    diffuse: [0.3, 1.0, 0.3]
                })
            }),

            new Mesh(viewer.scene, {// Blue table leg
                id: "blueLeg",
                isObject: true, // <---------- Node represents an object
                position: [4, -6, 4],
                scale: [1, 3, 1],
                rotation: [0, 0, 0],
                geometry: boxGeometry,
                material: new PhongMaterial(viewer.scene, {
                    diffuse: [0.3, 0.3, 1.0]
                })
            }),

            new Mesh(viewer.scene, {  // Yellow table leg
                id: "yellowLeg",
                isObject: true, // <---------- Node represents an object
                position: [-4, -6, 4],
                scale: [1, 3, 1],
                rotation: [0, 0, 0],
                geometry: boxGeometry,
                material: new PhongMaterial(viewer.scene, {
                    diffuse: [1.0, 1.0, 0.0]
                })
            }),

            new Mesh(viewer.scene, { // Purple table top
                id: "tableTop",
                isObject: true, // <---------- Node represents an object
                position: [0, -3, 0],
                scale: [6, 0.5, 6],
                rotation: [0, 0, 0],
                geometry: boxGeometry,
                material: new PhongMaterial(viewer.scene, {
                    diffuse: [1.0, 0.3, 1.0]
                })
            })
        ]
    });

    //------------------------------------------------------------------------------------------------------------------
    // Find scene graph nodes by their model and object IDs
    //------------------------------------------------------------------------------------------------------------------

    // Get the whole table model
    var table = viewer.scene.models["table"];

    table.edges = true;

    // Get some leg objects
    var redLeg = viewer.scene.objects["redLeg"];
    var greenLeg = viewer.scene.objects["greenLeg"];
    var blueLeg = viewer.scene.objects["blueLeg"];

    //------------------------------------------------------------------------------------------------------------------
    // Periodically update transforms on our scene nodes
    //------------------------------------------------------------------------------------------------------------------

    viewer.scene.on("tick", function () {

        // Rotate legs
        redLeg.rotateY(0.5);
        greenLeg.rotateY(0.5);
        blueLeg.rotateY(0.5);

        // Rotate table
        table.rotateY(0.5);
        table.rotateX(0.3);
    });
AXONE-IO commented 1 year ago

To put this in context, we're using the viewer to visualize industrial 3d models. Being able to apply rotations would make it possible to animate, bring to life the model and even reproduce the state of the machines like a digital twin.

Thank you for your explanations.

felipedc09 commented 1 month ago

Hi everyone,

I am planning to work on a feature that allows the rotation of individual elements within XKT and IFC models, with the goal of modifying the element coordinates in the original files. I would appreciate any insights or guidance from the community on this endeavor.

Objectives:

Rotate Individual Elements: Implement functionality to rotate specific elements in XKT and IFC models. Update Original Files: Ensure that the new coordinates are accurately reflected in the original XKT and IFC files.

Considerations:

Model Structure: Understanding the internal structure of XKT and IFC files to correctly identify and manipulate elements. Transformation Matrices: Applying appropriate rotation matrices and ensuring transformations are consistent with the models’ coordinate systems. SDK Capabilities: Leveraging the xeokit SDK for manipulating model elements and exploring any existing plugins or extensions that could facilitate this process. File Modifications: Using libraries like IfcOpenShell for IFC files to read, modify, and write back updated coordinates, and understanding the serialization process for XKT files.

I am looking forward to any advice, suggestions, or collaboration opportunities from the community. Thank you!