其实原来的_updateFrame逻辑中是有处理mesh的情况,当时项目中并没有使用到mesh,所以我也就没有处理。
js 复制代码 _updateFrame () { this._indices.length = 0; let indices = this._indices, localVertices = this._localVertices; let indexOffset = 0, vfOffset = 0; let currentTextureData = this._textureData; if (!this._display || this._displayIndex < 0 || !currentTextureData || !currentTextureData.spriteFrame) return; let texture = currentTextureData.spriteFrame.getTexture(); let textureAtlasWidth = texture.width; let textureAtlasHeight = texture.height; let region = currentTextureData.region; const currentVerticesData = (this._deformVertices !== null && this._display === this._meshDisplay) ? this._deformVertices.verticesData : null; if (currentVerticesData) { const data = currentVerticesData.data; const intArray = data.intArray; const floatArray = data.floatArray; const vertexCount = intArray[currentVerticesData.offset + BinaryOffset.MeshVertexCount]; const triangleCount = intArray[currentVerticesData.offset + BinaryOffset.MeshTriangleCount]; let vertexOffset = intArray[currentVerticesData.offset + BinaryOffset.MeshFloatOffset]; if (vertexOffset < 0) { vertexOffset += 65536; // Fixed out of bouds bug. } const uvOffset = vertexOffset + vertexCount * 2; const scale = this._armature._armatureData.scale; for (let i = 0, l = vertexCount * 2; i < l; i += 2) { localVertices[vfOffset++] = floatArray[vertexOffset + i] * scale; // 顶点的x localVertices[vfOffset++] = -floatArray[vertexOffset + i + 1] * scale; // 顶点的y // 下边是处理uv,魔改时注意region应该是SpriteFrame的区域,let region = spriteFrame.getRect(); if (currentVerticesData.rotated) { localVertices[vfOffset++] = (region.x + (1.0 - floatArray[uvOffset + i]) * region.width) / textureAtlasWidth; localVertices[vfOffset++] = (region.y + floatArray[uvOffset + i + 1] * region.height) / textureAtlasHeight; } else { localVertices[vfOffset++] = (region.x + floatArray[uvOffset + i] * region.width) / textureAtlasWidth; localVertices[vfOffset++] = (region.y + floatArray[uvOffset + i + 1] * region.height) / textureAtlasHeight; } } // 顶点索引 for (let i = 0; i < triangleCount * 3; ++i) { indices[indexOffset++] = intArray[currentVerticesData.offset + BinaryOffset.MeshVertexIndices + i]; } localVertices.length = vfOffset; indices.length = indexOffset; let isSkinned = !!currentVerticesData.weight; if (isSkinned) { this._identityTransform(); } } }
详细的逻辑分析就不展开了,之前的文章有详细的解释。
Engine的mesh的更新逻辑如下
js 复制代码 _updateMesh () { const scale = this._armature._armatureData.scale; const deformVertices = this._deformVertices.vertices; const bones = this._deformVertices.bones; const verticesData = this._deformVertices.verticesData; const weightData = verticesData.weight; const hasDeform = deformVertices.length > 0 && verticesData.inheritDeform; let localVertices = this._localVertices; if (weightData) { const data = verticesData.data; const intArray = data.intArray; const floatArray = data.floatArray; const vertexCount = intArray[verticesData.offset + BinaryOffset.MeshVertexCount]; let weightFloatOffset = intArray[weightData.offset + BinaryOffset.WeigthFloatOffset]; if (weightFloatOffset < 0) { weightFloatOffset += 65536; // Fixed out of bouds bug. } for ( let i = 0, iB = weightData.offset + BinaryOffset.WeigthBoneIndices + bones.length, iV = weightFloatOffset, iF = 0, lvi = 0; i < vertexCount; i++, lvi+=4 ) { const boneCount = intArray[iB++]; let xG = 0.0, yG = 0.0; for (let j = 0; j < boneCount; ++j) { const boneIndex = intArray[iB++]; const bone = bones[boneIndex]; if (bone !== null) { const matrix = bone.globalTransformMatrix; const weight = floatArray[iV++]; let xL = floatArray[iV++] * scale; let yL = floatArray[iV++] * scale; if (hasDeform) { xL += deformVertices[iF++]; yL += deformVertices[iF++]; } xG += (matrix.a * xL + matrix.c * yL + matrix.tx) * weight; yG += (matrix.b * xL + matrix.d * yL + matrix.ty) * weight; } } localVertices[lvi] = xG; // lvi=0 localVertices[lvi + 1] = -yG;// lvi=1 } } else if (hasDeform) { const isSurface = this._parent._boneData.type !== BoneType.Bone; const data = verticesData.data; const intArray = data.intArray; const floatArray = data.floatArray; const vertexCount = intArray[verticesData.offset + BinaryOffset.MeshVertexCount]; let vertexOffset = intArray[verticesData.offset + BinaryOffset.MeshFloatOffset]; if (vertexOffset < 0) { vertexOffset += 65536; // Fixed out of bouds bug. } for (let i = 0, l = vertexCount, lvi = 0; i < l; i ++, lvi += 4) { const x = floatArray[vertexOffset + i*2] * scale + deformVertices[i*2]; const y = floatArray[vertexOffset + i*2 + 1] * scale + deformVertices[i*2 + 1]; if (isSurface) { const matrix = this._parent._getGlobalTransformMatrix(x, y); localVertices[lvi] = matrix.a * x + matrix.c * y + matrix.tx; localVertices[lvi + 1] = -matrix.b * x + matrix.d * y + matrix.ty; } else { localVertices[lvi] = x; localVertices[lvi + 1] = -y; } } } if (weightData) { this._identityTransform(); } },
我们的关注点还是落在localVertices上,可以看到lvi=0, lvi=1
0和1其实就是顶点的x,y,mesh动画的本质就是顶点坐标的变化。
这样想来,只需要在我们实现的setSpriteFrame中更新uv即可,将原来的uv位置套到SpriteFrame的区域即可。
借鉴Engine的_updateFrame
逻辑,去掉xy的计算,因为渲染前会每次调用我们写的这个函数,mesh的xy已经在渲染前计算好了,我们需要强制将uv桥接上即可,注意region
我注释中有详细的说明
顺便开发了一个顶点uv查看工具