<commit_before>import { threshold } from '../math/Math.js';

const NODES_NEEDING_MATRIX_UPDATE = new Set();

export default class GLTFAnimation {
  constructor({
    data,
  }) {
    this._channels = data.channels;
    this._duration = 0;

    for (const channel of data.channels) {
      this._duration = Math.max(this._duration, channel.sampler.input[channel.sampler.input.length - 1]);
    }

    this.currentTime = 0;
  }

  get duration() {
    return this._duration;
  }

  get currentTime() {
    return this._currentTime;
  }

  set currentTime(value) {
    if (this._currentTime === value) {
      return;
    }
    this._currentTime = value;
    NODES_NEEDING_MATRIX_UPDATE.clear();

    for (const channel of this._channels) {
      const node = channel.target.node;
      const inputArray = channel.sampler.input;
      const outputArray = channel.sampler.output;
      let nextIndex = 0;
      const time = Math.min(this._currentTime, inputArray[inputArray.length - 1]);
      while (time > inputArray[nextIndex]) {
        nextIndex++;
      }
      const previousIndex = !nextIndex ? 0 : nextIndex - 1;
      const alpha = threshold(inputArray[previousIndex], inputArray[nextIndex], this._currentTime);
      if (channel.target.path === 'translation' || channel.target.path === 'scale') {
        const previousValue = outputArray.subarray(previousIndex * 3, previousIndex * 3 + 3);
        const nextValue = outputArray.subarray(nextIndex * 3, nextIndex * 3 + 3);
        node[channel.target.path].copy(previousValue).lerp(nextValue, alpha);
        NODES_NEEDING_MATRIX_UPDATE.add(node);
      } else if (channel.target.path === 'rotation') {
        const previousValue = outputArray.subarray(previousIndex * 4, previousIndex * 4 + 4);
        const nextValue = outputArray.subarray(nextIndex * 4, nextIndex * 4 + 4);
        node.rotation.copy(previousValue).slerp(nextValue, alpha);
        NODES_NEEDING_MATRIX_UPDATE.add(node);
      } else if (channel.target.path === 'weights') {
        const length = node.weights.length;
        const previousValue = outputArray.subarray(previousIndex * length, previousIndex * length + length);
        const nextValue = outputArray.subarray(nextIndex * length, nextIndex * length + length);
        for (let index = 0; index < node.weights.length; index++) {
          node.weights[index] = previousValue[index] + (nextValue[index] - previousValue[index]) * alpha;
        }
      }
    }

    for (const node of NODES_NEEDING_MATRIX_UPDATE) {
      node.matrix.fromTranslationRotationScale(node.translation, node.rotation, node.scale);
    }
  }
}<commit_msg>GLTFAnimation: small adds<commit_after>import { threshold } from '../math/Math.js';

const NODES_NEEDING_MATRIX_UPDATE = new Set();

export default class GLTFAnimation {
  constructor({
    data,
  }) {
    this.name = data.name;
    this.channels = data.channels;
    this.samplers = data.samplers;

    this._duration = 0;

    for (const channel of this.channels) {
      this._duration = Math.max(this._duration, channel.sampler.input[channel.sampler.input.length - 1]);
    }

    this.currentTime = 0;
  }

  get duration() {
    return this._duration;
  }

  get currentTime() {
    return this._currentTime;
  }

  set currentTime(value) {
    if (this._currentTime === value) {
      return;
    }
    this._currentTime = value;
    NODES_NEEDING_MATRIX_UPDATE.clear();

    for (const channel of this.channels) {
      const node = channel.target.node;
      const inputArray = channel.sampler.input;
      const outputArray = channel.sampler.output;
      let nextIndex = 0;
      const time = Math.min(this._currentTime, inputArray[inputArray.length - 1]);
      while (time > inputArray[nextIndex]) {
        nextIndex++;
      }
      const previousIndex = !nextIndex ? 0 : nextIndex - 1;
      const alpha = threshold(inputArray[previousIndex], inputArray[nextIndex], this._currentTime);
      if (channel.target.path === 'translation' || channel.target.path === 'scale') {
        const previousValue = outputArray.subarray(previousIndex * 3, previousIndex * 3 + 3);
        const nextValue = outputArray.subarray(nextIndex * 3, nextIndex * 3 + 3);
        node[channel.target.path].copy(previousValue).lerp(nextValue, alpha);
        NODES_NEEDING_MATRIX_UPDATE.add(node);
      } else if (channel.target.path === 'rotation') {
        const previousValue = outputArray.subarray(previousIndex * 4, previousIndex * 4 + 4);
        const nextValue = outputArray.subarray(nextIndex * 4, nextIndex * 4 + 4);
        node.rotation.copy(previousValue).slerp(nextValue, alpha);
        NODES_NEEDING_MATRIX_UPDATE.add(node);
      } else if (channel.target.path === 'weights') {
        const length = node.weights.length;
        const previousValue = outputArray.subarray(previousIndex * length, previousIndex * length + length);
        const nextValue = outputArray.subarray(nextIndex * length, nextIndex * length + length);
        for (let index = 0; index < node.weights.length; index++) {
          node.weights[index] = previousValue[index] + (nextValue[index] - previousValue[index]) * alpha;
        }
      }
    }

    for (const node of NODES_NEEDING_MATRIX_UPDATE) {
      if (node.matrix) node.matrix.fromTranslationRotationScale(node.translation, node.rotation, node.scale);
    }
  }
}
{'fraction_non_alphanumeric': 0.12106446776611694, 'fraction_numerical': 0.0074962518740629685, 'mean_word_length': 3.134004647560031, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3202361', 'n_tokens_mistral': 1643, 'n_tokens_neox': 1582, 'n_words': 342}