ADDING ANNOTATIONS/MARKERS/LABELS COORDINATES FROM EXTERNAL SOFTWARE

Hi all,

I am new to Threejs. I have 3D models and csv files with marker coordinates. While using other software like Metashape or Navisworks the markers coordinates in the csv file lead to the exact location where it was originally placed.

When I load the same 3D models in Threejs the coordinates system is completely changed and the coordinates of the markers in the csv file become useless.

I am using annotations to represent the markers (just edited an example scritpt found here ). When I insert the x,y,z coordinates from the csv file at the “lookAt” position it leads me somewhere else. Any idea of what I have to do?

I am thinking the issue is between line 64 and 90 in the image below.

The entire script is below:

import { Component, OnInit, VERSION } from ‘@angular/core’;

import * as THREE from ‘three’;

import { OrbitControls } from ‘three/examples/jsm/controls/OrbitControls’;

import { OBJLoader } from ‘three/examples/jsm/loaders/OBJLoader’;

import { MTLLoader } from ‘three/examples/jsm/loaders/MTLLoader’;

import Stats from ‘three/examples/jsm/libs/stats.module’;

import TWEEN from ‘three/examples/jsm/libs/tween.module.min’;

import {

CSS2DRenderer,

CSS2DObject,

} from ‘three/examples/jsm/renderers/CSS2DRenderer’;

@Component({

selector: ‘my-app’,

templateUrl: ‘./app.component.html’,

styleUrls: [’./app.component.css’],

})

export class AppComponent implements OnInit {

name = 'Angular ’ + VERSION.major;

constructor() {}

ngOnInit() {

this.load3DModal();

}

load3DModal() {

let annotations = [];

const annotationMarkers = [];

const scene = new THREE.Scene();

var light = new THREE.DirectionalLight();

light.position.set(-30, 30, 30);

scene.add(light);

var light2 = new THREE.DirectionalLight();

light2.position.set(30, 30, -30);

scene.add(light2);

const camera = new THREE.PerspectiveCamera(

  75,

  window.innerWidth / window.innerHeight,

  0.1,

  1000

);

camera.position.x = 10;

camera.position.y = 5;

camera.position.z = 8;

const renderer = new THREE.WebGLRenderer({ antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);

document.body.appendChild(renderer.domElement);

const labelRenderer = new CSS2DRenderer();

labelRenderer.setSize(window.innerWidth, window.innerHeight);

labelRenderer.domElement.style.position = 'absolute';

labelRenderer.domElement.style.top = '0px';

labelRenderer.domElement.style.pointerEvents = 'none';

document.body.appendChild(labelRenderer.domElement);

const controls = new OrbitControls(camera, renderer.domElement);

controls.dampingFactor = 0.2;

controls.enableDamping = true;

controls.target.set(8, 3, 4);

const raycaster = new THREE.Raycaster();

const sceneMeshes = new Array();

const circleTexture = new THREE.TextureLoader().load(

  'https://firebasestorage.googleapis.com/v0/b/dive-testing-268508.appspot.com/o/circle.png?alt=media&token=c10e0b88-3b23-42fb-81d0-07d97c072113'

);

const mtlLoader = new MTLLoader();

const progressBar: any = document.getElementById('progressBar');

const objLoader = new OBJLoader();

objLoader.load(

  'https://firebasestorage.googleapis.com/v0/b/dive-testing-268508.appspot.com/o/baseFiles%2Fcyllinder_no_flip_no_translate.obj?alt=media&token=e8206430-2043-4de6-b464-de471021ed4f',

  (object) => {

    //   object.scale.set(0.01, 0.01, 0.01);

    scene.add(object);

    sceneMeshes.push(object);

    var box = new THREE.Box3().setFromObject(object);

    var center = new THREE.Vector3();

    box.getCenter(center);

    object.position.sub(center);

    annotations = [

      {

        title: 'Tank SIde A',

        camPos: {

          y: -12.741706892945011,

          z: -4.218372137155576,

          x: -4.710730287250085,

        },

        lookAt: {

          x: -14.446332469449771,

          z: -6.427692230234284,

          y: -2.2862663387456337,

        },

        id: '58124016-6889-4d6b-ab6e-21840306abdc',

         },

    ];

    const annotationsPanel = document.getElementById('annotationsPanel');

    const ul = document.createElement('UL');

    const ulElem = annotationsPanel.appendChild(ul);

    Object.keys(annotations).forEach((a) => {

      const li = document.createElement('UL');

      const liElem = ulElem.appendChild(li);

      const button = document.createElement('BUTTON');

      button.innerHTML = a + ' : ' + annotations[a].title;

      button.className = 'annotationButton';

      button.addEventListener('click', function () {

        gotoAnnotation(annotations[a]);

      });

      liElem.appendChild(button);

      const annotationSpriteMaterial = new THREE.SpriteMaterial({

        map: circleTexture,

        depthTest: false,

        depthWrite: false,

        sizeAttenuation: false,

      });

      const annotationSprite = new THREE.Sprite(annotationSpriteMaterial);

      annotationSprite.scale.set(0.1, 0.1, 0.1);

      annotationSprite.position.copy(annotations[a].lookAt);

      annotationSprite.userData.id = a;

      scene.add(annotationSprite);

      annotationMarkers.push(annotationSprite);

      const annotationDiv = document.createElement('div');

      annotationDiv.className = 'annotationLabel';

      annotationDiv.innerHTML = a;

      const annotationLabel = new CSS2DObject(annotationDiv);

      annotationLabel.position.copy(annotations[a].lookAt);

      scene.add(annotationLabel);

      if (annotations[a].title) {

        const annotationDescriptionDiv = document.createElement('div');

        annotationDescriptionDiv.className = 'annotationDescription';

        annotationDescriptionDiv.innerHTML = annotations[a].title;

        annotationDiv.appendChild(annotationDescriptionDiv);

        annotations[a].descriptionDomElement = annotationDescriptionDiv;

      }

    });

    progressBar.style.display = 'none';

  }

);

(xhr) => {

  console.log((xhr.loaded / xhr.total) * 100 + '% loaded');

};

window.addEventListener('resize', onWindowResize, false);

function onWindowResize() {

  camera.aspect = window.innerWidth / window.innerHeight;

  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);

  labelRenderer.setSize(window.innerWidth, window.innerHeight);

  render();

}

renderer.domElement.addEventListener('pointerdown', onClick, false);

function onClick(event) {

  raycaster.setFromCamera(

    {

      x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,

      y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1,

    },

    camera

  );

  const intersects = raycaster.intersectObjects(annotationMarkers, true);

  if (

    intersects[0].object.userData &&

    intersects[0].object &&

    intersects[0].object.userData &&

    intersects[0].object.userData.id

  ) {

    gotoAnnotation(annotations[intersects[0].object.userData.id]);

  }

}

renderer.domElement.addEventListener('dblclick', onDoubleClick, false);

function onDoubleClick(event) {

  raycaster.setFromCamera(

    {

      x: (event.clientX / renderer.domElement.clientWidth) * 2 - 1,

      y: -(event.clientY / renderer.domElement.clientHeight) * 2 + 1,

    },

    camera

  );

  const intersects = raycaster.intersectObjects(sceneMeshes, true);

  if (intersects.length > 0) {

    const p = intersects[0].point;

    new TWEEN.Tween(controls.target)

      .to(

        {

          x: p.x,

          y: p.y,

          z: p.z,

        },

        500

      )

      .easing(TWEEN.Easing.Cubic.Out)

      .start();

    // .onComplete(() => {

    //     console.log(camera.position)

    //     console.log(controls.target)

    // })

  }

}

function gotoAnnotation(a) {

  new TWEEN.Tween(camera.position)

    .to(

      {

        x: a.camPos.x,

        y: a.camPos.y,

        z: a.camPos.z,

      },

      500

    )

    .easing(TWEEN.Easing.Cubic.Out)

    .start();

  new TWEEN.Tween(controls.target)

    .to(

      {

        x: a.lookAt.x,

        y: a.lookAt.y,

        z: a.lookAt.z,

      },

      500

    )

    .easing(TWEEN.Easing.Cubic.Out)

    .start();

  Object.keys(annotations).forEach((annotation) => {

    if (annotations[annotation].descriptionDomElement) {

      annotations[annotation].descriptionDomElement.style.display = 'none';

    }

  });

  if (a.descriptionDomElement) {

    console.log(a.descriptionDomElement.style.display);

    a.descriptionDomElement.style.display = 'block';

  }

}

// const stats = Stats();

//  document.body.appendChild(stats.dom);

var animate = function () {

  requestAnimationFrame(animate);

  controls.update();

  TWEEN.update();

  render();

  //   stats.update();

};

function render() {

  labelRenderer.render(scene, camera);

  renderer.render(scene, camera);

}

animate();

}

}