Skip to content

The basic functions

William CLOT edited this page Sep 4, 2018 · 5 revisions

Now that we know the how the bones work we can dive into the basic function of the app. The main function that does all the magic here is placeMesh():

function placeMesh(
  meshName,
  bodyPartClass,
  MeshType,
  parentAttachment,
  childAttachment,
  rotation,
  firstLoad,
  highLight,
  bones,
  poseData
) {
  loader.load(
    "models/" + bodyPartClass + "/" + meshName + ".glb",
    gltf => {
      var root = gltf.scene.children[0];
      root.traverse(function(child) {
        if (child instanceof THREE.Mesh) {
          // colouring the mesh in a unified color throughout the customizer
          child.castShadow = true;
          child.material.color = { r: 0.5, g: 0.5, b: 0.5 };
        }
      });

      group.add(root);

      scene.updateMatrixWorld(true);

      // updating the current value of loadedMeshes  
      loadedMeshes[MeshType].name = meshName;
      loadedMeshes[MeshType].rotation = rotation;

      if (MeshType === "Head" && firstLoad) {
        changeColor("Head", color);
      }
      // if the mesh must be highlighted then we change the color to red
      if (highLight) {
        changeColor(MeshType, color);
      }

      // Putting the new mesh in the pose configuration if any pose as been selected
      if (poseData) {
        root.traverse(function(child) {
          if (child instanceof THREE.Bone) {
            if (poseData[child.name]) {
              window.changeRotation(child.name, poseData[child.name].x, "x");
              window.changeRotation(child.name, poseData[child.name].y, "y");
              window.changeRotation(child.name, poseData[child.name].z, "z");
            }
          }
        });
      }

      if (
        typeof parentAttachment !== "undefined" &&
        typeof childAttachment !== "undefined"
      ) {
        //placing the mesh at the correct position
        let targetBone = scene.getObjectByName(parentAttachment);
        let object = scene.getObjectByName(childAttachment);
        clearPosition(object);
        rotateElement(object, true);
        rotateElement(object, false, rotation);
        targetBone.add(object);
      }

      //Going to look for all children of current mesh (recursive function)
      let children = childrenList[MeshType];
      if (children) {
        for (let i = 0; i < children.length; i++) {
          replaceMesh(children[i], firstLoad, bones, poseData);
        }
      }

      if (MeshType === "FootR") {
        if (scene.getObjectByName("FootL_Toes_L")) {
          scene.updateMatrixWorld();
          placeStand();
        }
      } else if (MeshType === "FootL") {
        if (scene.getObjectByName("FootR_Toes_R")) {
          scene.updateMatrixWorld();
          placeStand();
        }
      }
      window.partloaded = true;
    },
    null,
    function(error) {
      console.log(error);
    }
  );
}

It takes as argument the meshName which is the name of the glb file to open, the bodyPartClass to know in which directory we need to fetch the glb file, the MeshType to know where to put the mesh and to which bones the mesh will be linked to the skeleton with parentAttachment and childAttachment, rotation if the mesh must be loaded with a certain rotation, highlight if the mesh is selected in the customizer and poseData to put the current mesh in a certain position.

It firsts loads the glb file into the scene, it deals with changing the color to a unified gray or the highlight color. It updates the loadedMeshes value then changes the rotation of the bones within the placed mesh to the ones found in the poseData (which actually just is a list of rotation for each bones). It then deals with the position of the mesh, in order to position the mesh at the correct coordinates in space I just use the skinned mesh capabilities of Threejs to fetch the parent bone and add the child bone the it's children by using the command parentBone.add(childBone);

One of the great things about this function is that if we select a new torso then I want this function to place again all the children of the Torso (which means every mesh). I made this function recursive by looking at the children of the current mesh, if this mesh as children then it will then call placeMesh() again on all the children via the function replaceMesh().