Matrix.cpp revision 9d5316e3f56d138504565ff311145ac01621dff4
108ae317c21ec3086b5017672bba87420cc38a407Romain Guy/*
208ae317c21ec3086b5017672bba87420cc38a407Romain Guy * Copyright (C) 2010 The Android Open Source Project
308ae317c21ec3086b5017672bba87420cc38a407Romain Guy *
408ae317c21ec3086b5017672bba87420cc38a407Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
508ae317c21ec3086b5017672bba87420cc38a407Romain Guy * you may not use this file except in compliance with the License.
608ae317c21ec3086b5017672bba87420cc38a407Romain Guy * You may obtain a copy of the License at
708ae317c21ec3086b5017672bba87420cc38a407Romain Guy *
808ae317c21ec3086b5017672bba87420cc38a407Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
908ae317c21ec3086b5017672bba87420cc38a407Romain Guy *
1008ae317c21ec3086b5017672bba87420cc38a407Romain Guy * Unless required by applicable law or agreed to in writing, software
1108ae317c21ec3086b5017672bba87420cc38a407Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
1208ae317c21ec3086b5017672bba87420cc38a407Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308ae317c21ec3086b5017672bba87420cc38a407Romain Guy * See the License for the specific language governing permissions and
1408ae317c21ec3086b5017672bba87420cc38a407Romain Guy * limitations under the License.
1508ae317c21ec3086b5017672bba87420cc38a407Romain Guy */
1608ae317c21ec3086b5017672bba87420cc38a407Romain Guy
179d5316e3f56d138504565ff311145ac01621dff4Romain Guy#define LOG_TAG "Matrix"
1808ae317c21ec3086b5017672bba87420cc38a407Romain Guy
1908ae317c21ec3086b5017672bba87420cc38a407Romain Guy#include <math.h>
2008ae317c21ec3086b5017672bba87420cc38a407Romain Guy#include <stdlib.h>
213e168335b3422008908ac6973bb36078fd979f35Romain Guy#include <string.h>
2208ae317c21ec3086b5017672bba87420cc38a407Romain Guy
2308ae317c21ec3086b5017672bba87420cc38a407Romain Guy#include <utils/Log.h>
2408ae317c21ec3086b5017672bba87420cc38a407Romain Guy
25f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy#include <SkMatrix.h>
26f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
2785bf02fc16784d935fb9eebfa9cb20fe46ff7951Romain Guy#include "Matrix.h"
2808ae317c21ec3086b5017672bba87420cc38a407Romain Guy
2908ae317c21ec3086b5017672bba87420cc38a407Romain Guynamespace android {
309d5316e3f56d138504565ff311145ac01621dff4Romain Guynamespace uirenderer {
3108ae317c21ec3086b5017672bba87420cc38a407Romain Guy
3208ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::loadIdentity() {
33f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[0]  = 1.0f;
34f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[1]  = 0.0f;
35f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[2]  = 0.0f;
36f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[3]  = 0.0f;
37f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
38f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[4]  = 0.0f;
39f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[5]  = 1.0f;
40f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[6]  = 0.0f;
41f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[7]  = 0.0f;
42f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
43f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[8]  = 0.0f;
44f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[9]  = 0.0f;
45f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[10] = 1.0f;
46f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[11] = 0.0f;
47f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
48f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[12] = 0.0f;
49f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[13] = 0.0f;
50f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[14] = 0.0f;
51f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[15] = 1.0f;
5208ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
5308ae317c21ec3086b5017672bba87420cc38a407Romain Guy
5408ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::load(const float* v) {
5508ae317c21ec3086b5017672bba87420cc38a407Romain Guy	memcpy(mMat, v, sizeof(mMat));
5608ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
5708ae317c21ec3086b5017672bba87420cc38a407Romain Guy
5808ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::load(const Matrix4& v) {
5908ae317c21ec3086b5017672bba87420cc38a407Romain Guy	memcpy(mMat, v.mMat, sizeof(mMat));
6008ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
6108ae317c21ec3086b5017672bba87420cc38a407Romain Guy
62f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid Matrix4::load(const SkMatrix& v) {
63f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	memset(mMat, 0, sizeof(mMat));
64f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
65f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[0]  = v[SkMatrix::kMScaleX];
66f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[4]  = v[SkMatrix::kMSkewX];
67f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[12] = v[SkMatrix::kMTransX];
68f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
69f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[1]  = v[SkMatrix::kMSkewY];
70f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[5]  = v[SkMatrix::kMScaleY];
71f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[13] = v[SkMatrix::kMTransY];
72f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
73f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[3]  = v[SkMatrix::kMPersp0];
74f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[7]  = v[SkMatrix::kMPersp1];
75f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[15] = v[SkMatrix::kMPersp2];
76f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
77f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[10] = 1.0f;
78f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
79f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
80f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guyvoid Matrix4::copyTo(SkMatrix& v) const {
81f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.reset();
82f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
83f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMScaleX, mMat[0]);
84f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMSkewX,  mMat[4]);
85f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMTransX, mMat[12]);
86f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
87f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMSkewY,  mMat[1]);
88f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMScaleY, mMat[5]);
89f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMTransY, mMat[13]);
90f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
91f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMPersp0, mMat[3]);
92f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMPersp1, mMat[7]);
93f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	v.set(SkMatrix::kMPersp2, mMat[15]);
94f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy}
95f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy
9608ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::copyTo(float* v) const {
9708ae317c21ec3086b5017672bba87420cc38a407Romain Guy	memcpy(v, mMat, sizeof(mMat));
9808ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
9908ae317c21ec3086b5017672bba87420cc38a407Romain Guy
10008ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::loadTranslate(float x, float y, float z) {
10108ae317c21ec3086b5017672bba87420cc38a407Romain Guy	loadIdentity();
10208ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[12] = x;
10308ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[13] = y;
10408ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[14] = z;
10508ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
10608ae317c21ec3086b5017672bba87420cc38a407Romain Guy
10708ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::loadScale(float sx, float sy, float sz) {
10808ae317c21ec3086b5017672bba87420cc38a407Romain Guy	loadIdentity();
10908ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[0]  = sx;
11008ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[5]  = sy;
11108ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[10] = sz;
11208ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
11308ae317c21ec3086b5017672bba87420cc38a407Romain Guy
11408ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::loadRotate(float angle, float x, float y, float z) {
115f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[3]  = 0.0f;
116f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[7]  = 0.0f;
117f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[11] = 0.0f;
118f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[12] = 0.0f;
119f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[13] = 0.0f;
120f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[14] = 0.0f;
121f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy	mMat[15] = 1.0f;
12208ae317c21ec3086b5017672bba87420cc38a407Romain Guy
12308ae317c21ec3086b5017672bba87420cc38a407Romain Guy	angle *= float(M_PI / 180.0f);
12408ae317c21ec3086b5017672bba87420cc38a407Romain Guy	float c = cosf(angle);
12508ae317c21ec3086b5017672bba87420cc38a407Romain Guy	float s = sinf(angle);
12608ae317c21ec3086b5017672bba87420cc38a407Romain Guy
12708ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float length = sqrtf(x * x + y * y + z * z);
12808ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float nc = 1.0f - c;
12908ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float xy = x * y;
13008ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float yz = y * z;
13108ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float zx = z * x;
13208ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float xs = x * s;
13308ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float ys = y * s;
13408ae317c21ec3086b5017672bba87420cc38a407Romain Guy	const float zs = z * s;
13508ae317c21ec3086b5017672bba87420cc38a407Romain Guy
13608ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[0]  = x * x * nc +  c;
13708ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[4]  =    xy * nc - zs;
13808ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[8]  =    zx * nc + ys;
13908ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[1]  =    xy * nc + zs;
14008ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[5]  = y * y * nc +  c;
14108ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[9]  =    yz * nc - xs;
14208ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[2]  =    zx * nc - ys;
14308ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[6]  =    yz * nc + xs;
14408ae317c21ec3086b5017672bba87420cc38a407Romain Guy	mMat[10] = z * z * nc +  c;
14508ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
14608ae317c21ec3086b5017672bba87420cc38a407Romain Guy
14708ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
14808ae317c21ec3086b5017672bba87420cc38a407Romain Guy    for (int i = 0 ; i < 4 ; i++) {
14908ae317c21ec3086b5017672bba87420cc38a407Romain Guy        float x = 0;
15008ae317c21ec3086b5017672bba87420cc38a407Romain Guy        float y = 0;
15108ae317c21ec3086b5017672bba87420cc38a407Romain Guy        float z = 0;
15208ae317c21ec3086b5017672bba87420cc38a407Romain Guy        float w = 0;
15308ae317c21ec3086b5017672bba87420cc38a407Romain Guy
15408ae317c21ec3086b5017672bba87420cc38a407Romain Guy        for (int j = 0 ; j < 4 ; j++) {
15508ae317c21ec3086b5017672bba87420cc38a407Romain Guy            const float e = v.get(i,j);
15608ae317c21ec3086b5017672bba87420cc38a407Romain Guy            x += u.get(j, 0) * e;
15708ae317c21ec3086b5017672bba87420cc38a407Romain Guy            y += u.get(j, 1) * e;
15808ae317c21ec3086b5017672bba87420cc38a407Romain Guy            z += u.get(j, 2) * e;
15908ae317c21ec3086b5017672bba87420cc38a407Romain Guy            w += u.get(j, 3) * e;
16008ae317c21ec3086b5017672bba87420cc38a407Romain Guy        }
16108ae317c21ec3086b5017672bba87420cc38a407Romain Guy
16208ae317c21ec3086b5017672bba87420cc38a407Romain Guy        set(i, 0, x);
16308ae317c21ec3086b5017672bba87420cc38a407Romain Guy        set(i, 1, y);
16408ae317c21ec3086b5017672bba87420cc38a407Romain Guy        set(i, 2, z);
16508ae317c21ec3086b5017672bba87420cc38a407Romain Guy        set(i, 3, w);
16608ae317c21ec3086b5017672bba87420cc38a407Romain Guy    }
16708ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
16808ae317c21ec3086b5017672bba87420cc38a407Romain Guy
16908ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
17008ae317c21ec3086b5017672bba87420cc38a407Romain Guy    loadIdentity();
171f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    mMat[0]  = 2.0f / (right - left);
172f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    mMat[5]  = 2.0f / (top - bottom);
173f6a11b8a9e25ff9861bbba19251bea84d8a5daf2Romain Guy    mMat[10] = -2.0f / (far - near);
17408ae317c21ec3086b5017672bba87420cc38a407Romain Guy    mMat[12] = -(right + left) / (right - left);
17508ae317c21ec3086b5017672bba87420cc38a407Romain Guy    mMat[13] = -(top + bottom) / (top - bottom);
17608ae317c21ec3086b5017672bba87420cc38a407Romain Guy    mMat[14] = -(far + near) / (far - near);
17708ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
17808ae317c21ec3086b5017672bba87420cc38a407Romain Guy
1799d5316e3f56d138504565ff311145ac01621dff4Romain Guy#define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
1809d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1819d5316e3f56d138504565ff311145ac01621dff4Romain Guyvoid Matrix4::mapRect(Rect& r) const {
1829d5316e3f56d138504565ff311145ac01621dff4Romain Guy	const float sx = mMat[0];
1839d5316e3f56d138504565ff311145ac01621dff4Romain Guy	const float sy = mMat[5];
1849d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1859d5316e3f56d138504565ff311145ac01621dff4Romain Guy	const float tx = mMat[12];
1869d5316e3f56d138504565ff311145ac01621dff4Romain Guy	const float ty = mMat[13];
1879d5316e3f56d138504565ff311145ac01621dff4Romain Guy
1889d5316e3f56d138504565ff311145ac01621dff4Romain Guy	MUL_ADD_STORE(r.left, sx, tx);
1899d5316e3f56d138504565ff311145ac01621dff4Romain Guy	MUL_ADD_STORE(r.right, sx, tx);
1909d5316e3f56d138504565ff311145ac01621dff4Romain Guy	MUL_ADD_STORE(r.top, sy, ty);
1919d5316e3f56d138504565ff311145ac01621dff4Romain Guy	MUL_ADD_STORE(r.bottom, sy, ty);
1929d5316e3f56d138504565ff311145ac01621dff4Romain Guy}
1939d5316e3f56d138504565ff311145ac01621dff4Romain Guy
19408ae317c21ec3086b5017672bba87420cc38a407Romain Guyvoid Matrix4::dump() const {
195bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy	LOGD("Matrix4[");
196bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy	LOGD("  %f %f %f %f", mMat[0], mMat[4], mMat[ 8], mMat[12]);
197bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy	LOGD("  %f %f %f %f", mMat[1], mMat[5], mMat[ 9], mMat[13]);
198bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy	LOGD("  %f %f %f %f", mMat[2], mMat[6], mMat[10], mMat[14]);
199bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy	LOGD("  %f %f %f %f", mMat[3], mMat[7], mMat[11], mMat[15]);
200bb9524b6bdddc7ac77d8628daa8b366b8a7be4a4Romain Guy	LOGD("]");
20108ae317c21ec3086b5017672bba87420cc38a407Romain Guy}
20208ae317c21ec3086b5017672bba87420cc38a407Romain Guy
2039d5316e3f56d138504565ff311145ac01621dff4Romain Guy}; // namespace uirenderer
2049d5316e3f56d138504565ff311145ac01621dff4Romain Guy}; // namespace android
205