updateMatrixWorld method

void updateMatrixWorld([
  1. bool force = false
])
override

Implementation

updateMatrixWorld([bool force = false]) {
  var space = (this.mode == 'scale')
      ? 'local'
      : this.space; // scale always oriented to local rotation

  var quaternion =
      (space == 'local') ? this.worldQuaternion : _identityQuaternion;

  // Show only gizmos for current transform mode

  this.gizmo['translate'].visible = this.mode == 'translate';
  this.gizmo['rotate'].visible = this.mode == 'rotate';
  this.gizmo['scale'].visible = this.mode == 'scale';

  this.helper['translate'].visible = this.mode == 'translate';
  this.helper['rotate'].visible = this.mode == 'rotate';
  this.helper['scale'].visible = this.mode == 'scale';

  var handles = [];
  handles.addAll(this.picker[this.mode].children);
  handles.addAll(this.gizmo[this.mode].children);
  handles.addAll(this.helper[this.mode].children);

  // print("TransformControlsGizmo cameraQuaternion ${this.cameraQuaternion.toJSON()} ");

  // print("TransformControlsGizmo updateMatrixWorld mode: ${this.mode} handles: ${handles.length}  ");

  for (var i = 0; i < handles.length; i++) {
    var handle = handles[i];

    // hide aligned to camera

    handle.visible = true;
    handle.rotation.set(0.0, 0.0, 0.0);
    handle.position.copy(this.worldPosition);

    var factor;

    if (this.camera! is OrthographicCamera) {
      factor = (this.camera!.top - this.camera!.bottom) / this.camera!.zoom;
    } else {
      factor = this.worldPosition.distanceTo(this.cameraPosition) *
          Math.min(
              1.9 *
                  Math.tan(Math.PI * this.camera!.fov / 360) /
                  this.camera!.zoom,
              7);
    }

    handle.scale.set(1.0, 1.0, 1.0).multiplyScalar(factor * this.size / 4);

    // TODO: simplify helpers and consider decoupling from gizmo

    if (handle.tag == 'helper') {
      handle.visible = false;

      if (handle.name == 'AXIS') {
        handle.position.copy(this.worldPositionStart);
        handle.visible = this.axis != null;

        if (this.axis == 'X') {
          _tempQuaternion.setFromEuler(_tempEuler.set(0, 0, 0), false);
          handle.quaternion.copy(quaternion).multiply(_tempQuaternion);

          if (Math.abs(_alignVector
                  .copy(_unitX)
                  .applyQuaternion(quaternion)
                  .dot(this.eye)) >
              0.9) {
            handle.visible = false;
          }
        }

        if (this.axis == 'Y') {
          _tempQuaternion.setFromEuler(
              _tempEuler.set(0, 0, Math.PI / 2), false);
          handle.quaternion.copy(quaternion).multiply(_tempQuaternion);

          if (Math.abs(_alignVector
                  .copy(_unitY)
                  .applyQuaternion(quaternion)
                  .dot(this.eye)) >
              0.9) {
            handle.visible = false;
          }
        }

        if (this.axis == 'Z') {
          _tempQuaternion.setFromEuler(
              _tempEuler.set(0, Math.PI / 2, 0), false);
          handle.quaternion.copy(quaternion).multiply(_tempQuaternion);

          if (Math.abs(_alignVector
                  .copy(_unitZ)
                  .applyQuaternion(quaternion)
                  .dot(this.eye)) >
              0.9) {
            handle.visible = false;
          }
        }

        if (this.axis == 'XYZE') {
          _tempQuaternion.setFromEuler(
              _tempEuler.set(0, Math.PI / 2, 0), false);
          _alignVector.copy(this.rotationAxis);
          handle.quaternion.setFromRotationMatrix(
              _lookAtMatrix.lookAt(_zeroVector, _alignVector, _unitY));
          handle.quaternion.multiply(_tempQuaternion);
          handle.visible = this.dragging;
        }

        if (this.axis == 'E') {
          handle.visible = false;
        }
      } else if (handle.name == 'START') {
        handle.position.copy(this.worldPositionStart);
        handle.visible = this.dragging;
      } else if (handle.name == 'END') {
        handle.position.copy(this.worldPosition);
        handle.visible = this.dragging;
      } else if (handle.name == 'DELTA') {
        handle.position.copy(this.worldPositionStart);
        handle.quaternion.copy(this.worldQuaternionStart);
        _tempVector
            .set(1e-10, 1e-10, 1e-10)
            .add(this.worldPositionStart)
            .sub(this.worldPosition)
            .multiplyScalar(-1);
        _tempVector
            .applyQuaternion(this.worldQuaternionStart.clone().invert());
        handle.scale.copy(_tempVector);
        handle.visible = this.dragging;
      } else {
        handle.quaternion.copy(quaternion);

        if (this.dragging) {
          handle.position.copy(this.worldPositionStart);
        } else {
          handle.position.copy(this.worldPosition);
        }

        if (this.axis != null) {
          handle.visible = this.axis!.indexOf(handle.name) != -1;
        }
      }

      // If updating helper, skip rest of the loop
      continue;
    }

    // Align handles to current local or world rotation

    handle.quaternion.copy(quaternion);

    if (this.mode == 'translate' || this.mode == 'scale') {
      // Hide translate and scale axis facing the camera

      var AXIS_HIDE_TRESHOLD = 0.99;
      var PLANE_HIDE_TRESHOLD = 0.2;

      if (handle.name == 'X') {
        if (Math.abs(_alignVector
                .copy(_unitX)
                .applyQuaternion(quaternion)
                .dot(this.eye)) >
            AXIS_HIDE_TRESHOLD) {
          handle.scale.set(1e-10, 1e-10, 1e-10);
          handle.visible = false;
        }
      }

      if (handle.name == 'Y') {
        if (Math.abs(_alignVector
                .copy(_unitY)
                .applyQuaternion(quaternion)
                .dot(this.eye)) >
            AXIS_HIDE_TRESHOLD) {
          handle.scale.set(1e-10, 1e-10, 1e-10);
          handle.visible = false;
        }
      }

      if (handle.name == 'Z') {
        if (Math.abs(_alignVector
                .copy(_unitZ)
                .applyQuaternion(quaternion)
                .dot(this.eye)) >
            AXIS_HIDE_TRESHOLD) {
          handle.scale.set(1e-10, 1e-10, 1e-10);
          handle.visible = false;
        }
      }

      if (handle.name == 'XY') {
        var ll = Math.abs(_alignVector
            .copy(_unitZ)
            .applyQuaternion(quaternion)
            .dot(this.eye));

        if (ll < PLANE_HIDE_TRESHOLD) {
          handle.scale.set(1e-10, 1e-10, 1e-10);
          handle.visible = false;
        }
      }

      if (handle.name == 'YZ') {
        if (Math.abs(_alignVector
                .copy(_unitX)
                .applyQuaternion(quaternion)
                .dot(this.eye)) <
            PLANE_HIDE_TRESHOLD) {
          handle.scale.set(1e-10, 1e-10, 1e-10);
          handle.visible = false;
        }
      }

      if (handle.name == 'XZ') {
        if (Math.abs(_alignVector
                .copy(_unitY)
                .applyQuaternion(quaternion)
                .dot(this.eye)) <
            PLANE_HIDE_TRESHOLD) {
          handle.scale.set(1e-10, 1e-10, 1e-10);
          handle.visible = false;
        }
      }
    } else if (this.mode == 'rotate') {
      // Align handles to current local or world rotation

      _tempQuaternion2.copy(quaternion);
      _alignVector
          .copy(this.eye)
          .applyQuaternion(_tempQuaternion.copy(quaternion).invert());

      if (handle.name.indexOf('E') != -1) {
        handle.quaternion.setFromRotationMatrix(
            _lookAtMatrix.lookAt(this.eye, _zeroVector, _unitY));
      }

      if (handle.name == 'X') {
        _tempQuaternion.setFromAxisAngle(
            _unitX, Math.atan2(-_alignVector.y, _alignVector.z));
        _tempQuaternion.multiplyQuaternions(
            _tempQuaternion2, _tempQuaternion);
        handle.quaternion.copy(_tempQuaternion);
      }

      if (handle.name == 'Y') {
        _tempQuaternion.setFromAxisAngle(
            _unitY, Math.atan2(_alignVector.x, _alignVector.z));
        _tempQuaternion.multiplyQuaternions(
            _tempQuaternion2, _tempQuaternion);
        handle.quaternion.copy(_tempQuaternion);
      }

      if (handle.name == 'Z') {
        _tempQuaternion.setFromAxisAngle(
            _unitZ, Math.atan2(_alignVector.y, _alignVector.x));
        _tempQuaternion.multiplyQuaternions(
            _tempQuaternion2, _tempQuaternion);
        handle.quaternion.copy(_tempQuaternion);
      }
    }

    // Hide disabled axes
    handle.visible =
        handle.visible && (handle.name.indexOf('X') == -1 || this.showX);
    handle.visible =
        handle.visible && (handle.name.indexOf('Y') == -1 || this.showY);
    handle.visible =
        handle.visible && (handle.name.indexOf('Z') == -1 || this.showZ);
    handle.visible = handle.visible &&
        (handle.name.indexOf('E') == -1 ||
            (this.showX && this.showY && this.showZ));

    // highlight selected axis

    handle.material.userData["_color"] =
        handle.material.userData["_color"] ?? handle.material.color.clone();
    handle.material.userData["_opacity"] =
        handle.material.userData["_opacity"] ?? handle.material.opacity;

    handle.material.color.copy(handle.material.userData["_color"]);
    handle.material.opacity = handle.material.userData["_opacity"];

    if (this.enabled && this.axis != null) {
      if (handle.name == this.axis) {
        handle.material.color.setHex(0xffff00);
        handle.material.opacity = 1.0;
      } else if (this
              .axis!
              .split('')
              .where((a) {
                return handle.name == a;
              })
              .toList()
              .length >
          0) {
        handle.material.color.setHex(0xffff00);
        handle.material.opacity = 1.0;
      }
    }
  }

  super.updateMatrixWorld(force);
}