SkMatrix44 equivilants for SkM44

16 views
Skip to first unread message

Clark Kent

unread,
Sep 8, 2022, 2:00:41 AMSep 8
to skia-discuss
what would the SkM44 equivilants of the following SkMatrix44 functions be?

    /** Rotate about the vector [x,y,z]. If that vector is not unit-length,
        it will be automatically resized.
     */
    void setRotateAbout(SkScalar x, SkScalar y, SkScalar z, SkScalar radians);

    /** Rotate about the vector [x,y,z]. Does not check the length of the
        vector, assuming it is unit-length.
     */
    void setRotateAboutUnit(SkScalar x, SkScalar y, SkScalar z, SkScalar radians);

    /** Apply the matrix to the src vector, returning the new vector in dst.
        It is legal for src and dst to point to the same memory.
     */
    void mapScalars(const SkScalar src[4], SkScalar dst[4]) const;

    /**
     *  map an array of [x, y, 0, 1] through the matrix, returning an array
     *  of [x', y', z', w'].
     *
     *  @param src2     array of [x, y] pairs, with implied z=0 and w=1
     *  @param count    number of [x, y] pairs in src2
     *  @param dst4     array of [x', y', z', w'] quads as the output.
     */
    void map2(const float src2[], int count, float dst4[]) const;
    void map2(const double src2[], int count, double dst4[]) const;

    /** Returns true if transformating an axis-aligned square in 2d by this matrix
        will produce another 2d axis-aligned square; typically means the matrix
        is a scale with perhaps a 90-degree rotation. A 3d rotation through 90
        degrees into a perpendicular plane collapses a square to a line, but
        is still considered to be axis-aligned.

        By default, tolerates very slight error due to float imprecisions;
        a 90-degree rotation can still end up with 10^-17 of
        "non-axis-aligned" result.
     */
    bool preserves2dAxisAlignment(SkScalar epsilon = SK_ScalarNearlyZero) const;

    double determinant() const;

Clark Kent

unread,
Sep 8, 2022, 2:36:35 AMSep 8
to skia-discuss
and set3x3RowMajorf

Clark Kent

unread,
Sep 8, 2022, 3:14:46 AMSep 8
to skia-discuss
can i just rip the old SkMatrix44 .h and .cpp file and write a from/To M44 function ?

Clark Kent

unread,
Sep 8, 2022, 4:21:12 AMSep 8
to skia-discuss

Michael Ludwig

unread,
Sep 8, 2022, 10:28:14 AMSep 8
to skia-discuss
SkM44 has a setRotate() and a setRotateUnit() function that takes an SkV3 and a float radians. This is equivalent to SkMatrix44::setRotateAbout() except that the vector is stored in a SkV3 instead of 3 separate parameters.

You can easily implement map2() and mapScalars() functionality using either the map(x,y,z,w) function or the * operator that takes an SkV4. You are just responsible for supplying w = 1 and z = 0, as well as handling the iteration.

For something with complex implications like preserves2dAxisAlignment(), we would prefer not to expose our own definition of that because what we deem acceptable may not be right for the caller's use case, either too strict or not strict enough. From a mathematical sense, a 2D axis-alignment preserving 4x4 matrix will either be of the form:

[sx  0 0 tx]
[ 0 sy 0 ty]
[ 0  0  1  0]
[ 0  0  0  1]

or

[ 0 sy 0 tx]
[sx 0 0  ty]
[ 0  0  1  0]
[ 0  0  0  1]

It's entirely depend on your requirements whether or not you allow the 0's and the 1's to be epsilon close, or bit exact, or whether or not you handle the 90 degree rotations, or negative scale factors.

Clark Kent

unread,
Sep 8, 2022, 11:01:14 PMSep 8
to skia-discuss
hmmm alright

how would i use SKV3 and SKV4?

Michael Ludwig

unread,
Sep 9, 2022, 9:17:31 AMSep 9
to skia-d...@googlegroups.com
They are just simple structs defined in SkM44.h that represent a 3D or 4D vector, so you can construct one like SkV3{x,y,z} or SkV4{x, y, 0, 1}, etc.

--
You received this message because you are subscribed to a topic in the Google Groups "skia-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/skia-discuss/NFKd_JYEZwI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to skia-discuss...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/skia-discuss/eec76cac-1886-4630-b9c0-ac6d7dcc417en%40googlegroups.com.

Clark Kent

unread,
Sep 9, 2022, 10:10:02 AMSep 9
to skia-discuss
so we can get identical behaviour by using


void sk_m44_set_rotate_about_degrees(sk_m44_t* matrix, float x, float y, float z, float degrees) {
    sk_m44_set_rotate_about_radians(matrix, x, y, z, degrees * SK_ScalarPI / 180);
}

void sk_m44_set_rotate_about_radians(sk_m44_t* matrix, float x, float y, float z, float radians) {
    SkM44* m44 = AsM44(matrix);
    m44->setRotate(SkV3{ x, y, z }, radians);
}

void sk_m44_set_rotate_about_radians_unit(sk_m44_t* matrix, float x, float y, float z, float radians) {
    SkM44* m44 = AsM44(matrix);
    m44->setRotateUnit(SkV3{ x, y, z }, radians);
}


instead of


void sk_m44_set_rotate_about_degrees(sk_m44_t* matrix, float x, float y, float z, float degrees) {
    sk_m44_set_rotate_about_radians(matrix, x, y, z, degrees * SK_ScalarPI / 180);
}

void sk_m44_set_rotate_about_radians(sk_m44_t* matrix, float x, float y, float z, float radians) {
    double len2 = (double)x * x + (double)y * y + (double)z * z;
    if (1 != len2) {
        if (0 == len2) {
            AsM44(matrix)->setIdentity();
            return;
        }
        double scale = 1 / sqrt(len2);
        x = SkScalar(x * scale);
        y = SkScalar(y * scale);
        z = SkScalar(z * scale);
    }
    sk_m44_set_rotate_about_radians_unit(matrix, x, y, z, radians);
}

void set3x3(SkM44* m44, SkScalar m_00, SkScalar m_10, SkScalar m_20,
    SkScalar m_01, SkScalar m_11, SkScalar m_21,
    SkScalar m_02, SkScalar m_12, SkScalar m_22) {
    SMAT4(0, 0), m_00); SMAT4(0, 1), m_10); SMAT4(0, 2), m_20); SMAT4(0, 3), 0);
    SMAT4(1, 0), m_01); SMAT4(1, 1), m_11); SMAT4(1, 2), m_21); SMAT4(1, 3), 0);
    SMAT4(2, 0), m_02); SMAT4(2, 1), m_12); SMAT4(2, 2), m_22); SMAT4(2, 3), 0);
    SMAT4(3, 0), 0);    SMAT4(3, 1), 0);    SMAT4(3, 2), 0);    SMAT4(3, 3), 1);
}

void sk_m44_set_rotate_about_radians_unit(sk_m44_t* matrix, float x, float y, float z, float radians) {
    double c = cos(radians);
    double s = sin(radians);
    double C = 1 - c;
    double xs = x * s;
    double ys = y * s;
    double zs = z * s;
    double xC = x * C;
    double yC = y * C;
    double zC = z * C;
    double xyC = x * yC;
    double yzC = y * zC;
    double zxC = z * xC;

    // if you're looking at wikipedia, remember that we're column major.
    SkM44* m44 = AsM44(matrix);
    set3x3(m44,  SkScalar(x * xC + c),     // scale x
                 SkScalar(xyC + zs),       // skew x
                 SkScalar(zxC - ys),       // trans x

                 SkScalar(xyC - zs),       // skew y
                 SkScalar(y * yC + c),     // scale y
                 SkScalar(yzC + xs),       // trans y

                 SkScalar(zxC + ys),       // persp x
                 SkScalar(yzC - xs),       // persp y
                 SkScalar(z * zC + c));    // persp 2
}

?
Reply all
Reply to author
Forward
0 new messages