threejs Box UV Mapping

by realhunts

HTML

<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r101/build/three.min.js"></script>
<script src="https://rawcdn.githack.com/mrdoob/three.js/r101/examples/js/controls/OrbitControls.js"></script>

    <script src="https://rawcdn.githack.com/mrdoob/three.js/r101/examples/js/loaders/GLTFLoader.js"></script>

CSS

body {
  overflow: hidden;
}

JavaScript

function _applyBoxUV(geom, transformMatrix, bbox, bbox_max_size) {

  let coords = [];
  coords.length = 2 * geom.attributes.position.array.length / 3;

  // geom.removeAttribute('uv');
  if (geom.attributes.uv === undefined) {
    geom.addAttribute('uv', new THREE.Float32BufferAttribute(coords, 2));
  }
  
  //maps 3 verts of 1 face on the better side of the cube
  //side of the cube can be XY, XZ or YZ
  let makeUVs = function(v0, v1, v2) {

    //pre-rotate the model so that cube sides match world axis
    v0.applyMatrix4(transformMatrix);
    v1.applyMatrix4(transformMatrix);
    v2.applyMatrix4(transformMatrix);

    //get normal of the face, to know into which cube side it maps better
    let n = new THREE.Vector3();
    n.crossVectors(v1.clone().sub(v0), v1.clone().sub(v2)).normalize();

    n.x = Math.abs(n.x);
    n.y = Math.abs(n.y);
    n.z = Math.abs(n.z);

    let uv0 = new THREE.Vector2();
    let uv1 = new THREE.Vector2();
    let uv2 = new THREE.Vector2();
    // xz mapping
    if (n.y > n.x && n.y > n.z) {
      uv0.x = (v0.x - bbox.min.x) / bbox_max_size;
      uv0.y = (bbox.max.z - v0.z) / bbox_max_size;

      uv1.x = (v1.x - bbox.min.x) / bbox_max_size;
      uv1.y = (bbox.max.z - v1.z) / bbox_max_size;

      uv2.x = (v2.x - bbox.min.x) / bbox_max_size;
      uv2.y = (bbox.max.z - v2.z) / bbox_max_size;
    } else
    if (n.x > n.y && n.x > n.z) {
      uv0.x = (v0.z - bbox.min.z) / bbox_max_size;
      uv0.y = (v0.y - bbox.min.y) / bbox_max_size;

      uv1.x = (v1.z - bbox.min.z) / bbox_max_size;
      uv1.y = (v1.y - bbox.min.y) / bbox_max_size;

      uv2.x = (v2.z - bbox.min.z) / bbox_max_size;
      uv2.y = (v2.y - bbox.min.y) / bbox_max_size;
    } else
    if (n.z > n.y && n.z > n.x) {
      uv0.x = (v0.x - bbox.min.x) / bbox_max_size;
      uv0.y = (v0.y - bbox.min.y) / bbox_max_size;

      uv1.x = (v1.x - bbox.min.x) / bbox_max_size;
      uv1.y = (v1.y - bbox.min.y) / bbox_max_size;

      uv2.x = (v2.x - bbox.min.x) /...