1f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
2f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger/*
3f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Copyright 2006 The Android Open Source Project
4f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger *
5f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
6f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger * found in the LICENSE file.
7f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger */
8f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
9f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
10f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkCamera.h"
11f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
12f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkScalar SkScalarDotDiv(int count, const SkScalar a[], int step_a,
13f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                               const SkScalar b[], int step_b,
14f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                               SkScalar denom) {
15f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
16f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    float prod = 0;
17f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < count; i++) {
18f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        prod += a[0] * b[0];
19f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        a += step_a;
20f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        b += step_b;
21f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
22f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return prod / denom;
23f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else
24f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Sk64    prod, tmp;
25f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
26f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    prod.set(0);
27f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < count; i++) {
28f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        tmp.setMul(a[0], b[0]);
29f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        prod.add(tmp);
30f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        a += step_a;
31f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        b += step_b;
32f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
33f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    prod.div(denom, Sk64::kRound_DivOption);
34f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return prod.get32();
35f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
36f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
37f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
38f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergerstatic SkScalar SkScalarDot(int count, const SkScalar a[], int step_a,
39f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                                       const SkScalar b[], int step_b) {
40f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
41f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    float prod = 0;
42f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < count; i++) {
43f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        prod += a[0] * b[0];
44f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        a += step_a;
45f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        b += step_b;
46f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
47f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return prod;
48f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else
49f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Sk64    prod, tmp;
50f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
51f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    prod.set(0);
52f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < count; i++) {
53f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        tmp.setMul(a[0], b[0]);
54f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        prod.add(tmp);
55f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        a += step_a;
56f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        b += step_b;
57f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
58f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return prod.getFixed();
59f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
60f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
61f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
62f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
63f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
64f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkUnitScalar SkPoint3D::normalize(SkUnit3D* unit) const {
65f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
66f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    float mag = sk_float_sqrt(fX*fX + fY*fY + fZ*fZ);
67f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (mag) {
68f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        float scale = 1.0f / mag;
69f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fX = fX * scale;
70f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fY = fY * scale;
71f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fZ = fZ * scale;
72f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
73f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fX = unit->fY = unit->fZ = 0;
74f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
75f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#else
76f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Sk64    tmp1, tmp2;
77f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
78f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    tmp1.setMul(fX, fX);
79f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    tmp2.setMul(fY, fY);
80f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    tmp1.add(tmp2);
81f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    tmp2.setMul(fZ, fZ);
82f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    tmp1.add(tmp2);
83f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
84f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkFixed mag = tmp1.getSqrt();
85f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (mag) {
86f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        // what if mag < SK_Fixed1 ??? we will underflow the fixdiv
87f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkFixed scale = SkFixedDiv(SK_Fract1, mag);
88f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fX = SkFixedMul(fX, scale);
89f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fY = SkFixedMul(fY, scale);
90f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fZ = SkFixedMul(fZ, scale);
91f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    } else {
92f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        unit->fX = unit->fY = unit->fZ = 0;
93f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
94f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
95f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return mag;
96f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
97f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
98f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkUnitScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b) {
99f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return  SkUnitScalarMul(a.fX, b.fX) +
100f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkUnitScalarMul(a.fY, b.fY) +
101f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            SkUnitScalarMul(a.fZ, b.fZ);
102f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
103f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
104f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross) {
105f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(cross);
106f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
107f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // use x,y,z, in case &a == cross or &b == cross
108f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
109f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar x = SkUnitScalarMul(a.fY, b.fZ) - SkUnitScalarMul(a.fZ, b.fY);
110f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar y = SkUnitScalarMul(a.fZ, b.fX) - SkUnitScalarMul(a.fX, b.fY);
111f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar z = SkUnitScalarMul(a.fX, b.fY) - SkUnitScalarMul(a.fY, b.fX);
112f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
113f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    cross->set(x, y, z);
114f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
115f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
116f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
117f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
118f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkPatch3D::SkPatch3D() {
119f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->reset();
120f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
121f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
122f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkPatch3D::reset() {
123f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fOrigin.set(0, 0, 0);
124f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fU.set(SK_Scalar1, 0, 0);
125f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fV.set(0, -SK_Scalar1, 0);
126f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
127f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
128f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkPatch3D::transform(const SkMatrix3D& m, SkPatch3D* dst) const {
129f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (dst == NULL) {
130f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        dst = (SkPatch3D*)this;
131f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
132f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    m.mapVector(fU, &dst->fU);
133f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    m.mapVector(fV, &dst->fV);
134f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    m.mapPoint(fOrigin, &dst->fOrigin);
135f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
136f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
137f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar SkPatch3D::dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const {
138f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar cx = SkScalarMul(fU.fY, fV.fZ) - SkScalarMul(fU.fZ, fV.fY);
139f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar cy = SkScalarMul(fU.fZ, fV.fX) - SkScalarMul(fU.fX, fV.fY);
140f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar cz = SkScalarMul(fU.fX, fV.fY) - SkScalarMul(fU.fY, fV.fX);
141f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
142f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return SkScalarMul(cx, dx) + SkScalarMul(cy, dy) + SkScalarMul(cz, dz);
143f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
144f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
145f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
146f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
147f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::reset() {
148f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    memset(fMat, 0, sizeof(fMat));
149f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fMat[0][0] = fMat[1][1] = fMat[2][2] = SK_Scalar1;
150f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
151f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
152f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::setTranslate(SkScalar x, SkScalar y, SkScalar z) {
153f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    memset(fMat, 0, sizeof(fMat));
154f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fMat[0][0] = x;
155f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fMat[1][1] = y;
156f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fMat[2][2] = z;
157f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
158f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
159f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::setRotateX(SkScalar degX) {
160f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar    s, c;
161f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
162f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    s = SkScalarSinCos(SkDegreesToRadians(degX), &c);
163f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(0, SK_Scalar1, 0, 0);
164f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(1, 0, c, -s);
165f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(2, 0, s, c);
166f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
167f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
168f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::setRotateY(SkScalar degY) {
169f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar    s, c;
170f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
171f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    s = SkScalarSinCos(SkDegreesToRadians(degY), &c);
172f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(0, c, 0, -s);
173f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(1, 0, SK_Scalar1, 0);
174f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(2, s, 0, c);
175f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
176f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
177f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::setRotateZ(SkScalar degZ) {
178f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar    s, c;
179f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
180f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    s = SkScalarSinCos(SkDegreesToRadians(degZ), &c);
181f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(0, c, -s, 0);
182f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(1, s, c, 0);
183f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setRow(2, 0, 0, SK_Scalar1);
184f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
185f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
186f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::preTranslate(SkScalar x, SkScalar y, SkScalar z) {
187f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar col[3] = { x, y, z};
188f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
189f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < 3; i++) {
190f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fMat[i][3] += SkScalarDot(3, &fMat[i][0], 1, col, 1);
191f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
192f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
193f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
194f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::preRotateX(SkScalar degX) {
195f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkMatrix3D m;
196f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    m.setRotateX(degX);
197f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setConcat(*this, m);
198f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
199f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
200f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::preRotateY(SkScalar degY) {
201f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkMatrix3D m;
202f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    m.setRotateY(degY);
203f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setConcat(*this, m);
204f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
205f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
206f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::preRotateZ(SkScalar degZ) {
207f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkMatrix3D m;
208f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    m.setRotateZ(degZ);
209f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->setConcat(*this, m);
210f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
211f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
212f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::setConcat(const SkMatrix3D& a, const SkMatrix3D& b) {
213f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkMatrix3D  tmp;
214f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkMatrix3D* c = this;
215f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
216f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (this == &a || this == &b) {
217f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        c = &tmp;
218f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
219f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    for (int i = 0; i < 3; i++) {
220f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        for (int j = 0; j < 3; j++) {
221f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger            c->fMat[i][j] = SkScalarDot(3, &a.fMat[i][0], 1, &b.fMat[0][j], 4);
222f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        }
223f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        c->fMat[i][3] = SkScalarDot(3, &a.fMat[i][0], 1,
224f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                                    &b.fMat[0][3], 4) + a.fMat[i][3];
225f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
226f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
227f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (c == &tmp) {
228f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        *this = tmp;
229f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
230f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
231f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
232f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::mapPoint(const SkPoint3D& src, SkPoint3D* dst) const {
233f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1) + fMat[0][3];
234f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1) + fMat[1][3];
235f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1) + fMat[2][3];
236f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    dst->set(x, y, z);
237f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
238f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
239f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkMatrix3D::mapVector(const SkVector3D& src, SkVector3D* dst) const {
240f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1);
241f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1);
242f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1);
243f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    dst->set(x, y, z);
244f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
245f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
246f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
247f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
248f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkCamera3D::SkCamera3D() {
249f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->reset();
250f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
251f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
252f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkCamera3D::reset() {
253f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fLocation.set(0, 0, -SkIntToScalar(576));   // 8 inches backward
254f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fAxis.set(0, 0, SK_Scalar1);                // forward
255f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fZenith.set(0, -SK_Scalar1, 0);             // up
256f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
257f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fObserver.set(0, 0, fLocation.fZ);
258f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
259f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fNeedToUpdate = true;
260f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
261f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
262f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkCamera3D::update() {
263f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fNeedToUpdate = true;
264f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
265f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
266f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkCamera3D::doUpdate() const {
267f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkUnit3D    axis, zenith, cross;
268f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
269f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fAxis.normalize(&axis);
270f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
271f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    {
272f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkScalar dot = SkUnit3D::Dot(*(const SkUnit3D*)(const void*)&fZenith, axis);
273f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
274f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        zenith.fX = fZenith.fX - SkUnitScalarMul(dot, axis.fX);
275f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        zenith.fY = fZenith.fY - SkUnitScalarMul(dot, axis.fY);
276f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        zenith.fZ = fZenith.fZ - SkUnitScalarMul(dot, axis.fZ);
277f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
278f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        (void)((SkPoint3D*)(void*)&zenith)->normalize(&zenith);
279f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
280f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
281f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkUnit3D::Cross(axis, zenith, &cross);
282f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
283f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    {
284f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkMatrix* orien = &fOrientation;
285f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkScalar x = fObserver.fX;
286f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkScalar y = fObserver.fY;
287f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkScalar z = fObserver.fZ;
288f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
289f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMScaleX, SkUnitScalarMul(x, axis.fX) - SkUnitScalarMul(z, cross.fX));
290f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMSkewX,  SkUnitScalarMul(x, axis.fY) - SkUnitScalarMul(z, cross.fY));
291f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMTransX, SkUnitScalarMul(x, axis.fZ) - SkUnitScalarMul(z, cross.fZ));
292f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMSkewY,  SkUnitScalarMul(y, axis.fX) - SkUnitScalarMul(z, zenith.fX));
293f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMScaleY, SkUnitScalarMul(y, axis.fY) - SkUnitScalarMul(z, zenith.fY));
294f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMTransY, SkUnitScalarMul(y, axis.fZ) - SkUnitScalarMul(z, zenith.fZ));
295f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMPersp0, axis.fX);
296f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMPersp1, axis.fY);
297f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        orien->set(SkMatrix::kMPersp2, axis.fZ);
298f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
299f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
300f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
301f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const {
302f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (fNeedToUpdate) {
303f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        this->doUpdate();
304f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fNeedToUpdate = false;
305f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
306f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
307f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const SkScalar* mapPtr = (const SkScalar*)(const void*)&fOrientation;
308f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    const SkScalar* patchPtr;
309f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkPoint3D       diff;
310f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar        dot;
311f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
312f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    diff.fX = quilt.fOrigin.fX - fLocation.fX;
313f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    diff.fY = quilt.fOrigin.fY - fLocation.fY;
314f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    diff.fZ = quilt.fOrigin.fZ - fLocation.fZ;
315f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
316f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    dot = SkUnit3D::Dot(*(const SkUnit3D*)(const void*)&diff,
317f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger                        *(const SkUnit3D*)(((const SkScalar*)(const void*)&fOrientation) + 6));
318f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
319f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    patchPtr = (const SkScalar*)&quilt;
320f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMScaleX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
321f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMSkewY,  SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
322f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMPersp0, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot));
323f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
324f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    patchPtr += 3;
325f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMSkewX,  SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
326f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMScaleY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
327f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMPersp1, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot));
328f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
329f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    patchPtr = (const SkScalar*)(const void*)&diff;
330f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMTransX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
331f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMTransY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot));
332f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    matrix->set(SkMatrix::kMPersp2, SK_UnitScalar1);
333f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
334f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
335f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger///////////////////////////////////////////////////////////////////////////////
336f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
337f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSk3DView::Sk3DView() {
338f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fInitialRec.fMatrix.reset();
339f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec = &fInitialRec;
340f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
341f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
342f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSk3DView::~Sk3DView() {
343f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Rec* rec = fRec;
344f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    while (rec != &fInitialRec) {
345f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        Rec* next = rec->fNext;
346f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkDELETE(rec);
347f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        rec = next;
348f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
349f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
350f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
351f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::save() {
352f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Rec* rec = SkNEW(Rec);
353f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    rec->fNext = fRec;
354f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    rec->fMatrix = fRec->fMatrix;
355f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec = rec;
356f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
357f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
358f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::restore() {
359f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkASSERT(fRec != &fInitialRec);
360f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    Rec* next = fRec->fNext;
361f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkDELETE(fRec);
362f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec = next;
363f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
364f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
365f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID
366f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::setCameraLocation(SkScalar x, SkScalar y, SkScalar z) {
367f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    // the camera location is passed in inches, set in pt
368f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkScalar lz = z * SkFloatToScalar(72.0f);
369f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fCamera.fLocation.set(x * SkFloatToScalar(72.0f), y * SkFloatToScalar(72.0f), lz);
370f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fCamera.fObserver.set(0, 0, lz);
371f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fCamera.update();
372f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
373f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
374f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
375f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar Sk3DView::getCameraLocationX() {
376f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return fCamera.fLocation.fX / SkFloatToScalar(72.0f);
377f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
378f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
379f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar Sk3DView::getCameraLocationY() {
380f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return fCamera.fLocation.fY / SkFloatToScalar(72.0f);
381f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
382f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
383f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar Sk3DView::getCameraLocationZ() {
384f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return fCamera.fLocation.fZ / SkFloatToScalar(72.0f);
385f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
386f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#endif
387f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
388f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::translate(SkScalar x, SkScalar y, SkScalar z) {
389f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec->fMatrix.preTranslate(x, y, z);
390f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
391f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
392f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::rotateX(SkScalar deg) {
393f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec->fMatrix.preRotateX(deg);
394f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
395f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
396f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::rotateY(SkScalar deg) {
397f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec->fMatrix.preRotateY(deg);
398f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
399f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
400f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::rotateZ(SkScalar deg) {
401f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    fRec->fMatrix.preRotateZ(deg);
402f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
403f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
404f8cacf6b11e35785df8efb613b0c3592d535f603Derek SollenbergerSkScalar Sk3DView::dotWithNormal(SkScalar x, SkScalar y, SkScalar z) const {
405f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkPatch3D   patch;
406f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    patch.transform(fRec->fMatrix);
407f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    return patch.dotWith(x, y, z);
408f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
409f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
410f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::getMatrix(SkMatrix* matrix) const {
411f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    if (matrix != NULL) {
412f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        SkPatch3D   patch;
413f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        patch.transform(fRec->fMatrix);
414f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger        fCamera.patchToMatrix(patch, matrix);
415f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    }
416f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
417f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
418f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger#include "SkCanvas.h"
419f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
420f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenbergervoid Sk3DView::applyToCanvas(SkCanvas* canvas) const {
421f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    SkMatrix    matrix;
422f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
423f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    this->getMatrix(&matrix);
424f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger    canvas->concat(matrix);
425f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger}
426f8cacf6b11e35785df8efb613b0c3592d535f603Derek Sollenberger
427