如何在three.js中一次只加载一个模型?

时间:2017-01-03 19:08:45

标签: javascript jquery three.js

我正在开发一个程序,它将项添加到three.js场景中,根据场景中已存在的项目将它们定位在坐标处。目前,我遇到的问题是,当用户选择"高空作业时,会有两个人加入到场景中。这是两个单独的函数调用,但是当场景结束时,两个人都处于相同的坐标。当用户点击添加多个人并且不等待每个人加载时,也会发生这种情况。

有没有办法可以强制我的加载函数等待第一个对象完成加载,以便一次只加载一个模型?

This mention of the LoadingManager让我思考,并尝试通过保存加载的文件数和总数作为变量来使用它,然后在while循环中比较它们,但是,正如预期的那样,这只会减慢脚本的速度我的浏览器希望我阻止它们。



// adds objects to the basket with the appropriate rotation
      function createObjectBasket(filePath, scale, position, name, type) {
        // Load in the object and add it to the scene.
        var loader = new THREE.ObjectLoader(manager);
        /*while (gl_itemsLoaded < gl_itemsTotal) {
          
        }*/
        loader.load( filePath, function(object, materials){
          
          // rotate
          object.rotation.x = - ((Math.PI / 2) - (Math.PI / 18));
          object.rotation.y = - (Math.PI - (Math.PI / 5));
          object.rotation.z = 0; //- (Math.PI / 120);
          
          // scale
          object.scale.set(scale, scale, scale);
          
          // translate
          object.position.set(position.x, position.y, position.z);
          
          // set name for easy access
          object.name = name;
          
          // add to scene
          scene.add(object);
          
          if (type == "basket") {
            // add to object array for easy access
            basketContents["basket"].push(object);
          }
          else if (type == "person") {
            // add to object array for easy access
            basketContents["people"].push(object);
          }
          else if (type == "tool") {
            // add to object array for easy access
            basketContents["tools"].push(object);
          }
          else if (type == "attachment") {
            // add to object array for easy access
            basketContents["attachments"].push(object);
          }
        });
      }
&#13;
&#13;
&#13;

如果我遇到问题,可以通过以下两行(间接)调用此代码:

&#13;
&#13;
objectAddRemove("person", "CWM_A");
objectAddRemove("person", "CWM_B");
&#13;
&#13;
&#13;

然后执行调用createObjectBasket的函数:

&#13;
&#13;
      // add/remove objects to/from basket on click
      function objectAddRemove(type, objectName) {
        // if adding items
        if (addRemove == "add") {
          
          // determine if there is still room to add more objects
          var room = true;
          // can have <= 3 people total, so if there are 3, can't add more
          if ((type == "person") && basketContents["people"].length >= 3) {
            room = false;
            return;
          }
          // no current restrictions on tools
          /*else if ((type == "tool")) {
            
          }*/
          // can only have 1 of each attachment
          else if ((type == "attachment") && (object[objectName]["contentsCount"] > 0)) {
            room = false;
            return;
          }
          
          if (room == true) {
            // if it's a person
            if (type == "person") {
              // if it's a man
              if (objectName.indexOf("M") >= 0) {
                // add model
                createObjectBasket(("models/" + objectName + ".json"), 1.5, personCoordsMan[basketContents["people"].length + 1], objectName, "person");
              }
              // if it's a woman
              else {
                // add model
                createObjectBasket(("models/" + objectName + ".json"), 1.5, personCoordsWoman[basketContents["people"].length + 1], objectName, "person");
              }
            }
            // if it's a tool
            else if (type == "tool") {
              /*createObjectBasket(("models/" + objectName + ".json"), 1.5, toolCoords[basketContents["tools"].length + 1], objectName, "tool");*/
              createObjectBasket(("models/" + objectName + ".json"), 1.5, toolCoords, objectName, "tool");
            }
            // if it's an attachment
            else if (type == "attachment") {
              createObjectBasket(("models/" + objectName + ".json"), .04, attachmentCoords[objectName], objectName, "attachment");
            }

            // increase count
            object[objectName]["contentsCount"] += 1;
            console.log(objectName);

            $('#' + objectName).children('.status').children('.checkMark').show();
          }
        }
        
        // if removing items
        else if (addRemove == "remove") {
          
          // remove objects from arrays
          if (type == "person") {
            removeObjectArray("people", objectName);
            
            // if person is found (and removed), rearrange all people to accommodate
            if (itemFound == true) {
              for (i = 0; i < basketContents["people"].length; ++i) {
                if (basketContents["people"][i].name.indexOf("M") >= 0) {
                  basketContents["people"][i].position.set(personCoordsMan[i+1].x, personCoordsMan[i+1].y, personCoordsMan[i+1].z);
                }
                else {
                  basketContents["people"][i].position.set(personCoordsWoman[i+1].x, personCoordsWoman[i+1].y, personCoordsWoman[i+1].z);
                }
              }
            }
          }
          else if (type == "tool") {
            removeObjectArray("tools", objectName);
            
            // if tool is found (and removed), rearrange all tools to accommodate
            /*if (itemFound == true) {
              
            }*/
          }
          else if (type == "attachment") {
            removeObjectArray("attachments", objectName);
          }
          
          // if all objects of that id have been removed, hide remove x mark
          if (object[objectName]["contentsCount"] <= 0) {
            $('#' + objectName).children('.status').children('.xMark').hide();
          }
          
          // if, after removing, person/object count is now 0, no remaining items can be removed, so switch to add
          if ((steps[currentStep] == "people") && (basketContents["people"].length <= 0)) {
            addItems();
          }
          else if ((steps[currentStep] == "objects") && ((basketContents["tools"].length + basketContents["attachments"].length) <= 0)) {
            addItems();
          }
        }
        // if no remaining items can be removed on this page
        else {
          addItems();
        }
      }
&#13;
&#13;
&#13;

每当一个人点击代表所需对象的图像时,也会调用objectAddRemove,因此我还需要一种方法来等待先前点击的模型加载(除了通过代码自动加载的模型)。

要测试/查看更多代码,您可以访问this link。选择&#34;高度工作&#34;,权重单位,然后跳到&#34;添加运营商&#34;。它将显示两个人在篮子里(已检查)但在篮子中只能看到一个人。如果单击&#34;删除项目&#34;然后是可见的人去除可见的人,隐藏的人将会显示。

非常感谢!!!

2 个答案:

答案 0 :(得分:1)

加载外部数据几乎总是异步发生,因此确保在另一个模型加载后需要处理onLoad事件。

我不确定LoadingManager是否支持一个接一个地加载模型。

但您可以自己实现一个简单的加载队列。以下内容:

var myQueue = ['model1.dae', 'model2.dae'];

function loadFromQueue()
{
    if (myQueue.length == 0) return;

    // Takes the first name from array and remove it from the array
    var name = myQueue.shift(); 

    // Call the loader and provide an onLoad event handler
    loader.load(name, function(model){

         // Do what you need to do with the model,
         // usually it's scene.add(model) and some transformations.

         // Call the next item in the queue
         loadFromQueue();
    });
}

现在这是一个非常粗糙的队列,有更好的方法来做到这一点。但我正在使用它最简单的演示如何使用onLoad事件处理程序一个接一个地加载模型。

我认为你将遇到的下一个障碍是如何将一些值传递给事件处理程序。那么回来吧!

答案 1 :(得分:0)

我实际上通过采用不同的方法来解决这个问题 - 我需要变量来跟踪对象,所以我检查了对象是否已根据变量值(快速设置)而不是数量加载three.js对象(加载时间更长)。与使用超时相比,这在系统中工作得更好,更好,更可靠。