Mig Bach
Mig Bach

Reputation: 65

Why does placing more than 1 place marker on an planet object3D not work anymore?

I have a piece of code from 3 years ago that appears to not be working anymore from Three.js.

I have updated all of the other issues of the migration to ES6 for Three.js, but when I try to add as I did in the past more than 1 place marker on the planet surface, only 1 place marker is displayed, with only the last added place marker being successfully displayed in the desired position... with all other place markers being erased.

Problem example -> https://jsfiddle.net/jhL6s579/6/

Complete code:

HTML

<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://s3-eu-west-2.amazonaws.com/bckld/lab/loading.js"></script>

JS

// ------ Marker object ------------------------------------------------

function Marker() {
    var radius = 0.005;
    var sphereRadius = 0.02;
    var height = 0.05;
    var material = new THREE.MeshPhongMaterial({ color: 0xbab68f });
    var cone = new THREE.Mesh(new THREE.ConeBufferGeometry(radius, height, 8, 1, true), material);
    cone.position.y = height * 0.5;
    cone.rotation.x = Math.PI;
    var sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(sphereRadius, 16, 8), material);
    sphere.position.y = height * 0.95 + sphereRadius;
    this.add(cone, sphere);
}
Marker.prototype = Object.create(new THREE.Object3D());

// ------ Earth object -------------------------------------------------

function Earth(radius, texture) {
    this.userData.radius = radius;
    var earth = new THREE.Mesh(
        new THREE.SphereBufferGeometry(radius, 64.0, 48.0),
        new THREE.MeshPhongMaterial({
            map: texture
        })
    );
    this.add(earth);
}
Earth.prototype = Object.create(new THREE.Object3D());
Earth.prototype.createMarker = function (lat,lon ) {
    var marker = new Marker();

    var lonRad = -lon * (Math.PI / 180);
    var latRad = lat * (Math.PI / 180);
    var r = this.userData.radius;

    marker.position.set(Math.cos(latRad) * Math.cos(lonRad) * r, Math.sin(latRad) * r, Math.cos(latRad) * Math.sin(lonRad) * r);
    marker.rotation.set(0.0, -lonRad, latRad - Math.PI * 0.5);

    this.attach(marker);
};

// ------ Three.js code ------------------------------------------------

var scene, camera, renderer;
var controls;

init();

function init() {
    scene = new THREE.Scene();

    camera = new THREE.PerspectiveCamera(45, 4 / 3, 0.1, 100);
    camera.position.set(0.0, 1.5, 3.0);

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

    controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.autoRotate = true;
    controls.autoRotateSpeed = -1.0;
    controls.enablePan = false;

    var ambient = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambient);

    var direcitonal = new THREE.DirectionalLight(0xffffff, 0.5);
    direcitonal.position.set(5.0, 2.0, 5.0).normalize();
    scene.add(direcitonal);

    // just some code for the loading
    var manager = createLoader(renderer.domElement, animate);

    var texLoader = new THREE.TextureLoader(manager).setCrossOrigin(true);

    var texture = texLoader.load('https://s3-eu-west-2.amazonaws.com/bckld/lab/textures/earth_latlon.jpg');
    texture.anisotropy = renderer.capabilities.getMaxAnisotropy();

    var earth = new Earth(1.0, texture);

    earth.createMarker(48.856700, 2.350800); // Paris
    earth.createMarker(28.524167, -80.650833); // Paris

    scene.add(earth);

    window.addEventListener('resize', onResize);
    onResize();

    document.body.appendChild(renderer.domElement);
}

function onResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

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

function animate() {
    requestAnimationFrame(animate);

    controls.update();

    renderer.render(scene, camera);
}

CSS

body {
    background: #000;
    margin: 0;
    overflow: hidden;
}

I have also tried doing this.attach(marker) but still not working...

Upvotes: 2

Views: 144

Answers (1)

Mugen87
Mugen87

Reputation: 31066

You have to derive your custom classes Marker and Earth in ES6 now. Meaning you have to use the class syntax like below since Object3D is now a class, too.

// ------ Marker object ------------------------------------------------

class Marker extends THREE.Object3D {

  constructor() {

    super();
    var radius = 0.005;
    var sphereRadius = 0.02;
    var height = 0.05;
    var material = new THREE.MeshPhongMaterial({
      color: 0xbab68f
    });
    var cone = new THREE.Mesh(new THREE.ConeBufferGeometry(radius, height, 8, 1, true), material);
    cone.position.y = height * 0.5;
    cone.rotation.x = Math.PI;
    var sphere = new THREE.Mesh(new THREE.SphereBufferGeometry(sphereRadius, 16, 8), material);
    sphere.position.y = height * 0.95 + sphereRadius;
    this.add(cone, sphere);

  }

}

// ------ Earth object -------------------------------------------------

class Earth extends THREE.Object3D {

  constructor(radius, texture) {
  
    super();

    this.userData.radius = radius;
    var earth = new THREE.Mesh(
      new THREE.SphereBufferGeometry(radius, 64.0, 48.0),
      new THREE.MeshPhongMaterial({
        map: texture
      })
    );
    this.add(earth);
  }

  createMarker(lat, lon) {
    var marker = new Marker();

    var lonRad = -lon * (Math.PI / 180);
    var latRad = lat * (Math.PI / 180);
    var r = this.userData.radius;

    marker.position.set(Math.cos(latRad) * Math.cos(lonRad) * r, Math.sin(latRad) * r, Math.cos(latRad) * Math.sin(lonRad) * r);
    marker.rotation.set(0.0, -lonRad, latRad - Math.PI * 0.5);

    this.attach(marker);
  }


}


// ------ Three.js code ------------------------------------------------

var scene, camera, renderer;
var controls;

init();

function init() {
  scene = new THREE.Scene();

  camera = new THREE.PerspectiveCamera(45, 4 / 3, 0.1, 100);
  camera.position.set(0.0, 1.5, 3.0);

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

  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.autoRotate = true;
  controls.autoRotateSpeed = -1.0;
  controls.enablePan = false;

  var ambient = new THREE.AmbientLight(0xffffff, 0.5);
  scene.add(ambient);

  var direcitonal = new THREE.DirectionalLight(0xffffff, 0.5);
  direcitonal.position.set(5.0, 2.0, 5.0).normalize();
  scene.add(direcitonal);

  // just some code for the loading
  var manager = createLoader(renderer.domElement, animate);

  var texLoader = new THREE.TextureLoader(manager).setCrossOrigin(true);

  var texture = texLoader.load('https://s3-eu-west-2.amazonaws.com/bckld/lab/textures/earth_latlon.jpg');
  texture.anisotropy = renderer.capabilities.getMaxAnisotropy();

  var earth = new Earth(1.0, texture);

  earth.createMarker(48.856700, 2.350800); // Paris
  earth.createMarker(28.524167, -80.650833); // Paris

  scene.add(earth);

  window.addEventListener('resize', onResize);
  onResize();

  document.body.appendChild(renderer.domElement);
}

function onResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

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

function animate() {
  requestAnimationFrame(animate);

  controls.update();

  renderer.render(scene, camera);
}
body {
    margin: 0;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>
<script src="https://s3-eu-west-2.amazonaws.com/bckld/lab/loading.js"></script>

Upvotes: 2

Related Questions