使用Media3 Transformer的Matrix.rotateM方法旋转图像异常原因排查
问题:Media3 Transformer中使用Matrix.rotateM旋转Overlay图像效果异常
我希望在单一平面内旋转图像,目前基于Media3 Transformer示例项目进行测试,编写了如下代码片段:
private OverlayEffect createOverlayEffectFromBundle(Bundle bundle, boolean[] selectedEffects) throws PackageManager.NameNotFoundException { ImmutableList.Builder<TextureOverlay> overlaysBuilder = new ImmutableList.Builder<>(); if (selectedEffects[ConfigurationActivity.OVERLAY_LOGO_AND_TIMER_INDEX]) { float[] logoPositioningMatrix = GlUtil.create4x4IdentityMatrix(); Matrix.translateM( logoPositioningMatrix, /* mOffset= */ 0, /* x= */ -0.95f, /* y= */ -0.95f, /* z= */ 1); // here I rotate 45 degrees around the Z axis Matrix.rotateM( logoPositioningMatrix,0, 45f,0f, 0f, 1f); OverlaySettings logoSettings = new OverlaySettings.Builder() .setMatrix(logoPositioningMatrix) .setAnchor(/* x= */ -1f, /* y= */ -1f) .build();
测试后发现,无旋转、绕Z轴旋转、绕X轴旋转、绕Y轴旋转的效果均不符合预期,请问为何使用Matrix.rotateM方法旋转图像会出现异常?
原因分析及解决方案
1. 矩阵变换顺序错误
当前代码先执行平移再旋转,旋转会基于原始坐标系原点(画面中心)进行,而非你期望的Overlay锚点位置,导致旋转后Overlay的位置偏移异常。正确的2D平面旋转逻辑应该是先旋转,再平移——让旋转围绕Overlay自身锚点完成后,再移动到目标位置。
2. 锚点与坐标系的匹配问题
Media3 Overlay设置的setAnchor(-1f, -1f)对应画面左下角,但Matrix.rotateM默认以坐标系原点(画面中心)为旋转基准。要让旋转围绕锚点生效,需要先将坐标系临时平移到锚点位置,旋转后再平移回原坐标系,最后执行目标位置的平移。
3. 3D旋转的误用
你要实现的是单一平面内的2D旋转,绕Z轴旋转是正确选择,但绕X/Y轴属于3D空间旋转,会导致Overlay出现透视变形(比如测试中的绕X/Y轴效果),这本身就不符合2D平面旋转的预期。
修正后的代码示例
private OverlayEffect createOverlayEffectFromBundle(Bundle bundle, boolean[] selectedEffects) throws PackageManager.NameNotFoundException { ImmutableList.Builder<TextureOverlay> overlaysBuilder = new ImmutableList.Builder<>(); if (selectedEffects[ConfigurationActivity.OVERLAY_LOGO_AND_TIMER_INDEX]) { float[] logoPositioningMatrix = GlUtil.create4x4IdentityMatrix(); // 1. 临时平移到锚点对应的坐标系原点(让旋转围绕锚点进行) Matrix.translateM(logoPositioningMatrix, 0, 1f, 1f, 0); // 2. 执行2D平面旋转(绕Z轴45度) Matrix.rotateM(logoPositioningMatrix, 0, 45f, 0f, 0f, 1f); // 3. 平移回原坐标系,再移动到目标位置 Matrix.translateM(logoPositioningMatrix, 0, -1f - 0.95f, -1f - 0.95f, 1); OverlaySettings logoSettings = new OverlaySettings.Builder() .setMatrix(logoPositioningMatrix) .setAnchor(/* x= */ -1f, /* y= */ -1f) .build();
额外说明
Media3的OverlaySettings矩阵采用OpenGL齐次坐标系,所有变换操作遵循从右到左的执行顺序(代码中写的操作顺序是逆序),因此必须严格控制变换步骤的顺序,否则会出现偏移、旋转中心错误等异常。
内容的提问来源于stack exchange,提问作者Arseni Hlaz
相关产品推荐
相关产品推荐

