Strange result adding multiple texture planes

Hi,

I am trying to add multiple texture planes to a scene, each texture comes from a remote different url image and it is positioned on a exact point defined by an array of positions.

The images are provided by asyncronous calls to a server api.

My problem is that each time that loads the scene the images are positioned on different position or are repeated .

What I am doing wrong?

This is my code:

<!DOCTYPE html>
<html lang="en">
<head>
  <title>three.js webgl - effects - stereo</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
  <style>
    body {
      background:#0000ff;
      padding:0;
      margin:0;
      font-weight: bold;
      overflow:hidden;
    }
  </style>
</head>

<body>
<script src="https://www.gstatic.com/firebasejs/4.9.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.9.0/firebase-database.js"></script>

<script src="js/three.js"></script>
<script src="js/DeviceOrientationControls.js"></script>
<script src="js/StereoEffect.js"></script>
<script src="js/Detector.js"></script>
<script>

    if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

    var container;

    var camera, scene, renderer, effect, controls;

    var SCALE = 3;


    var loader = new THREE.TextureLoader();
    //allow cross origin loading
    loader.crossOrigin = '';

    var lastTweet;
    var feedTwitter = [];
    var feedInstagram = [];


    var positions =[
        [4, 0, 0],
        [4, 5, -5],
        [4, 5, 5],
        [4, 0, -5],
        [4, 0, 5],
        [4, -5, -5],
        [4, -5, 5],
        [-3, 5, -5],
        [-3, 0, -5],
        [-3, -5, -5],
        [-3, 5, 5],
        [-3, 0, 5],
        [-3, -5, 5]
    ]


    var windowHalfX = window.innerWidth / 2;
    var windowHalfY = window.innerHeight / 2;


    asyncronous.on("value", function(snapshot){
        var data = snapshot.val()
      
        var geometry = new THREE.PlaneGeometry(1.5 * SCALE, 1 * SCALE);

        var texture = loader.load(data[0]);
        var material = new THREE.MeshBasicMaterial({map: texture});
        var plane = new THREE.Mesh(geometry, material);
        plane.position.x = positions[0][0]
        plane.position.y = positions[0][1]
        plane.position.z = positions[0][2]

        plane.lookAt(camera.position);
        scene.add(plane)

        lastTweet = plane;

    });



    asyncronous2.on("value", function(snapshot){
        var dataTweet = snapshot.val()
        console.log("TWITT" + JSON.stringify(dataTweet));
        
        for(var i = 0; i < dataTweet.length; i++){
            var geometry = new THREE.PlaneGeometry(1.5 * SCALE, 1 * SCALE);

            var texture = loader.load(dataTweet[i]);
            var material = new THREE.MeshBasicMaterial({map: texture});
            var plane = new THREE.Mesh(geometry, material);
            plane.position.x = positions[i + 1][0]
            plane.position.y = positions[i + 1][1]
            plane.position.z = positions[i + 1][2]

            plane.lookAt(camera.position);
            scene.add(plane)

          feedTwitter.push(plane);


        }


    });


      asyncronous3.on("value", function(snapshot){
          var dataInsta = snapshot.val()
          console.log("INSTA" + JSON.stringify(dataInsta));

          for(var i = 0; i < dataInsta.length; i++){
              for(var i = 0; i < dataInsta.length; i++){
                  var geometry = new THREE.PlaneGeometry(1.5 * SCALE, 1 * SCALE);

                  var texture = loader.load(dataInsta[i]);
                  var material = new THREE.MeshBasicMaterial({map: texture});
                  var plane = new THREE.Mesh(geometry, material);
                  plane.position.x = positions[i + 7][0]
                  plane.position.y = positions[i + 7][1]
                  plane.position.z = positions[i + 7][2]

                  plane.lookAt(camera.position);
                  scene.add(plane)

                  feedInstagram.push(plane);


              }
          }
      });






    init();
    animate();


    function init() {

        container = document.createElement( 'div' );
        document.body.appendChild( container );

        camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 100000 );
        /*camera.position.x= 0
        camera.position.y= 0
        camera.position.z= 0*/
        controls = new THREE.DeviceOrientationControls( camera );

        scene = new THREE.Scene();
        scene.background = new THREE.CubeTextureLoader()
            .setPath( 'textures/cube/demo/' )
            .load( [ 'px.jpg', 'nx.jpg', 'py.jpg', 'ny.jpg', 'pz.jpg', 'nz.jpg' ] );


        renderer = new THREE.WebGLRenderer()
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        container.appendChild( renderer.domElement );



        effect = new THREE.StereoEffect( renderer );
        effect.setSize( window.innerWidth, window.innerHeight );
        effect.separation = 0.6;
        console.log("finish init")

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

    }
    
    function onWindowResize() {

        windowHalfX = window.innerWidth / 2;
        windowHalfY = window.innerHeight / 2;

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

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

    }



    function animate() {

        requestAnimationFrame( animate );
        controls.update();
        render();

    }

    function render() {

        effect.render( scene, camera );/*
        console.log("finish render")*/

    }
</script>

</body>
</html>

You can’t control in which order your async request are finished. Each time, the responses are in a different order and thus the state of your 3D visualization.

This is the only problem I can think of right now…

OK, you are right, the order is async but it render repeated images, when all images are different.

On the other hand the async request returns an array of images, then I load the texture with this url and add to the scene

var texture = loader.load(data[i]);

I don’t know why

What would be a correct and safe way to add multiple images to a scene in a determined position?

Thanks a lot

Crossposting:

Sorry but I need help with this and all help is welcome :wink:

I’d recommend to load all the resources (textures) first, putting them in an array (THREE.LoadingManager() is a big help in this question). When it’s done, initialize your scene with setting planes at determined positions with associated texture from an array. That’s all.

1 Like

Thanks a lot. I will try it

Is it possible to create different managers?

The image url resources comes to the app asynchronously from different services.

thanks

I think that I arrived to a key of problem.

Each texture was a png file of 900x700px. When the texture loader load the texture the log says that the size of the image is not power of two and automatically resize to a 512 x512 image.

If I load images, for example, of 2048 x 1024 it works correctly.

However if I pass images more smaller(not power of 2) it resizes to 256 x 256 and works fine.

What I am missing? Memory leak?

Thanks

This is no memory leak. Just a warning that POT textures needs to be generate because of mipmapping. You can…

  • ignore the warning,
  • ensure the usage of POT textures or
  • set texture.minFilter to a different value like THREE.LinearFilter.

Wich would be the best practice?

If possible, ensure POT textures.

Thanks a lot. I will use POT.

Some explicaction to my initial problem:

If i not use POT images the loader render random images.

?

Thanks