Три.проблема JS создание сеток вне функции load() загрузчика

У меня были трудности с экспортом более одной текстуры, используя три блендера.JS add-on, поэтому планировал работать вокруг него, разделяя части на отдельные сетки, но затем наткнулся на неожиданную проблему кода, не работающего, когда я создал сетки вне функции load (). Ниже приведен пример использования одной модели с одной сеткой. Следующие работы отлично:

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>working</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 {
                font-family: Monospace;
                background-color: #000000;
                margin: 0px;
                overflow: hidden;
            }

        </style>
    </head>

    <body>

        <script src="js/build/three.min.js"></script>

        <script src="js/loaders/ColladaLoader.js"></script>

        <script src="js/Detector.js"></script>

        <script>

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

            var container;

            var camera, scene, renderer, objects;

            var scaleAdj = 100;
            init();
            animate();

            function init() 
            {

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

                camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
                camera.position.set( 0, 500, 0 );

                scene = new THREE.Scene();
                scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );

                var loader = new THREE.JSONLoader();

                loader.load( 'cube.json', function ( geometry, materials ) 
                {

                    var faceMaterial = new THREE.MultiMaterial( materials );

                    for ( var i = 0; i < 250; i ++ ) 
                    {

                        var x = ( ( i % 27 )  - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
                        var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);

                        mesh = new THREE.Mesh( geometry, faceMaterial );

                        var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
                        mesh.scale.set( s, s, s );

                        mesh.position.set( x, scaleAdj, z );
                        mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );

                        mesh.matrixAutoUpdate = false;
                        mesh.updateMatrix();

                        scene.add( mesh );

                    }

                } );

                scene.add( new THREE.AmbientLight( 0xffffff ) );

                // ground
                var textureLoader = new THREE.TextureLoader();
                var groundTexture = textureLoader.load( "texture.jpg" );
                groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
                groundTexture.repeat.set( 40, 40 );
                groundTexture.anisotropy = 16;

                var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );

                var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
                mesh.position.y = 0;
                mesh.rotation.x = - Math.PI / 2;
                mesh.receiveShadow = true;
                scene.add( mesh );

                // Renderer

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

                renderer.setClearColor( scene.fog.color );

                container.appendChild( renderer.domElement );

                // Events

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

            }


            function onWindowResize( event ) {

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

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

            }

            function animate() {

                requestAnimationFrame( animate );

                render();

            }

            function render() {

                renderer.render( scene, camera );

            }



        </script>
    </body>
</html>

Но это не так (я аннотировал, какие разделы содержат различия):

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>not working</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 {
                font-family: Monospace;
                background-color: #000000;
                margin: 0px;
                overflow: hidden;
            }

        </style>
    </head>

    <body>

        <script src="js/build/three.min.js"></script>

        <script src="js/loaders/ColladaLoader.js"></script>

        <script src="js/Detector.js"></script>

        <script>

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

            //--------------- difference number 1
            var obj_geometry;
            var obj_material;
            //-----------------------------------

            var container;

            var camera, scene, renderer, objects;

            var scaleAdj = 100;
            init();
            animate();

            function init() 
            {

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

                camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
                camera.position.set( 0, 500, 0 );

                scene = new THREE.Scene();
                scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );


                //-------------------difference number 2--------------------
                var loader = new THREE.JSONLoader();

                loader.load( 'cube.json', function ( geometry, material ) 
                {
                    obj_geometry = geometry;
                    obj_material = material;
                });

                var faceMaterial = new THREE.MultiMaterial( obj_material);

                for ( var i = 0; i < 250; i ++ ) 
                {

                        var x = ( ( i % 27 )  - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
                        var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);

                        mesh = new THREE.Mesh( obj_geometry, faceMaterial);

                        var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
                        mesh.scale.set( s, s, s );

                        mesh.position.set( x, 0, z );
                        mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );

                        mesh.matrixAutoUpdate = false;
                        mesh.updateMatrix();

                        scene.add( mesh );

                }

                //--------------------------------------

                scene.add( new THREE.AmbientLight( 0xffffff ) );

                // ground
                var textureLoader = new THREE.TextureLoader();
                var groundTexture = textureLoader.load(  "texture.jpg" );
                groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
                groundTexture.repeat.set( 40, 40 );
                groundTexture.anisotropy = 16;

                var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );

                var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
                mesh.position.y = 0;
                mesh.rotation.x = - Math.PI / 2;
                mesh.receiveShadow = true;
                scene.add( mesh );

                // Renderer

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

                renderer.setClearColor( scene.fog.color );

                container.appendChild( renderer.domElement );

                // Events

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

            }


            function onWindowResize( event ) {

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

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

            }

            function animate() {

                requestAnimationFrame( animate );

                render();

            }

            function render() {

                renderer.render( scene, camera );

            }



        </script>
    </body>
</html>

Вот копия содержимого Куба.JSON:

{
    "uvs":[[0,0,1,0,1,1,0,1]],
    "faces":[43,0,1,2,3,0,0,1,2,3,0,1,2,3,43,4,7,6,5,0,0,1,2,3,4,5,6,7,43,0,4,5,1,0,0,1,2,3,0,4,7,1,43,1,5,6,2,0,0,1,2,3,1,7,6,2,43,2,6,7,3,0,0,1,2,3,2,6,5,3,43,4,0,3,7,0,0,1,2,3,4,0,3,5],
    "normals":[0.577349,-0.577349,-0.577349,0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,-0.577349,0.577349,0.577349,-0.577349,-0.577349,0.577349,-0.577349,-0.577349,0.577349,0.577349,0.577349,0.577349,0.577349],
    "metadata":{
        "generator":"io_three",
        "type":"Geometry",
        "normals":8,
        "vertices":8,
        "uvs":1,
        "version":3,
        "materials":1,
        "faces":6
    },
    "vertices":[1,-1,-1,1,-1,1,-1,-1,1,-1,-1,-1,1,1,-1,0.999999,1,1,-1,1,1,-1,1,-1],
    "materials":[{
        "DbgName":"Material",
        "colorSpecular":[0.5,0.5,0.5],
        "DbgIndex":0,
        "mapDiffuseWrap":["RepeatWrapping","RepeatWrapping"],
        "mapDiffuse":"texture.jpg",
        "shading":"phong",
        "depthTest":true,
        "opacity":1,
        "transparent":false,
        "colorDiffuse":[0.64,0.64,0.64],
        "mapDiffuseAnisotropy":1,
        "blending":"NormalBlending",
        "depthWrite":true,
        "visible":true,
        "specularCoef":50,
        "mapDiffuseRepeat":[1,1],
        "colorEmissive":[0,0,0],
        "wireframe":false,
        "DbgColor":15658734
    }],
    "name":"CubeGeometry"
}

И здесь прикрепленная текстура которая смогла быть использована.

Это может быть просто тривиальной проблемой для некоторых плакатов здесь, и если это так, Заранее спасибо за то, что просто дал мне знать, что это. Если нет, то ответ может быть полезен гораздо большему количеству людей, и спасибо за любую помощь, которую вы можете дать на него.

2 ответа

  1. Вы не можете сделать это асинхронно:

    var obj_geometry; // === undefined
    var myMesh = new THREE.Mesh( obj_geometry ); //because undefined, same as calling new THREE.Mesh();
    
    obj_geometry = geometry;//does nothing, mesh has no idea about this happening
    obj_material = material;
    

    Когда вы строите сетку, вы дали ее undefinedдля геометрии, поэтому я думаю, что она просто вызывает new Geometry()внутри конструктора. Эта сетка была создана с уникальным isntance пустого Geometryи не имеет ничего общего с вашим obj_geometry.

    Решение здесь сделать:

    var obj_geometry = new THREE.Geometry();
    var myMesh = new THREE.Mesh( obj_geometry ); //holds a reference to an empty "proxy"
    

    затем onLoad

    loader.load( 'url' , function( geom ) {
      obj_geometry.merge(geom); //"FILL PREVIOUSLY CREATED GEOMETRY WITH DATA"
      obj_geometry.vertsNeedUpdate = true; // there's a few flags like this you need to turn on
    }
    

    ИЛИ

    var myMesh = new THREE.Mesh();
    
    loader.load( 'url', function( geom ) {
    
       myMesh.geometry = geom; //"PUT THE JUST CREATED GEOMETRY IN THE RIGHT PLACE"
       //myOtherMesh.geometry = geom; //if you have more places where this needs to end up
       //myThirdMesh.geometry = geom; //gets very cumbersome
    
    }
    

    Оба довольно громоздкие и не очень интуитивные 🙁 мне очень не нравится эта часть трех.js.

  2. Благодаря помощи pailhead, указав на асинхронную проблему, я внес следующие изменения в код и обнаружил, что он работает. Удивительно, что количество, которое я добавил, Не кажется выше 0, но я предполагаю, что это было, потому что это было довольно близко.

    <!DOCTYPE html>
    <html lang="en">
        <head>
            <title>asynchronous working</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 {
                    font-family: Monospace;
                    background-color: #000000;
                    margin: 0px;
                    overflow: hidden;
                }
    
            </style>
        </head>
    
        <body>
    
    
            <script src="build/three.min.js"></script>
    
            <script>
    
                //--------------- difference number 1
                var obj_geometry;
                var obj_material;
                var loaded = false;
                //-----------------------------------
    
                var container;
    
                var camera, scene, renderer, objects;
    
                var scaleAdj = 100;
                init();
                animate();
    
                function init() 
                {
    
                    container = document.createElement( 'div' );
                    document.body.appendChild( container );
    
                    //-----an info display
                    info = document.createElement( 'div' );
                    info.id = "info";
                    info.style.position = 'absolute';
                    info.style.top = '10px';
                    info.style.width = '100%';
                    info.style.textAlign = 'center';
    
                    container.appendChild(info);
                    //-----------------
    
    
                    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 20000 );
                    camera.position.set( 0, 500, 0 );
    
                    scene = new THREE.Scene();
                    scene.fog = new THREE.Fog( 0xcce0ff, 10, 10000 );
    
    
                    //-------------------difference number 2--------------------
                    var loader = new THREE.JSONLoader();
    
                    loader.load( 'cube.json', function ( geometry, material ) 
                    {
                        obj_geometry = geometry;
                        obj_material = material;
                        loaded = true;
    
                    });
    
                    var notLoadedCount = 0;
    
                    var processor = setInterval(function()
                    {           
                        if(!loaded)
                        {
                            notLoadedCount++;                   
                        }
                        else
                        {
                            var faceMaterial = new THREE.MultiMaterial( obj_material);
    
                            for ( var i = 0; i < 250; i ++ ) 
                            {
    
                                var x = ( ( i % 27 )  - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
                                var z = ( Math.floor( i / 27 ) - 13.5 ) * (5 * scaleAdj) + THREE.Math.randFloatSpread( 300 * scaleAdj);
    
                                mesh = new THREE.Mesh( obj_geometry, faceMaterial);
    
                                var s = THREE.Math.randFloat( 0.5, 2 ) * scaleAdj;
                                mesh.scale.set( s, s, s );
    
                                mesh.position.set( x, 0, z );
                                mesh.rotation.y = THREE.Math.randFloat( -0.25, 0.25 );
    
                                mesh.matrixAutoUpdate = false;
                                mesh.updateMatrix();
    
                                scene.add( mesh );
    
                                info.innerHTML= '*not loaded count = ' + notLoadedCount;
    
                            }
    
                            clearInterval(processor);
                        }
                    }, 100);
    
    
                    //--------------------------------------
    
                    scene.add( new THREE.AmbientLight( 0xffffff ) );
    
                    // ground
                    var textureLoader = new THREE.TextureLoader();
                    var groundTexture = textureLoader.load(  "texture.jpg" );
                    groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
                    groundTexture.repeat.set( 40, 40 );
                    groundTexture.anisotropy = 16;
    
                    var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
    
                    var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
                    mesh.position.y = 0;
                    mesh.rotation.x = - Math.PI / 2;
                    mesh.receiveShadow = true;
                    scene.add( mesh );
    
                    // Renderer
    
                    renderer = new THREE.WebGLRenderer();
                    renderer.setPixelRatio( window.devicePixelRatio );
                    renderer.setSize( window.innerWidth, window.innerHeight );
    
                    renderer.setClearColor( scene.fog.color );
    
                    container.appendChild( renderer.domElement );
    
                    // Events
    
                    window.addEventListener( 'resize', onWindowResize, false );
    
                }
    
    
                function onWindowResize( event ) {
    
                    renderer.setSize( window.innerWidth, window.innerHeight );
    
                    camera.aspect = window.innerWidth / window.innerHeight;
                    camera.updateProjectionMatrix();
    
                }
    
                function animate() {
    
                    requestAnimationFrame( animate );
    
                    render();
    
                }
    
                function render() {
    
                    renderer.render( scene, camera );
    
                }
    
    
    
            </script>
        </body>
    </html>
    

    Спасибо за помощь в этом, надеюсь, это поможет другим тоже. Если есть какие-либо проблемы с этим разрешением, которые кто-либо замечает, пожалуйста, дайте мне знать. Спасибо.