通过重新排序正方形的四个角来旋转和翻转正方形(纹理四边形)



我有一个正方形,它的四个角从左上角开始按ccw顺序定义。所以我基本上有一个坐标数组
[TL,BL,BR,TR]
它用于2d纹理坐标,但这对问题影响不大
我想应用旋转90°,并水平和垂直翻转到这些坐标。我想通过指定一个"变换"来实现这一点,该"变换"保存左右90°旋转的次数以及h/v翻转的标志。然后,我想使用该变换将坐标复制到一个新的位置,并基于变换使用新的顺序。因此rot_0/xflip_0/yflip_1将导致
[TR,BR,TL,BL]
(我通常将翻转定义为沿命名轴的反射,但这只是命名的东西。)

如何在不将所有情况写在长列表中的情况下创建相应的坐标顺序?我对可以指定的90°旋转次数(3/4/unlimited)很灵活,我也可以使用多个不同的变换来获得相同的结果,或者使用只包含最低规格的选择器来覆盖所有可能的变换

达到所有最终状态所需的最小变换是什么?双向旋转和单轴翻转是否足够?

它看起来像

Math.abs(invert*3 - ((coord + rot) % 4)));

可以做到这一点
我们有四个角落和四个可以放置它们的插槽。这给出了一个基本的4!排列。但是,该集合的2/3不会导致纹理角的正确顺序。唯一可接受的顺序是四次旋转中的原始CCW顺序和四次旋转的反转CW顺序。这意味着我们需要四次旋转和沿着上方向向量的翻转才能达到所有变换
要计算旋转,只需移动/旋转阵列本身就足够了。因此,目标数组中的每个条目都变为coord+rot,为了保持循环,可以使用模4
要沿着向上矢量翻转,我们必须反转顺序,这可以通过3门来完成。如果我们想使用0/1反转参数,我们需要处理负值,因此使用abs()方法
问:有不同的方法来处理这个问题吗?一个不需要评估条件的公式

我不想每次更新纹理坐标时都评估abs()条件,也不想将变换后的纹理坐标存储在GPU之外的任何地方。因此,我最终用全部8个变换填满了一个短表。使用一个循环变得相当丑陋

for (int invert = 0; invert < 2; invert++)
    for (int shift = 0; shift < 4; shift++) {
        System.out.println("");
        for (int coord = 0; coord < 4; coord++) {
            System.out.print(Math.abs(invert*3 - ((coord + shift) % 4)));
        }
        System.out.println("");
    }

所以我简单地用8个转换手动初始化一个数组。

char texTransform[8 * 4] = {    0, 1, 2, 3,
                                1, 2, 3, 0,
                                2, 3, 0, 1,
                                3, 0, 1, 2,
                                3, 2, 1, 0,
                                2, 1, 0, 3,
                                1, 0, 3, 2,
                                0, 3, 2, 1
                        };

并且基于旋转和翻转参数来计算针对特定变换的查找。

public static int textureTransform(int rot, int flip){
    int tf = rot % 4 + (flip % 2) * 4;
    return ( tf >= 0 ) ? tf : 0;
}

然后,复制纹理坐标只需要根据变换索引参数查找角点顺序。(在我的情况下是JNI代码)

void nativeCopyFrameCoords(JNIEnv *env, jclass cl, jobject src, jint srcOffset, jobject dst,  jint dstOffset, jint tf)
  {
           float* pSrc = (float*) (*env)->GetDirectBufferAddress( env, src );
           float* pDst = (float*) (*env)->GetDirectBufferAddress( env, dst );
           char* selector = texTransform+tf*4;
           pDst[dstOffset +0] = pSrc[srcOffset + selector[0]*2];
           pDst[dstOffset +1] = pSrc[srcOffset + selector[0]*2 +1];
           pDst[dstOffset +2] = pSrc[srcOffset + selector[1]*2];
           pDst[dstOffset +3] = pSrc[srcOffset + selector[1]*2 +1];
           pDst[dstOffset +4] = pSrc[srcOffset + selector[2]*2];
           pDst[dstOffset +5] = pSrc[srcOffset + selector[2]*2 +1];
           pDst[dstOffset +6] = pSrc[srcOffset + selector[3]*2];
           pDst[dstOffset +7] = pSrc[srcOffset + selector[3]*2 +1];
  }

(如果不需要转换,则应使用对memcopy的调用,而不是逐个设置值。memcpy( &pDst[dstOffset], &pSrc[srcOffset], sizeof(float) * 8 );

最新更新