-1

Hi i tried a forge viewer with some point of interest to put iot on it. me program is in react.

enter image description here

here's my code poiExtension.js here we have all the poi's called by a json (x,y,z):

    let Autodesk = window.Autodesk;
let THREE = window.THREE;

// Extension Three.js pour afficher des points d'intérêts sous la forme de billboards de taille fixe faisant face à la caméra
// NB: Ne fonctionne bien qu'en mode perspective
class POIExtension extends Autodesk.Viewing.Extension {
    constructor(viewer, options) {
        super();
        this.viewer = viewer;
        var texture = THREE.ImageUtils.loadTexture("img/icone_pointeur.png");
        this.selectedMaterial = new THREE.MeshBasicMaterial( { map: texture, transparent: true, alphaTest: 0.5, color: 0xFF0000 } );
        this.defaultMaterial = new THREE.MeshBasicMaterial( { map: texture, transparent: true, alphaTest: 0.5, color: 0x00FF00 } );
        this.loaded_poi = [];
        this.planeGeometry = new THREE.PlaneGeometry(0.6, 1, 1, 1);
        this.spriteScaleFactor = 0.8;
        this.spriteAltitude = 15.0;
    }

    load () {
        let self = this;
        this.viewer.addEventListener(Autodesk.Viewing.CAMERA_CHANGE_EVENT,
            (event) => {
                this.animate(self);
            }
        );
        return true
    }

    unload () {
        return true
    }

    setSettings(settings) {
        const scale = 1.0 / 255.0;
        this.selectedMaterial.color.setRGB(
            settings.selectedPointColor[0] * scale,
            settings.selectedPointColor[1] * scale,
            settings.selectedPointColor[2] * scale);

        this.defaultMaterial.color.setRGB(
                settings.defaultPointColor[0] * scale,
                settings.defaultPointColor[1] * scale,
                settings.defaultPointColor[2] * scale);

        this.spriteScaleFactor = settings.spriteScaleFactor;
        this.spriteAltitude = settings.spriteAltitude;
    }

    clearAllPOI () {
        this.loaded_poi.map((poiParticle) => {
            this.viewer.impl.scene.remove( poiParticle.mesh );
        });
        this.loaded_poi = [];

    }

    createPOI (poi, isSelected) {
        let poiParticle = {
            poi: poi,
            mesh: new THREE.Mesh(this.planeGeometry, isSelected === true ? this.selectedMaterial : this.defaultMaterial)
        }
        this.loaded_poi.push(poiParticle);
        poiParticle.original_position = {
            x: poi.x,
            y: poi.y,
            z: poi.z
        }
        poiParticle.mesh.position.set(poi.x, poi.y, this.spriteAltitude);
        this.viewer.impl.scene.add(poiParticle.mesh);
        this.viewer.impl.sceneUpdated(true);
        this.animate();
    }

    animate() {
        // THIS IS A HUGE HACK REQUIRED BECAUSE SOME STATE IN FORGE I'SNT SET CORRECTLY IN SOME BROWSER
        if (this.hacked === undefined) {
            this.viewer.toolbar._controls[1];
            let menu_1 = this.viewer.toolbar._controls[2];
            if ((menu_1 !== undefined) && (menu_1._controls!== undefined)) {
                let menu_2 = menu_1._controls[0];
                if ((menu_2 !== undefined) && (menu_2.subMenu !== undefined) && (menu_2.subMenu._controls !== undefined)) {
                    menu_2.subMenu._controls[2].onClick();
                    this.hacked = true;
                }
            }
        }
        // END HACK

        this.loaded_poi.map((poiParticle) => {
            var vec = new THREE.Vector3(); 
            var defaultDepth = 10;

            poiParticle.mesh.scale.x = poiParticle.mesh.scale.y = poiParticle.mesh.scale.z = this.spriteScaleFactor * vec.setFromMatrixPosition( poiParticle.mesh.matrixWorld ).sub( this.viewer.impl.camera.position ).length() / defaultDepth;
            poiParticle.mesh.position.set(poiParticle.original_position.x, poiParticle.original_position.y, poiParticle.original_position.z );

            poiParticle.mesh.quaternion.copy( this.viewer.impl.camera.quaternion );
            this.viewer.impl.scene.updateMatrixWorld(true);
        });
    }
}

export default POIExtension;

And here's is my poiList.js (the clickable list on the right):

    import React, { Component } from 'react';
import './poiList.css';

// Composant react affichant la liste des points d'intérêts
// C'est ce composant qui communique avec l'extension POI
class PoiList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            poi: [],
            selectedPoi: undefined,
            settings: {
                defaultPointColor: [61, 183, 255],
                selectedPointColor: [37, 27, 255],
                defaultPointTransparancy: 0.4,
                spriteScaleFactor: 0.8,
                //altitude par défaut
                spriteAltitude: 15.0
            }
        }; 
    }

    componentDidMount() {                
        fetch('/settings')
            .then(response => {
                if (!response.ok) {
                    console.log(`status ${response.status}`);
                    throw new Error(`status ${response.status}`);
                }
                return response.json();
            })
            .then(json => {
                this.setState({
                    settings: json
                });               

            })
            .catch(e => {
                console.log(`Settings call failed: ${e}`);
                this.setState({
                    message: `Settings call failed: ${e}`
                });
            })
        fetch('/poi')
            .then(response => {
                if (!response.ok) {
                    console.log(`status ${response.status}`);
                    throw new Error(`status ${response.status}`);
                }
                return response.json();
            })
            .then(json => {
                this.setState({
                    poi: json.poi
                });               

            })
            .catch(e => {
                console.log(`POI call failed: ${e}`);
                this.setState({
                    message: `POI call failed: ${e}`
                });
            });
    }

    render() {
        if(this.props.poiExtension !== undefined) {
            this.props.poiExtension.clearAllPOI();
            this.props.poiExtension.setSettings(this.state.settings);
        }
        let self = this;
        let poiList = [];
        let index = 0;
        this.state.poi.map((poi) => {
            if(this.props.poiExtension !== undefined) {
                this.props.poiExtension.createPOI(poi, this.state.selectedPoi === poi);
            }
            let colorState = index % 2 === 1 ? "lightgrey" : "";
            colorState = this.state.selectedPoi === poi ? "selected" : colorState;
            let classC = "poiEntry " + colorState;
            let poiItem = (
                <div className={classC} key={index} onClick={() => {
                    self.setState({
                        selectedPoi: poi,
                    });
                }}>
                    {poi.type} ({poi.x}, {poi.y}, {poi.z})
                </div>
            );
            index++;

            poiList.push(poiItem);
        })

        return(
            <div className="fullscreen">
                <div className="poiTitle">BATIMENT E17</div>
                <div className="poiList">
                    { poiList }
                </div>
            </div>
        );
    }
}

export default PoiList;

i don't know how to do it....then if someone can help me i'll be very happy :)

Saif Ejjilali
  • 107
  • 2
  • 3
  • 12

1 Answers1

0

Looks like your issue does not really has to do with Forge or Viewer.js but...

If by "can't click on POIs" you meant when you clicked on a POI's DIV nothing happens (no highlight visible) then Redux serialize your states so the way you test whether the current selectedPOI is selected won't work - use a serializable key (ID string etc) to identify your POIs:

colorState = this.state.selectedPoi.id === poi.id ? "selected" : colorState;
Bryan Huang
  • 5,247
  • 2
  • 15
  • 20