<p dir="auto">glTF files assume that morph target data is specified as relative adjustments, and three.js assumes that the data in morph target buffers is absolute.</p>
<p dir="auto">This leads to a few obvious memory/performance caveats - the morph target data needs to be duplicated and modified during import - but also leads to inability to use a very narrow type for position deltas.</p>
<p dir="auto">For example, when data is quantized with gltfpack (which makes the glTF files technically invalid right now but this will change soon: <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="496845080" data-permission-text="Title is private" data-url="https://github.com/KhronosGroup/glTF/issues/1673" data-hovercard-type="pull_request" data-hovercard-url="/KhronosGroup/glTF/pull/1673/hovercard" href="https://github.com/KhronosGroup/glTF/pull/1673">KhronosGroup/glTF#1673</a>), the positions typically use UInt16 and morph target deltas use Int16. However, very frequently the morph target delta range is small enough to fit in Int8 - because three.js attempts to reconstruct the absolute position however, attempting to encode Int8 deltas leads to decoding issues on three.js side. Babylon.JS handles files like this perfectly.</p>
<p dir="auto">I'd like to fix this - the obvious tactical fix is changing the morph target attribute cloning to assume the type of the base attribute, not morph target. However, I'd like to check - what are the thoughts of fixing this by adding support to three.js for relative morph target data?</p>
<p dir="auto">In theory, the formulas are compatible to not require any shader code duplication - specifically, this equation that three.js currently uses:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="basePosition
+ weight0 * ( morphPosition0 - basePosition )
+ weight1 * ( morphPosition1 - basePosition )"><pre class="notranslate"><code class="notranslate">basePosition
+ weight0 * ( morphPosition0 - basePosition )
+ weight1 * ( morphPosition1 - basePosition )
</code></pre></div>
<p dir="auto">and this equation that glTF assumes:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="basePosition
+ weight0 * glTFmorphPosition0
+ weight1 * glTFmorphPosition1"><pre class="notranslate"><code class="notranslate">basePosition
+ weight0 * glTFmorphPosition0
+ weight1 * glTFmorphPosition1
</code></pre></div>
<p dir="auto">can be reformulated as:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="weightBase * basePosition
+ weight0 * morphPosition0
+ weight1 * morphPosition1"><pre class="notranslate"><code class="notranslate">weightBase * basePosition
+ weight0 * morphPosition0
+ weight1 * morphPosition1
</code></pre></div>
<p dir="auto">After which for glTF style files the shader needs <code class="notranslate">[1, weight0, weight1, ...]</code> as an input, whereas normally you'd pass <code class="notranslate">[1 - weight0 - weight1 - ..., weight0, weight1, ...]</code> as an input. So by adding some sort of flag to three.js mesh (e.g. <code class="notranslate">morphTargetsAreDeltas</code>) and a bit of JS code to compute the weights correctly, we could support both with minimal cost.</p>
<p dir="auto">Right now there is a parameter in the shaders that lets you render backfaces.  It does so by setting CCW and it inverts the normals:</p>
<p dir="auto">FlipSided changes CCW:</p>
<p dir="auto"><a href="https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L5285">https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L5285</a></p>
<p dir="auto">FlipSided also changes normal:</p>
<p dir="auto"><a href="https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/WebGLProgram.js#L140">https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/WebGLProgram.js#L140</a></p>
<p dir="auto"><a href="https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk.js#L1355">https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk.js#L1355</a></p>
<p dir="auto">But sometimes one has a negative scale in the transform matrix -- in DCC programs like 3DS Max, Maya, Softimage, etc, it means flip the object.  The way to do this is to have CCW set (as opposed to CW) but keep the normals the way they are (because they are already flipped by the matrix transform.)  To achieve this efficiently with ThreeJS it is necessary to be able to set CCW/CW independently of flipping the normals.</p>
<p dir="auto">Right now there is no flag that allows for CCW but without inverting the normals.  Can we add some option that enables this?</p>
<p dir="auto">Even if we had another option called FLIP_NORMAL/flipNormals that would just invert normals from whatever they are set via flipSided/FLIP_SIDED.  In our case we could set both flipSided and flipNormals to achieve our desired result.  This would be backwards compatible.</p>
<p dir="auto">We can make the PR if this is acceptable.</p>