/**
         * @param world
         * @param vertex
         * @param o_para
         * @
         */
        private bool get_cpara(NyARIntPoint2d[] i_vertex, NyARMat o_para)
        {
            double[][] world = CPARAM_WORLD;
            NyARMat a = wk_get_cpara_a;// 次処理で値を設定するので、初期化不要// new NyARMat( 8, 8 );
            double[][] a_array = a.getArray();
            NyARMat b = wk_get_cpara_b;// 次処理で値を設定するので、初期化不要// new NyARMat( 8, 1 );
            double[][] b_array = b.getArray();
            double[] a_pt0, a_pt1;
            double[] world_pti;

            for (int i = 0; i < 4; i++)
            {
                a_pt0 = a_array[i * 2];
                a_pt1 = a_array[i * 2 + 1];
                world_pti = world[i];

                a_pt0[0] = (double)world_pti[0];// a->m[i*16+0] = world[i][0];
                a_pt0[1] = (double)world_pti[1];// a->m[i*16+1] = world[i][1];
                a_pt0[2] = 1.0;// a->m[i*16+2] = 1.0;
                a_pt0[3] = 0.0;// a->m[i*16+3] = 0.0;
                a_pt0[4] = 0.0;// a->m[i*16+4] = 0.0;
                a_pt0[5] = 0.0;// a->m[i*16+5] = 0.0;
                a_pt0[6] = (double)(-world_pti[0] * i_vertex[i].x);// a->m[i*16+6]= -world[i][0]*vertex[i][0];
                a_pt0[7] = (double)(-world_pti[1] * i_vertex[i].x);// a->m[i*16+7]=-world[i][1]*vertex[i][0];
                a_pt1[0] = 0.0;// a->m[i*16+8] = 0.0;
                a_pt1[1] = 0.0;// a->m[i*16+9] = 0.0;
                a_pt1[2] = 0.0;// a->m[i*16+10] = 0.0;
                a_pt1[3] = (double)world_pti[0];// a->m[i*16+11] = world[i][0];
                a_pt1[4] = (double)world_pti[1];// a->m[i*16+12] = world[i][1];
                a_pt1[5] = 1.0;// a->m[i*16+13] = 1.0;
                a_pt1[6] = (double)(-world_pti[0] * i_vertex[i].y);// a->m[i*16+14]=-world[i][0]*vertex[i][1];
                a_pt1[7] = (double)(-world_pti[1] * i_vertex[i].y);// a->m[i*16+15]=-world[i][1]*vertex[i][1];
                b_array[i * 2 + 0][0] = (double)i_vertex[i].x;// b->m[i*2+0] =vertex[i][0];
                b_array[i * 2 + 1][0] = (double)i_vertex[i].y;// b->m[i*2+1] =vertex[i][1];
            }
            if (!a.inverse())
            {
                return false;
            }

            o_para.mul(a, b);
            return true;
        }
Esempio n. 2
0
        /// <summary>
        /// Returns a right-handed perspective transformation matrix built from the camera calibration data.
        /// </summary>
        /// <param name="arParameters">The camera calibration data.</param>
        /// <param name="nearPlane">The near view plane of the frustum.</param>
        /// <param name="farPlane">The far view plane of the frustum.</param>
        /// <returns>The projection matrix.</returns>
        internal static Matrix3D GetCameraFrustumRH(this NyARParam arParameters, double nearPlane, double farPlane)
        {
            NyARMat transformation = new NyARMat(3, 4);
            NyARMat icParameters   = new NyARMat(3, 4);

            double[,] p = new double[3, 3];
            double[,] q = new double[4, 4];

            NyARIntSize size   = arParameters.getScreenSize();
            int         width  = size.w;
            int         height = size.h;

            arParameters.getPerspectiveProjectionMatrix().decompMat(icParameters, transformation);

            double[][] icpara = icParameters.getArray();
            double[][] trans  = transformation.getArray();
            for (int i = 0; i < 4; i++)
            {
                icpara[1][i] = (height - 1) * (icpara[2][i]) - icpara[1][i];
            }

            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    p[i, j] = icpara[i][j] / icpara[2][2];
                }
            }

            q[0, 0] = (2.0 * p[0, 0] / (width - 1));
            q[0, 1] = (2.0 * p[0, 1] / (width - 1));
            q[0, 2] = ((2.0 * p[0, 2] / (width - 1)) - 1.0);
            q[0, 3] = 0.0;

            q[1, 0] = 0.0;
            q[1, 1] = -(2.0 * p[1, 1] / (height - 1));
            q[1, 2] = -((2.0 * p[1, 2] / (height - 1)) - 1.0);
            q[1, 3] = 0.0;

            q[2, 0] = 0.0;
            q[2, 1] = 0.0;
            q[2, 2] = (farPlane + nearPlane) / (nearPlane - farPlane);
            q[2, 3] = 2.0 * farPlane * nearPlane / (nearPlane - farPlane);

            q[3, 0] = 0.0;
            q[3, 1] = 0.0;
            q[3, 2] = -1.0;
            q[3, 3] = 0.0;

            return(new Matrix3D(q[0, 0] * trans[0][0] + q[0, 1] * trans[1][0] + q[0, 2] * trans[2][0],
                                q[1, 0] * trans[0][0] + q[1, 1] * trans[1][0] + q[1, 2] * trans[2][0],
                                q[2, 0] * trans[0][0] + q[2, 1] * trans[1][0] + q[2, 2] * trans[2][0],
                                q[3, 0] * trans[0][0] + q[3, 1] * trans[1][0] + q[3, 2] * trans[2][0],
                                q[0, 0] * trans[0][1] + q[0, 1] * trans[1][1] + q[0, 2] * trans[2][1],
                                q[1, 0] * trans[0][1] + q[1, 1] * trans[1][1] + q[1, 2] * trans[2][1],
                                q[2, 0] * trans[0][1] + q[2, 1] * trans[1][1] + q[2, 2] * trans[2][1],
                                q[3, 0] * trans[0][1] + q[3, 1] * trans[1][1] + q[3, 2] * trans[2][1],
                                q[0, 0] * trans[0][2] + q[0, 1] * trans[1][2] + q[0, 2] * trans[2][2],
                                q[1, 0] * trans[0][2] + q[1, 1] * trans[1][2] + q[1, 2] * trans[2][2],
                                q[2, 0] * trans[0][2] + q[2, 1] * trans[1][2] + q[2, 2] * trans[2][2],
                                q[3, 0] * trans[0][2] + q[3, 1] * trans[1][2] + q[3, 2] * trans[2][2],
                                q[0, 0] * trans[0][3] + q[0, 1] * trans[1][3] + q[0, 2] * trans[2][3] + q[0, 3],
                                q[1, 0] * trans[0][3] + q[1, 1] * trans[1][3] + q[1, 2] * trans[2][3] + q[1, 3],
                                q[2, 0] * trans[0][3] + q[2, 1] * trans[1][3] + q[2, 2] * trans[2][3] + q[2, 3],
                                q[3, 0] * trans[0][3] + q[3, 1] * trans[1][3] + q[3, 2] * trans[2][3] + q[3, 3]));
        }
        //分割数16未満になると少し遅くなるかも。
        private void updateExtpat(INyARRgbRaster image, NyARMat i_cpara, int i_xdiv2, int i_ydiv2)
        {
            int i, j;
            int r, g, b;
            //ピクセルリーダーを取得
            int    pat_size_w  = this._size.w;
            int    xdiv        = i_xdiv2 / pat_size_w;   // xdiv = xdiv2/Config.AR_PATT_SIZE_X;
            int    ydiv        = i_ydiv2 / this._size.h; // ydiv = ydiv2/Config.AR_PATT_SIZE_Y;
            int    xdiv_x_ydiv = xdiv * ydiv;
            double reciprocal;

            double[][] para   = i_cpara.getArray();
            double     para00 = para[0 * 3 + 0][0];
            double     para01 = para[0 * 3 + 1][0];
            double     para02 = para[0 * 3 + 2][0];
            double     para10 = para[1 * 3 + 0][0];
            double     para11 = para[1 * 3 + 1][0];
            double     para12 = para[1 * 3 + 2][0];
            double     para20 = para[2 * 3 + 0][0];
            double     para21 = para[2 * 3 + 1][0];

            INyARRgbPixelDriver reader = image.getRgbPixelDriver();
            int img_width  = image.getWidth();
            int img_height = image.getHeight();

            //ワークバッファの準備
            reservWorkBuffers(xdiv, ydiv);
            double[] xw      = this.__updateExtpat_xw;
            double[] yw      = this.__updateExtpat_yw;
            int[]    xc      = this.__updateExtpat_xc;
            int[]    yc      = this.__updateExtpat_yc;
            int[]    rgb_set = this.__updateExtpat_rgbset;


            for (int iy = this._size.h - 1; iy >= 0; iy--)
            {
                for (int ix = pat_size_w - 1; ix >= 0; ix--)
                {
                    //xw,ywマップを作成
                    reciprocal = 1.0 / i_xdiv2;
                    for (i = xdiv - 1; i >= 0; i--)
                    {
                        xw[i] = LT_POS + SQ_SIZE * (ix * xdiv + i + 0.5) * reciprocal;
                    }
                    reciprocal = 1.0 / i_ydiv2;
                    for (i = ydiv - 1; i >= 0; i--)
                    {
                        yw[i] = LT_POS + SQ_SIZE * (iy * ydiv + i + 0.5) * reciprocal;
                    }
                    //1ピクセルを構成するピクセル座標の集合をxc,yc配列に取得
                    int number_of_pix = 0;
                    for (i = ydiv - 1; i >= 0; i--)
                    {
                        double para01_x_yw_para02 = para01 * yw[i] + para02;
                        double para11_x_yw_para12 = para11 * yw[i] + para12;
                        double para12_x_yw_para22 = para21 * yw[i] + 1.0;
                        for (j = xdiv - 1; j >= 0; j--)
                        {
                            double d = para20 * xw[j] + para12_x_yw_para22;
                            if (d == 0)
                            {
                                throw new NyARException();
                            }
                            int xcw = (int)((para00 * xw[j] + para01_x_yw_para02) / d);
                            int ycw = (int)((para10 * xw[j] + para11_x_yw_para12) / d);
                            if (xcw < 0 || xcw >= img_width || ycw < 0 || ycw >= img_height)
                            {
                                continue;
                            }
                            xc[number_of_pix] = xcw;
                            yc[number_of_pix] = ycw;
                            number_of_pix++;
                        }
                    }
                    //1ピクセル分の配列を取得
                    reader.getPixelSet(xc, yc, number_of_pix, rgb_set);
                    r = g = b = 0;
                    for (i = number_of_pix * 3 - 1; i >= 0; i -= 3)
                    {
                        r += rgb_set[i - 2]; // R
                        g += rgb_set[i - 1]; // G
                        b += rgb_set[i];     // B
                    }
                    //1ピクセル確定
                    this._patdata[iy * pat_size_w + ix] = (((r / xdiv_x_ydiv) & 0xff) << 16) | (((g / xdiv_x_ydiv) & 0xff) << 8) | (((b / xdiv_x_ydiv) & 0xff));
                }
            }
            return;
        }
        /**
         * この関数は、ラスタのi_vertexsで定義される四角形からパターンを取得して、インスタンスに格納します。
         */
        public override bool pickFromRaster(INyARRgbRaster image, NyARIntPoint2d[] i_vertexs)
        {
            NyARMat cpara = this.wk_pickFromRaster_cpara;
            // xdiv2,ydiv2の計算
            int xdiv2, ydiv2;
            int l1, l2;
            int w1, w2;

            // x計算
            w1 = i_vertexs[0].x - i_vertexs[1].x;
            w2 = i_vertexs[0].y - i_vertexs[1].y;
            l1 = (w1 * w1 + w2 * w2);
            w1 = i_vertexs[2].x - i_vertexs[3].x;
            w2 = i_vertexs[2].y - i_vertexs[3].y;
            l2 = (w1 * w1 + w2 * w2);
            if (l2 > l1)
            {
                l1 = l2;
            }
            l1    = l1 / 4;
            xdiv2 = this._size.w;
            while (xdiv2 * xdiv2 < l1)
            {
                xdiv2 *= 2;
            }
            if (xdiv2 > AR_PATT_SAMPLE_NUM)
            {
                xdiv2 = AR_PATT_SAMPLE_NUM;
            }

            // y計算
            w1 = i_vertexs[1].x - i_vertexs[2].x;
            w2 = i_vertexs[1].y - i_vertexs[2].y;
            l1 = (w1 * w1 + w2 * w2);
            w1 = i_vertexs[3].x - i_vertexs[0].x;
            w2 = i_vertexs[3].y - i_vertexs[0].y;
            l2 = (w1 * w1 + w2 * w2);
            if (l2 > l1)
            {
                l1 = l2;
            }
            ydiv2 = this._size.h;
            l1    = l1 / 4;
            while (ydiv2 * ydiv2 < l1)
            {
                ydiv2 *= 2;
            }
            if (ydiv2 > AR_PATT_SAMPLE_NUM)
            {
                ydiv2 = AR_PATT_SAMPLE_NUM;
            }

            // cparaの計算
            if (!get_cpara(i_vertexs, cpara))
            {
                return(false);
            }
            updateExtpat(image, cpara, xdiv2, ydiv2);

            return(true);
        }
Esempio n. 5
0
        public static void toCameraFrustumRH(NyARParam i_arparam, double i_near, double i_far, ref Matrix o_d3d_projection)
        {
            NyARMat trans_mat  = new NyARMat(3, 4);
            NyARMat icpara_mat = new NyARMat(3, 4);

            double[,] p = new double[3, 3], q = new double[4, 4];
            int width, height;
            int i, j;

            NyARIntSize size = i_arparam.getScreenSize();

            width  = size.w;
            height = size.h;

            i_arparam.getPerspectiveProjectionMatrix().decompMat(icpara_mat, trans_mat);

            double[][] icpara = icpara_mat.getArray();
            double[][] trans  = trans_mat.getArray();
            for (i = 0; i < 4; i++)
            {
                icpara[1][i] = (height - 1) * (icpara[2][i]) - icpara[1][i];
            }

            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    p[i, j] = icpara[i][j] / icpara[2][2];
                }
            }
            q[0, 0] = (2.0 * p[0, 0] / (width - 1));
            q[0, 1] = (2.0 * p[0, 1] / (width - 1));
            q[0, 2] = ((2.0 * p[0, 2] / (width - 1)) - 1.0);
            q[0, 3] = 0.0;

            q[1, 0] = 0.0;
            q[1, 1] = -(2.0 * p[1, 1] / (height - 1));
            q[1, 2] = -((2.0 * p[1, 2] / (height - 1)) - 1.0);
            q[1, 3] = 0.0;

            q[2, 0] = 0.0;
            q[2, 1] = 0.0;
            q[2, 2] = (i_far + i_near) / (i_near - i_far);
            q[2, 3] = 2.0 * i_far * i_near / (i_near - i_far);

            q[3, 0] = 0.0;
            q[3, 1] = 0.0;
            q[3, 2] = -1.0;
            q[3, 3] = 0.0;

            o_d3d_projection.M11 = (float)(q[0, 0] * trans[0][0] + q[0, 1] * trans[1][0] + q[0, 2] * trans[2][0]);
            o_d3d_projection.M12 = (float)(q[1, 0] * trans[0][0] + q[1, 1] * trans[1][0] + q[1, 2] * trans[2][0]);
            o_d3d_projection.M13 = (float)(q[2, 0] * trans[0][0] + q[2, 1] * trans[1][0] + q[2, 2] * trans[2][0]);
            o_d3d_projection.M14 = (float)(q[3, 0] * trans[0][0] + q[3, 1] * trans[1][0] + q[3, 2] * trans[2][0]);
            o_d3d_projection.M21 = (float)(q[0, 0] * trans[0][1] + q[0, 1] * trans[1][1] + q[0, 2] * trans[2][1]);
            o_d3d_projection.M22 = (float)(q[1, 0] * trans[0][1] + q[1, 1] * trans[1][1] + q[1, 2] * trans[2][1]);
            o_d3d_projection.M23 = (float)(q[2, 0] * trans[0][1] + q[2, 1] * trans[1][1] + q[2, 2] * trans[2][1]);
            o_d3d_projection.M24 = (float)(q[3, 0] * trans[0][1] + q[3, 1] * trans[1][1] + q[3, 2] * trans[2][1]);
            o_d3d_projection.M31 = (float)(q[0, 0] * trans[0][2] + q[0, 1] * trans[1][2] + q[0, 2] * trans[2][2]);
            o_d3d_projection.M32 = (float)(q[1, 0] * trans[0][2] + q[1, 1] * trans[1][2] + q[1, 2] * trans[2][2]);
            o_d3d_projection.M33 = (float)(q[2, 0] * trans[0][2] + q[2, 1] * trans[1][2] + q[2, 2] * trans[2][2]);
            o_d3d_projection.M34 = (float)(q[3, 0] * trans[0][2] + q[3, 1] * trans[1][2] + q[3, 2] * trans[2][2]);
            o_d3d_projection.M41 = (float)(q[0, 0] * trans[0][3] + q[0, 1] * trans[1][3] + q[0, 2] * trans[2][3] + q[0, 3]);
            o_d3d_projection.M42 = (float)(q[1, 0] * trans[0][3] + q[1, 1] * trans[1][3] + q[1, 2] * trans[2][3] + q[1, 3]);
            o_d3d_projection.M43 = (float)(q[2, 0] * trans[0][3] + q[2, 1] * trans[1][3] + q[2, 2] * trans[2][3] + q[2, 3]);
            o_d3d_projection.M44 = (float)(q[3, 0] * trans[0][3] + q[3, 1] * trans[1][3] + q[3, 2] * trans[2][3] + q[3, 3]);
            return;
        }
        //分割数16未満になると少し遅くなるかも。
        private void updateExtpat(INyARRgbRaster image, NyARMat i_cpara, int i_xdiv2, int i_ydiv2)
        {

            int i, j;
            int r, g, b;
            //ピクセルリーダーを取得
            int pat_size_w = this._size.w;
            int xdiv = i_xdiv2 / pat_size_w;// xdiv = xdiv2/Config.AR_PATT_SIZE_X;
            int ydiv = i_ydiv2 / this._size.h;// ydiv = ydiv2/Config.AR_PATT_SIZE_Y;
            int xdiv_x_ydiv = xdiv * ydiv;
            double reciprocal;
            double[][] para = i_cpara.getArray();
            double para00 = para[0 * 3 + 0][0];
            double para01 = para[0 * 3 + 1][0];
            double para02 = para[0 * 3 + 2][0];
            double para10 = para[1 * 3 + 0][0];
            double para11 = para[1 * 3 + 1][0];
            double para12 = para[1 * 3 + 2][0];
            double para20 = para[2 * 3 + 0][0];
            double para21 = para[2 * 3 + 1][0];

            INyARRgbPixelDriver reader = image.getRgbPixelDriver();
            int img_width = image.getWidth();
            int img_height = image.getHeight();

            //ワークバッファの準備
            reservWorkBuffers(xdiv, ydiv);
            double[] xw = this.__updateExtpat_xw;
            double[] yw = this.__updateExtpat_yw;
            int[] xc = this.__updateExtpat_xc;
            int[] yc = this.__updateExtpat_yc;
            int[] rgb_set = this.__updateExtpat_rgbset;


            for (int iy = this._size.h - 1; iy >= 0; iy--)
            {
                for (int ix = pat_size_w - 1; ix >= 0; ix--)
                {
                    //xw,ywマップを作成
                    reciprocal = 1.0 / i_xdiv2;
                    for (i = xdiv - 1; i >= 0; i--)
                    {
                        xw[i] = LT_POS + SQ_SIZE * (ix * xdiv + i + 0.5) * reciprocal;
                    }
                    reciprocal = 1.0 / i_ydiv2;
                    for (i = ydiv - 1; i >= 0; i--)
                    {
                        yw[i] = LT_POS + SQ_SIZE * (iy * ydiv + i + 0.5) * reciprocal;
                    }
                    //1ピクセルを構成するピクセル座標の集合をxc,yc配列に取得
                    int number_of_pix = 0;
                    for (i = ydiv - 1; i >= 0; i--)
                    {
                        double para01_x_yw_para02 = para01 * yw[i] + para02;
                        double para11_x_yw_para12 = para11 * yw[i] + para12;
                        double para12_x_yw_para22 = para21 * yw[i] + 1.0;
                        for (j = xdiv - 1; j >= 0; j--)
                        {

                            double d = para20 * xw[j] + para12_x_yw_para22;
                            if (d == 0)
                            {
                                throw new NyARException();
                            }
                            int xcw = (int)((para00 * xw[j] + para01_x_yw_para02) / d);
                            int ycw = (int)((para10 * xw[j] + para11_x_yw_para12) / d);
                            if (xcw < 0 || xcw >= img_width || ycw < 0 || ycw >= img_height)
                            {
                                continue;
                            }
                            xc[number_of_pix] = xcw;
                            yc[number_of_pix] = ycw;
                            number_of_pix++;
                        }
                    }
                    //1ピクセル分の配列を取得
                    reader.getPixelSet(xc, yc, number_of_pix, rgb_set);
                    r = g = b = 0;
                    for (i = number_of_pix * 3 - 1; i >= 0; i -= 3)
                    {
                        r += rgb_set[i - 2];// R
                        g += rgb_set[i - 1];// G
                        b += rgb_set[i];// B
                    }
                    //1ピクセル確定
                    this._patdata[iy * pat_size_w + ix] = (((r / xdiv_x_ydiv) & 0xff) << 16) | (((g / xdiv_x_ydiv) & 0xff) << 8) | (((b / xdiv_x_ydiv) & 0xff));
                }
            }
            return;
        }
        private Matrix GetProjectionMatrix(NyARParam i_arparam, float near, float far)
        {
            NyARMat trans_mat = new NyARMat(3, 4);
            NyARMat icpara_mat = new NyARMat(3, 4);
            double[,] p = new double[3, 3], q = new double[4, 4];
            int width, height;
            int i, j;

            NyARIntSize size = i_arparam.getScreenSize();
            width = size.w;
            height = size.h;

            i_arparam.getPerspectiveProjectionMatrix().decompMat(icpara_mat, trans_mat);

            double[][] icpara = icpara_mat.getArray();
            double[][] trans = trans_mat.getArray();

            for (i = 0; i < 3; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    p[i, j] = icpara[i][j] / icpara[2][2];
                }
            }

            q[0, 0] = (2.0 * p[0, 0] / (width));
            q[0, 1] = (2.0 * p[0, 1] / (width));
            q[0, 2] = ((2.0 * p[0, 2] / (width)) - 1.0);
            q[0, 3] = 0.0;

            q[1, 0] = 0.0;
            q[1, 1] = (2.0 * p[1, 1] / (height));
            q[1, 2] = ((2.0 * p[1, 2] / (height)) - 1.0);
            q[1, 3] = 0.0;

            q[2, 0] = 0.0;
            q[2, 1] = 0.0;
            q[2, 2] = (far + near) / (far - near);
            q[2, 3] = -2.0 * far * near / (far - near);

            q[3, 0] = 0.0;
            q[3, 1] = 0.0;
            q[3, 2] = 1.0;
            q[3, 3] = 0.0;

            Matrix mat = Matrix.Identity;
            mat.M11 = (float)(q[0, 0] * trans[0][0] + q[0, 1] * trans[1][0] + q[0, 2] * trans[2][0]);
            mat.M12 = (float)(q[1, 0] * trans[0][0] + q[1, 1] * trans[1][0] + q[1, 2] * trans[2][0]);
            mat.M13 = (float)(q[2, 0] * trans[0][0] + q[2, 1] * trans[1][0] + q[2, 2] * trans[2][0]);
            mat.M14 = (float)(q[3, 0] * trans[0][0] + q[3, 1] * trans[1][0] + q[3, 2] * trans[2][0]);
            mat.M21 = (float)(q[0, 1] * trans[0][1] + q[0, 1] * trans[1][1] + q[0, 2] * trans[2][1]);
            mat.M22 = (float)(q[1, 1] * trans[0][1] + q[1, 1] * trans[1][1] + q[1, 2] * trans[2][1]);
            mat.M23 = (float)(q[2, 1] * trans[0][1] + q[2, 1] * trans[1][1] + q[2, 2] * trans[2][1]);
            mat.M24 = (float)(q[3, 1] * trans[0][1] + q[3, 1] * trans[1][1] + q[3, 2] * trans[2][1]);
            mat.M31 = (float)(q[0, 2] * trans[0][2] + q[0, 1] * trans[1][2] + q[0, 2] * trans[2][2]);
            mat.M32 = (float)(q[1, 2] * trans[0][2] + q[1, 1] * trans[1][2] + q[1, 2] * trans[2][2]);
            mat.M33 = -(float)(q[2, 2] * trans[0][2] + q[2, 1] * trans[1][2] + q[2, 2] * trans[2][2]);
            mat.M34 = -(float)(q[3, 2] * trans[0][2] + q[3, 1] * trans[1][2] + q[3, 2] * trans[2][2]);
            mat.M41 = (float)(q[0, 3] * trans[0][3] + q[0, 1] * trans[1][3] + q[0, 2] * trans[2][3] + q[0, 3]);
            mat.M42 = (float)(q[1, 3] * trans[0][3] + q[1, 1] * trans[1][3] + q[1, 2] * trans[2][3] + q[1, 3]);
            mat.M43 = (float)(q[2, 3] * trans[0][3] + q[2, 1] * trans[1][3] + q[2, 2] * trans[2][3] + q[2, 3]);
            mat.M44 = (float)(q[3, 3] * trans[0][3] + q[3, 1] * trans[1][3] + q[3, 2] * trans[2][3] + q[3, 3]);

            return mat;
        }