2015-12-27 228 views
0

在我的程序中,我有幾個地方我實例化幾何,每個地方都有自己的喜好,如何將它們的幾何圖形網格化(雙面或不是?Lambert或基本材質?)。但是,它們都使用相同的紋理。我只想加載這個常見的紋理一次。這給我一個設計問題:three.js:重用紋理?

當使用TextureLoader.load()加載紋理時,我只能使用一次紋理,即在傳遞給load函數的回調函數中。這意味着我必須在加載我的紋理之前收集我所有的幾何圖形實例和它們的每個參數,以便在啓動加載時使我的回調函數全部可用(通過閉包)。

我在想是否有一個規範的方法來解決這個問題?我想其他three.js用戶可能遇到過類似的情況。我知道如何使用promise來解決這個問題:load函數將返回一個代表紋理的promise。然後可以將該紋理傳遞給每個需要對幾何進行網格劃分的網站。這種解決方案非常方便,因爲我不需要收集大量的幾何數據,僅僅是爲了能夠在一個步驟後傳遞它。

但是,有沒有類似的方便,或近乎方便的解決這個問題,留在回調語義領域?

+1

因爲你需要等待加載紋理,承諾是迄今爲止在這裏最合適的。關於諾言的好處是你可以繼續調用'.then()',這會讓你的代碼更加乾淨。這聽起來像你不需要承諾的幫助,但我已經回答了一個類似的問題之前:http://stackoverflow.com/questions/33283386/is-there-a-way-to-wait-for-三textureloader負載到結束/ 33292152#33292152 – Leeft

回答

0

我結束了持續的承諾路線:包裹在JavaScript中的TextureLoader.load()調用內置的承諾,返回名爲constructor Promise

var loadTexture_promise = (texture_path, texture_loader) => { 
    var texture_promise; 

    if (  loadTexture_promise.texturePromises_cache[texture_path] !== undefined) { 
     return loadTexture_promise.texturePromises_cache[texture_path] 
    } 

    texture_promise = new Promise(
     function(resolve, reject) 
     { 
      texture_loader.load(
       texture_path, 
       function (texture) { 
        // Success callback of TextureLoader 
        // We're done, so tell the promise it is complete 
        resolve(texture); 
       }, 
       function (XmlHttpRequest_instance) { 
        // Progress callback of TextureLoader 
       }, 
       function (unknown_parameter) { 
        // Failure callback of TextureLoader 
        // Reject the promise with the failure 
        reject(new Error('Could not load texture ' + texture_path)); 
       } 
      ); 
     } 
    ); 

    // add texture_promise to cache: 
    loadTexture_promise.texturePromises_cache[texture_path] = texture_promise; 

    return texture_promise; 
}; 
// establish cache object on the loadTexture_promise function: 
loadTexture_promise.texturePromises_cache = []; 

然後我有一個lambertMesher功能,我的幾何供應商可撥打:

function lambertMesher (aGeometry, aTexture_promise, doubleSided, debug) { 
    var aMesh_promise = aTexture_promise.then(
     (resolved_texture) => 
     { 
      var material, mesh; 

      if (debug) { 
       console.log("resolved_texture: ", resolved_texture); 
       console.log("aGeometry: ", aGeometry); 
      } 

      resolved_texture.minFilter = THREE.NearestFilter; 

      if (doubleSided) { 
       material = new THREE.MeshLambertMaterial({ map: resolved_texture, side: THREE.DoubleSide }); 
      } else { 
       material = new THREE.MeshLambertMaterial({ map: resolved_texture, emissive: 0xffffff }); 
      } 

      mesh = new THREE.Mesh(aGeometry, material); 
      if (debug) { 
       console.log("mesh: ", mesh); 
      } 
      return mesh 

     }, 
     (reason_of_textureLoading_failure) => 
     { 
      console.log("meshing failed. Also: " + reason_of_textureLoading_failure) 
     } 
    ); 

    return aMesh_promise 
} 

最後,我這是怎麼叫我lambertMesher

var myPlateGeom = new THREE.PlateGeometry(myPlatePolygonSet, true); 
var myPlateMesh_promise = utils_meshers.lambertMesher(myPlateGeom, myRobinieTexture_promise, true, false); 

,然後,終於終於,我在我的網添加到我的場景是這樣的:

myPlateMesh_promise.then(
    (myPlateMesh) => { myScene.add(myPlateMesh) }, 
    (reason)  => console.log("failed to add myPlateMesh. Also: " + reason) 
);