1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/utils/SkCamera.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,373 @@ 1.4 +/* 1.5 + * Copyright 2006 The Android Open Source Project 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkCamera.h" 1.12 + 1.13 +static SkScalar SkScalarDotDiv(int count, const SkScalar a[], int step_a, 1.14 + const SkScalar b[], int step_b, 1.15 + SkScalar denom) { 1.16 + SkScalar prod = 0; 1.17 + for (int i = 0; i < count; i++) { 1.18 + prod += a[0] * b[0]; 1.19 + a += step_a; 1.20 + b += step_b; 1.21 + } 1.22 + return prod / denom; 1.23 +} 1.24 + 1.25 +static SkScalar SkScalarDot(int count, const SkScalar a[], int step_a, 1.26 + const SkScalar b[], int step_b) { 1.27 + SkScalar prod = 0; 1.28 + for (int i = 0; i < count; i++) { 1.29 + prod += a[0] * b[0]; 1.30 + a += step_a; 1.31 + b += step_b; 1.32 + } 1.33 + return prod; 1.34 +} 1.35 + 1.36 +/////////////////////////////////////////////////////////////////////////////// 1.37 + 1.38 +SkScalar SkPoint3D::normalize(SkUnit3D* unit) const { 1.39 + SkScalar mag = SkScalarSqrt(fX*fX + fY*fY + fZ*fZ); 1.40 + if (mag) { 1.41 + SkScalar scale = SkScalarInvert(mag); 1.42 + unit->fX = fX * scale; 1.43 + unit->fY = fY * scale; 1.44 + unit->fZ = fZ * scale; 1.45 + } else { 1.46 + unit->fX = unit->fY = unit->fZ = 0; 1.47 + } 1.48 + return mag; 1.49 +} 1.50 + 1.51 +SkScalar SkUnit3D::Dot(const SkUnit3D& a, const SkUnit3D& b) { 1.52 + return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ; 1.53 +} 1.54 + 1.55 +void SkUnit3D::Cross(const SkUnit3D& a, const SkUnit3D& b, SkUnit3D* cross) { 1.56 + SkASSERT(cross); 1.57 + 1.58 + // use x,y,z, in case &a == cross or &b == cross 1.59 + 1.60 + SkScalar x = a.fY * b.fZ - a.fZ * b.fY; 1.61 + SkScalar y = a.fZ * b.fX - a.fX * b.fY; 1.62 + SkScalar z = a.fX * b.fY - a.fY * b.fX; 1.63 + 1.64 + cross->set(x, y, z); 1.65 +} 1.66 + 1.67 +/////////////////////////////////////////////////////////////////////////////// 1.68 + 1.69 +SkPatch3D::SkPatch3D() { 1.70 + this->reset(); 1.71 +} 1.72 + 1.73 +void SkPatch3D::reset() { 1.74 + fOrigin.set(0, 0, 0); 1.75 + fU.set(SK_Scalar1, 0, 0); 1.76 + fV.set(0, -SK_Scalar1, 0); 1.77 +} 1.78 + 1.79 +void SkPatch3D::transform(const SkMatrix3D& m, SkPatch3D* dst) const { 1.80 + if (dst == NULL) { 1.81 + dst = (SkPatch3D*)this; 1.82 + } 1.83 + m.mapVector(fU, &dst->fU); 1.84 + m.mapVector(fV, &dst->fV); 1.85 + m.mapPoint(fOrigin, &dst->fOrigin); 1.86 +} 1.87 + 1.88 +SkScalar SkPatch3D::dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const { 1.89 + SkScalar cx = SkScalarMul(fU.fY, fV.fZ) - SkScalarMul(fU.fZ, fV.fY); 1.90 + SkScalar cy = SkScalarMul(fU.fZ, fV.fX) - SkScalarMul(fU.fX, fV.fY); 1.91 + SkScalar cz = SkScalarMul(fU.fX, fV.fY) - SkScalarMul(fU.fY, fV.fX); 1.92 + 1.93 + return SkScalarMul(cx, dx) + SkScalarMul(cy, dy) + SkScalarMul(cz, dz); 1.94 +} 1.95 + 1.96 +/////////////////////////////////////////////////////////////////////////////// 1.97 + 1.98 +void SkMatrix3D::reset() { 1.99 + memset(fMat, 0, sizeof(fMat)); 1.100 + fMat[0][0] = fMat[1][1] = fMat[2][2] = SK_Scalar1; 1.101 +} 1.102 + 1.103 +void SkMatrix3D::setTranslate(SkScalar x, SkScalar y, SkScalar z) { 1.104 + memset(fMat, 0, sizeof(fMat)); 1.105 + fMat[0][0] = x; 1.106 + fMat[1][1] = y; 1.107 + fMat[2][2] = z; 1.108 +} 1.109 + 1.110 +void SkMatrix3D::setRotateX(SkScalar degX) { 1.111 + SkScalar s, c; 1.112 + 1.113 + s = SkScalarSinCos(SkDegreesToRadians(degX), &c); 1.114 + this->setRow(0, SK_Scalar1, 0, 0); 1.115 + this->setRow(1, 0, c, -s); 1.116 + this->setRow(2, 0, s, c); 1.117 +} 1.118 + 1.119 +void SkMatrix3D::setRotateY(SkScalar degY) { 1.120 + SkScalar s, c; 1.121 + 1.122 + s = SkScalarSinCos(SkDegreesToRadians(degY), &c); 1.123 + this->setRow(0, c, 0, -s); 1.124 + this->setRow(1, 0, SK_Scalar1, 0); 1.125 + this->setRow(2, s, 0, c); 1.126 +} 1.127 + 1.128 +void SkMatrix3D::setRotateZ(SkScalar degZ) { 1.129 + SkScalar s, c; 1.130 + 1.131 + s = SkScalarSinCos(SkDegreesToRadians(degZ), &c); 1.132 + this->setRow(0, c, -s, 0); 1.133 + this->setRow(1, s, c, 0); 1.134 + this->setRow(2, 0, 0, SK_Scalar1); 1.135 +} 1.136 + 1.137 +void SkMatrix3D::preTranslate(SkScalar x, SkScalar y, SkScalar z) { 1.138 + SkScalar col[3] = { x, y, z}; 1.139 + 1.140 + for (int i = 0; i < 3; i++) { 1.141 + fMat[i][3] += SkScalarDot(3, &fMat[i][0], 1, col, 1); 1.142 + } 1.143 +} 1.144 + 1.145 +void SkMatrix3D::preRotateX(SkScalar degX) { 1.146 + SkMatrix3D m; 1.147 + m.setRotateX(degX); 1.148 + this->setConcat(*this, m); 1.149 +} 1.150 + 1.151 +void SkMatrix3D::preRotateY(SkScalar degY) { 1.152 + SkMatrix3D m; 1.153 + m.setRotateY(degY); 1.154 + this->setConcat(*this, m); 1.155 +} 1.156 + 1.157 +void SkMatrix3D::preRotateZ(SkScalar degZ) { 1.158 + SkMatrix3D m; 1.159 + m.setRotateZ(degZ); 1.160 + this->setConcat(*this, m); 1.161 +} 1.162 + 1.163 +void SkMatrix3D::setConcat(const SkMatrix3D& a, const SkMatrix3D& b) { 1.164 + SkMatrix3D tmp; 1.165 + SkMatrix3D* c = this; 1.166 + 1.167 + if (this == &a || this == &b) { 1.168 + c = &tmp; 1.169 + } 1.170 + for (int i = 0; i < 3; i++) { 1.171 + for (int j = 0; j < 3; j++) { 1.172 + c->fMat[i][j] = SkScalarDot(3, &a.fMat[i][0], 1, &b.fMat[0][j], 4); 1.173 + } 1.174 + c->fMat[i][3] = SkScalarDot(3, &a.fMat[i][0], 1, 1.175 + &b.fMat[0][3], 4) + a.fMat[i][3]; 1.176 + } 1.177 + 1.178 + if (c == &tmp) { 1.179 + *this = tmp; 1.180 + } 1.181 +} 1.182 + 1.183 +void SkMatrix3D::mapPoint(const SkPoint3D& src, SkPoint3D* dst) const { 1.184 + SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1) + fMat[0][3]; 1.185 + SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1) + fMat[1][3]; 1.186 + SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1) + fMat[2][3]; 1.187 + dst->set(x, y, z); 1.188 +} 1.189 + 1.190 +void SkMatrix3D::mapVector(const SkVector3D& src, SkVector3D* dst) const { 1.191 + SkScalar x = SkScalarDot(3, &fMat[0][0], 1, &src.fX, 1); 1.192 + SkScalar y = SkScalarDot(3, &fMat[1][0], 1, &src.fX, 1); 1.193 + SkScalar z = SkScalarDot(3, &fMat[2][0], 1, &src.fX, 1); 1.194 + dst->set(x, y, z); 1.195 +} 1.196 + 1.197 +/////////////////////////////////////////////////////////////////////////////// 1.198 + 1.199 +SkCamera3D::SkCamera3D() { 1.200 + this->reset(); 1.201 +} 1.202 + 1.203 +void SkCamera3D::reset() { 1.204 + fLocation.set(0, 0, -SkIntToScalar(576)); // 8 inches backward 1.205 + fAxis.set(0, 0, SK_Scalar1); // forward 1.206 + fZenith.set(0, -SK_Scalar1, 0); // up 1.207 + 1.208 + fObserver.set(0, 0, fLocation.fZ); 1.209 + 1.210 + fNeedToUpdate = true; 1.211 +} 1.212 + 1.213 +void SkCamera3D::update() { 1.214 + fNeedToUpdate = true; 1.215 +} 1.216 + 1.217 +void SkCamera3D::doUpdate() const { 1.218 + SkUnit3D axis, zenith, cross; 1.219 + 1.220 + fAxis.normalize(&axis); 1.221 + 1.222 + { 1.223 + SkScalar dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D*>(&fZenith), axis); 1.224 + 1.225 + zenith.fX = fZenith.fX - dot * axis.fX; 1.226 + zenith.fY = fZenith.fY - dot * axis.fY; 1.227 + zenith.fZ = fZenith.fZ - dot * axis.fZ; 1.228 + 1.229 + SkTCast<SkPoint3D*>(&zenith)->normalize(&zenith); 1.230 + } 1.231 + 1.232 + SkUnit3D::Cross(axis, zenith, &cross); 1.233 + 1.234 + { 1.235 + SkMatrix* orien = &fOrientation; 1.236 + SkScalar x = fObserver.fX; 1.237 + SkScalar y = fObserver.fY; 1.238 + SkScalar z = fObserver.fZ; 1.239 + 1.240 + orien->set(SkMatrix::kMScaleX, x * axis.fX - z * cross.fX); 1.241 + orien->set(SkMatrix::kMSkewX, x * axis.fY - z * cross.fY); 1.242 + orien->set(SkMatrix::kMTransX, x * axis.fZ - z * cross.fZ); 1.243 + orien->set(SkMatrix::kMSkewY, y * axis.fX - z * zenith.fX); 1.244 + orien->set(SkMatrix::kMScaleY, y * axis.fY - z * zenith.fY); 1.245 + orien->set(SkMatrix::kMTransY, y * axis.fZ - z * zenith.fZ); 1.246 + orien->set(SkMatrix::kMPersp0, axis.fX); 1.247 + orien->set(SkMatrix::kMPersp1, axis.fY); 1.248 + orien->set(SkMatrix::kMPersp2, axis.fZ); 1.249 + } 1.250 +} 1.251 + 1.252 +void SkCamera3D::patchToMatrix(const SkPatch3D& quilt, SkMatrix* matrix) const { 1.253 + if (fNeedToUpdate) { 1.254 + this->doUpdate(); 1.255 + fNeedToUpdate = false; 1.256 + } 1.257 + 1.258 + const SkScalar* mapPtr = (const SkScalar*)(const void*)&fOrientation; 1.259 + const SkScalar* patchPtr; 1.260 + SkPoint3D diff; 1.261 + SkScalar dot; 1.262 + 1.263 + diff.fX = quilt.fOrigin.fX - fLocation.fX; 1.264 + diff.fY = quilt.fOrigin.fY - fLocation.fY; 1.265 + diff.fZ = quilt.fOrigin.fZ - fLocation.fZ; 1.266 + 1.267 + dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D*>(&diff), 1.268 + *SkTCast<const SkUnit3D*>(SkTCast<const SkScalar*>(&fOrientation) + 6)); 1.269 + 1.270 + patchPtr = (const SkScalar*)&quilt; 1.271 + matrix->set(SkMatrix::kMScaleX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot)); 1.272 + matrix->set(SkMatrix::kMSkewY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot)); 1.273 + matrix->set(SkMatrix::kMPersp0, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot)); 1.274 + 1.275 + patchPtr += 3; 1.276 + matrix->set(SkMatrix::kMSkewX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot)); 1.277 + matrix->set(SkMatrix::kMScaleY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot)); 1.278 + matrix->set(SkMatrix::kMPersp1, SkScalarDotDiv(3, patchPtr, 1, mapPtr+6, 1, dot)); 1.279 + 1.280 + patchPtr = (const SkScalar*)(const void*)&diff; 1.281 + matrix->set(SkMatrix::kMTransX, SkScalarDotDiv(3, patchPtr, 1, mapPtr, 1, dot)); 1.282 + matrix->set(SkMatrix::kMTransY, SkScalarDotDiv(3, patchPtr, 1, mapPtr+3, 1, dot)); 1.283 + matrix->set(SkMatrix::kMPersp2, SK_Scalar1); 1.284 +} 1.285 + 1.286 +/////////////////////////////////////////////////////////////////////////////// 1.287 + 1.288 +Sk3DView::Sk3DView() { 1.289 + fInitialRec.fMatrix.reset(); 1.290 + fRec = &fInitialRec; 1.291 +} 1.292 + 1.293 +Sk3DView::~Sk3DView() { 1.294 + Rec* rec = fRec; 1.295 + while (rec != &fInitialRec) { 1.296 + Rec* next = rec->fNext; 1.297 + SkDELETE(rec); 1.298 + rec = next; 1.299 + } 1.300 +} 1.301 + 1.302 +void Sk3DView::save() { 1.303 + Rec* rec = SkNEW(Rec); 1.304 + rec->fNext = fRec; 1.305 + rec->fMatrix = fRec->fMatrix; 1.306 + fRec = rec; 1.307 +} 1.308 + 1.309 +void Sk3DView::restore() { 1.310 + SkASSERT(fRec != &fInitialRec); 1.311 + Rec* next = fRec->fNext; 1.312 + SkDELETE(fRec); 1.313 + fRec = next; 1.314 +} 1.315 + 1.316 +#ifdef SK_BUILD_FOR_ANDROID 1.317 +void Sk3DView::setCameraLocation(SkScalar x, SkScalar y, SkScalar z) { 1.318 + // the camera location is passed in inches, set in pt 1.319 + SkScalar lz = z * 72.0f; 1.320 + fCamera.fLocation.set(x * 72.0f, y * 72.0f, lz); 1.321 + fCamera.fObserver.set(0, 0, lz); 1.322 + fCamera.update(); 1.323 + 1.324 +} 1.325 + 1.326 +SkScalar Sk3DView::getCameraLocationX() { 1.327 + return fCamera.fLocation.fX / 72.0f; 1.328 +} 1.329 + 1.330 +SkScalar Sk3DView::getCameraLocationY() { 1.331 + return fCamera.fLocation.fY / 72.0f; 1.332 +} 1.333 + 1.334 +SkScalar Sk3DView::getCameraLocationZ() { 1.335 + return fCamera.fLocation.fZ / 72.0f; 1.336 +} 1.337 +#endif 1.338 + 1.339 +void Sk3DView::translate(SkScalar x, SkScalar y, SkScalar z) { 1.340 + fRec->fMatrix.preTranslate(x, y, z); 1.341 +} 1.342 + 1.343 +void Sk3DView::rotateX(SkScalar deg) { 1.344 + fRec->fMatrix.preRotateX(deg); 1.345 +} 1.346 + 1.347 +void Sk3DView::rotateY(SkScalar deg) { 1.348 + fRec->fMatrix.preRotateY(deg); 1.349 +} 1.350 + 1.351 +void Sk3DView::rotateZ(SkScalar deg) { 1.352 + fRec->fMatrix.preRotateZ(deg); 1.353 +} 1.354 + 1.355 +SkScalar Sk3DView::dotWithNormal(SkScalar x, SkScalar y, SkScalar z) const { 1.356 + SkPatch3D patch; 1.357 + patch.transform(fRec->fMatrix); 1.358 + return patch.dotWith(x, y, z); 1.359 +} 1.360 + 1.361 +void Sk3DView::getMatrix(SkMatrix* matrix) const { 1.362 + if (matrix != NULL) { 1.363 + SkPatch3D patch; 1.364 + patch.transform(fRec->fMatrix); 1.365 + fCamera.patchToMatrix(patch, matrix); 1.366 + } 1.367 +} 1.368 + 1.369 +#include "SkCanvas.h" 1.370 + 1.371 +void Sk3DView::applyToCanvas(SkCanvas* canvas) const { 1.372 + SkMatrix matrix; 1.373 + 1.374 + this->getMatrix(&matrix); 1.375 + canvas->concat(matrix); 1.376 +}