其实原来的_updateFrame逻辑中是有处理mesh的情况,当时项目中并没有使用到mesh,所以我也就没有处理。
_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的更新逻辑如下
_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查看工具