-
Notifications
You must be signed in to change notification settings - Fork 4
The basic functions
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()
.
MyMiniFactory | 2018