<h5 dir="auto">Description of the problem</h5>
<p dir="auto">I think this implementation of Vector3.prototype.projectOnVector:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="projectOnVector = function ( vector ) {
    var length = vector.length();
    var scalar = this.dot(vector) / (length * length);
    return vector.multiplyScalar(scalar);
};"><pre class="notranslate"><code class="notranslate">projectOnVector = function ( vector ) {
    var length = vector.length();
    var scalar = this.dot(vector) / (length * length);
    return vector.multiplyScalar(scalar);
};
</code></pre></div>
<p dir="auto">would be significantly faster than the current implementation:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="projectOnVector: function () {
    var v1, dot;
    return function projectOnVector( vector ) {
        if ( v1 === undefined ) v1 = new THREE.Vector3();
        v1.copy( vector ).normalize();
        dot = this.dot( v1 );
        return this.copy( v1 ).multiplyScalar( dot );
    };
}()"><pre class="notranslate"><code class="notranslate">projectOnVector: function () {
    var v1, dot;
    return function projectOnVector( vector ) {
        if ( v1 === undefined ) v1 = new THREE.Vector3();
        v1.copy( vector ).normalize();
        dot = this.dot( v1 );
        return this.copy( v1 ).multiplyScalar( dot );
    };
}()
</code></pre></div>
<p dir="auto">The allocation of a temporary Vector3 is stripped away, and it uses two function calls less.</p>
<h5 dir="auto">Three.js version</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Dev</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> r77</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> r73</li>
</ul>
<h5 dir="auto">Browser</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Chrome</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Firefox</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Internet Explorer</li>
</ul>
<h5 dir="auto">OS</h5>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> All of them</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Windows</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Linux</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> Android</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> IOS</li>
</ul>
<h5 dir="auto">Hardware Requirements (graphics card, VR Device, ...)</h5>
<h5 dir="auto">Description of the problem</h5>
<p dir="auto">At the moment, the <code class="notranslate">Object3D.updateMatrix</code> method,</p>
<p dir="auto"></p><div class="Box Box--condensed my-2">
  <div class="Box-header f6">
    <p class="mb-0 text-bold">
      <a href="https://github.com/mrdoob/three.js/blob/f55b3d3b91b0f50c28523ed707baec91ddff465a/src/core/Object3D.js#L592-L598">three.js/src/core/Object3D.js</a>
    </p>
    <p class="mb-0 color-fg-muted">
        Lines 592 to 598
      in
      <a data-pjax="true" class="commit-tease-sha" href="/mrdoob/three.js/commit/f55b3d3b91b0f50c28523ed707baec91ddff465a">f55b3d3</a>
    </p>
  </div>
  <div itemprop="text" class="Box-body p-0 blob-wrapper blob-wrapper-embedded data">
    <table class="highlight tab-size mb-0 js-file-line-container" data-tab-size="8" data-paste-markdown-skip="">

        <tbody><tr class="border-0">
          <td id="L592" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="592"></td>
          <td id="LC592" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-en">updateMatrix</span>: <span class="pl-k">function</span> <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L593" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="593"></td>
          <td id="LC593" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">  </td>
        </tr>

        <tr class="border-0">
          <td id="L594" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="594"></td>
          <td id="LC594" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> 	<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">matrix</span><span class="pl-kos">.</span><span class="pl-en">compose</span><span class="pl-kos">(</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">position</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">quaternion</span><span class="pl-kos">,</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">scale</span> <span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L595" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="595"></td>
          <td id="LC595" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">  </td>
        </tr>

        <tr class="border-0">
          <td id="L596" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="596"></td>
          <td id="LC596" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> 	<span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">matrixWorldNeedsUpdate</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L597" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="597"></td>
          <td id="LC597" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">  </td>
        </tr>

        <tr class="border-0">
          <td id="L598" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="598"></td>
          <td id="LC598" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-kos">}</span><span class="pl-kos">,</span> </td>
        </tr>
    </tbody></table>
  </div>
</div>
<p></p>
<p dir="auto">always causes <code class="notranslate">this.matrixWorldNeedsUpdate</code> to be true.</p>
<p dir="auto">Instead it can set that to true only if the resulting composition results in a changed local matrix.</p>
<p dir="auto">Would detecting a change be cheaper than just always multiplying the parent world matrix? My gut feeling is that it would be.</p>