8#include "matrix/SCamera.h"
15template <
typename Dst>
16Dst SkTCast(
const void *ptr)
30 void set(
float x,
float y,
float z)
36 static float Dot(
const SkUnit3D &,
const SkUnit3D &);
37 static void Cross(
const SkUnit3D &,
const SkUnit3D &, SkUnit3D *cross);
44 void set(
float x,
float y,
float z)
50 float normalize(SkUnit3D *)
const;
52typedef SkPoint3D SkVector3D;
60 void setRow(
int row,
float a,
float b,
float c,
float d = 0)
62 SASSERT((
unsigned)row < 3);
69 void setRotateX(
float deg);
70 void setRotateY(
float deg);
71 void setRotateZ(
float deg);
72 void setTranslate(
float x,
float y,
float z);
74 void preRotateX(
float deg);
75 void preRotateY(
float deg);
76 void preRotateZ(
float deg);
77 void preTranslate(
float x,
float y,
float z);
79 void setConcat(
const SkMatrix3D &a,
const SkMatrix3D &b);
80 void mapPoint(
const SkPoint3D &src, SkPoint3D *dst)
const;
81 void mapVector(
const SkVector3D &src, SkVector3D *dst)
const;
83 void mapPoint(SkPoint3D *v)
const
85 this->mapPoint(*v, v);
88 void mapVector(SkVector3D *v)
const
90 this->mapVector(*v, v);
99 void transform(
const SkMatrix3D &, SkPatch3D *dst = NULL)
const;
102 float dotWith(
float dx,
float dy,
float dz)
const;
103 float dotWith(
const SkVector3D &v)
const
105 return this->dotWith(v.fX, v.fY, v.fZ);
112 friend class SkCamera3D;
121 void patchToMatrix(
const SkPatch3D &, SMatrix *matrix)
const;
129 mutable SMatrix fOrientation;
130 mutable bool fNeedToUpdate;
132 void doUpdate()
const;
143 void translate(
float x,
float y,
float z);
144 void rotateX(
float deg);
145 void rotateY(
float deg);
146 void rotateZ(
float deg);
148 void setCameraLocation(
float x,
float y,
float z);
149 float getCameraLocationX();
150 float getCameraLocationY();
151 float getCameraLocationZ();
153 void getMatrix(SMatrix *)
const;
155 float dotWithNormal(
float dx,
float dy,
float dz)
const;
168static float SFloatDotDiv(
int count,
const float a[],
int step_a,
const float b[],
int step_b,
float denom)
171 for (
int i = 0; i < count; i++)
180static float SFloatDot(
int count,
const float a[],
int step_a,
const float b[],
int step_b)
183 for (
int i = 0; i < count; i++)
194float SkPoint3D::normalize(SkUnit3D *unit)
const
196 float mag = SFloatSqrt(fX * fX + fY * fY + fZ * fZ);
199 float scale = SFloatInvert(mag);
200 unit->fX = fX * scale;
201 unit->fY = fY * scale;
202 unit->fZ = fZ * scale;
206 unit->fX = unit->fY = unit->fZ = 0;
211float SkUnit3D::Dot(
const SkUnit3D &a,
const SkUnit3D &b)
213 return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;
216void SkUnit3D::Cross(
const SkUnit3D &a,
const SkUnit3D &b, SkUnit3D *cross)
222 float x = a.fY * b.fZ - a.fZ * b.fY;
223 float y = a.fZ * b.fX - a.fX * b.fY;
224 float z = a.fX * b.fY - a.fY * b.fX;
231SkPatch3D::SkPatch3D()
236void SkPatch3D::reset()
238 fOrigin.set(0, 0, 0);
239 fU.set(SK_Scalar1, 0, 0);
240 fV.set(0, -SK_Scalar1, 0);
243void SkPatch3D::transform(
const SkMatrix3D &m, SkPatch3D *dst)
const
247 dst = (SkPatch3D *)
this;
249 m.mapVector(fU, &dst->fU);
250 m.mapVector(fV, &dst->fV);
251 m.mapPoint(fOrigin, &dst->fOrigin);
254float SkPatch3D::dotWith(
float dx,
float dy,
float dz)
const
256 float cx = SFloatMul(fU.fY, fV.fZ) - SFloatMul(fU.fZ, fV.fY);
257 float cy = SFloatMul(fU.fZ, fV.fX) - SFloatMul(fU.fX, fV.fY);
258 float cz = SFloatMul(fU.fX, fV.fY) - SFloatMul(fU.fY, fV.fX);
260 return SFloatMul(cx, dx) + SFloatMul(cy, dy) + SFloatMul(cz, dz);
265void SkMatrix3D::reset()
267 memset(fMat, 0,
sizeof(fMat));
268 fMat[0][0] = fMat[1][1] = fMat[2][2] = SK_Scalar1;
271void SkMatrix3D::setTranslate(
float x,
float y,
float z)
273 memset(fMat, 0,
sizeof(fMat));
279void SkMatrix3D::setRotateX(
float degX)
283 s = SMatrix::SFloatSinCos(SkDegreesToRadians(degX), &c);
284 this->setRow(0, SK_Scalar1, 0, 0);
285 this->setRow(1, 0, c, -s);
286 this->setRow(2, 0, s, c);
289void SkMatrix3D::setRotateY(
float degY)
293 s = SMatrix::SFloatSinCos(SkDegreesToRadians(degY), &c);
294 this->setRow(0, c, 0, -s);
295 this->setRow(1, 0, SK_Scalar1, 0);
296 this->setRow(2, s, 0, c);
299void SkMatrix3D::setRotateZ(
float degZ)
303 s = SMatrix::SFloatSinCos(SkDegreesToRadians(degZ), &c);
304 this->setRow(0, c, -s, 0);
305 this->setRow(1, s, c, 0);
306 this->setRow(2, 0, 0, SK_Scalar1);
309void SkMatrix3D::preTranslate(
float x,
float y,
float z)
311 float col[3] = { x, y, z };
313 for (
int i = 0; i < 3; i++)
315 fMat[i][3] += SFloatDot(3, &fMat[i][0], 1, col, 1);
319void SkMatrix3D::preRotateX(
float degX)
323 this->setConcat(*
this, m);
326void SkMatrix3D::preRotateY(
float degY)
330 this->setConcat(*
this, m);
333void SkMatrix3D::preRotateZ(
float degZ)
337 this->setConcat(*
this, m);
340void SkMatrix3D::setConcat(
const SkMatrix3D &a,
const SkMatrix3D &b)
343 SkMatrix3D *c =
this;
345 if (
this == &a ||
this == &b)
349 for (
int i = 0; i < 3; i++)
351 for (
int j = 0; j < 3; j++)
353 c->fMat[i][j] = SFloatDot(3, &a.fMat[i][0], 1, &b.fMat[0][j], 4);
355 c->fMat[i][3] = SFloatDot(3, &a.fMat[i][0], 1, &b.fMat[0][3], 4) + a.fMat[i][3];
364void SkMatrix3D::mapPoint(
const SkPoint3D &src, SkPoint3D *dst)
const
366 float x = SFloatDot(3, &fMat[0][0], 1, &src.fX, 1) + fMat[0][3];
367 float y = SFloatDot(3, &fMat[1][0], 1, &src.fX, 1) + fMat[1][3];
368 float z = SFloatDot(3, &fMat[2][0], 1, &src.fX, 1) + fMat[2][3];
372void SkMatrix3D::mapVector(
const SkVector3D &src, SkVector3D *dst)
const
374 float x = SFloatDot(3, &fMat[0][0], 1, &src.fX, 1);
375 float y = SFloatDot(3, &fMat[1][0], 1, &src.fX, 1);
376 float z = SFloatDot(3, &fMat[2][0], 1, &src.fX, 1);
382SkCamera3D::SkCamera3D()
387void SkCamera3D::reset()
389 fLocation.set(0, 0, -SkIntToScalar(576));
390 fAxis.set(0, 0, SK_Scalar1);
391 fZenith.set(0, -SK_Scalar1, 0);
393 fObserver.set(0, 0, fLocation.fZ);
395 fNeedToUpdate =
true;
398void SkCamera3D::update()
400 fNeedToUpdate =
true;
403void SkCamera3D::doUpdate()
const
405 SkUnit3D axis, zenith, cross;
407 fAxis.normalize(&axis);
410 float dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D *>(&fZenith), axis);
412 zenith.fX = fZenith.fX - dot * axis.fX;
413 zenith.fY = fZenith.fY - dot * axis.fY;
414 zenith.fZ = fZenith.fZ - dot * axis.fZ;
416 SkTCast<SkPoint3D *>(&zenith)->normalize(&zenith);
419 SkUnit3D::Cross(axis, zenith, &cross);
422 SMatrix *orien = &fOrientation;
423 float x = fObserver.fX;
424 float y = fObserver.fY;
425 float z = fObserver.fZ;
427 orien->
set(kMScaleX, x * axis.fX - z * cross.fX);
428 orien->
set(kMSkewX, x * axis.fY - z * cross.fY);
429 orien->
set(kMTransX, x * axis.fZ - z * cross.fZ);
430 orien->
set(kMSkewY, y * axis.fX - z * zenith.fX);
431 orien->
set(kMScaleY, y * axis.fY - z * zenith.fY);
432 orien->
set(kMTransY, y * axis.fZ - z * zenith.fZ);
433 orien->
set(kMPersp0, axis.fX);
434 orien->
set(kMPersp1, axis.fY);
435 orien->
set(kMPersp2, axis.fZ);
439void SkCamera3D::patchToMatrix(
const SkPatch3D &quilt,
SMatrix *matrix)
const
444 fNeedToUpdate =
false;
447 const float *mapPtr = fOrientation.fMat;
448 const float *patchPtr;
452 diff.fX = quilt.fOrigin.fX - fLocation.fX;
453 diff.fY = quilt.fOrigin.fY - fLocation.fY;
454 diff.fZ = quilt.fOrigin.fZ - fLocation.fZ;
456 dot = SkUnit3D::Dot(*SkTCast<const SkUnit3D *>(&diff), *SkTCast<const SkUnit3D *>(fOrientation.fMat + 6));
458 patchPtr = (
const float *)&quilt;
459 matrix->
set(kMScaleX, SFloatDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
460 matrix->
set(kMSkewY, SFloatDotDiv(3, patchPtr, 1, mapPtr + 3, 1, dot));
461 matrix->
set(kMPersp0, SFloatDotDiv(3, patchPtr, 1, mapPtr + 6, 1, dot));
464 matrix->
set(kMSkewX, SFloatDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
465 matrix->
set(kMScaleY, SFloatDotDiv(3, patchPtr, 1, mapPtr + 3, 1, dot));
466 matrix->
set(kMPersp1, SFloatDotDiv(3, patchPtr, 1, mapPtr + 6, 1, dot));
468 patchPtr = (
const float *)(
const void *)&diff;
469 matrix->
set(kMTransX, SFloatDotDiv(3, patchPtr, 1, mapPtr, 1, dot));
470 matrix->
set(kMTransY, SFloatDotDiv(3, patchPtr, 1, mapPtr + 3, 1, dot));
471 matrix->
set(kMPersp2, SK_Scalar1);
478 fInitialRec.fMatrix.reset();
485 while (rec != &fInitialRec)
487 Rec *next = rec->fNext;
497 rec->fMatrix = fRec->fMatrix;
501void S3DView::restore()
503 SASSERT(fRec != &fInitialRec);
504 Rec *next = fRec->fNext;
509void S3DView::setCameraLocation(
float x,
float y,
float z)
512 float lz = z * 72.0f;
513 fCamera.fLocation.set(x * 72.0f, y * 72.0f, lz);
514 fCamera.fObserver.set(0, 0, lz);
518float S3DView::getCameraLocationX()
520 return fCamera.fLocation.fX / 72.0f;
523float S3DView::getCameraLocationY()
525 return fCamera.fLocation.fY / 72.0f;
528float S3DView::getCameraLocationZ()
530 return fCamera.fLocation.fZ / 72.0f;
533void S3DView::translate(
float x,
float y,
float z)
535 fRec->fMatrix.preTranslate(x, y, z);
538void S3DView::rotateX(
float deg)
540 fRec->fMatrix.preRotateX(deg);
543void S3DView::rotateY(
float deg)
545 fRec->fMatrix.preRotateY(deg);
548void S3DView::rotateZ(
float deg)
550 fRec->fMatrix.preRotateZ(deg);
553float S3DView::dotWithNormal(
float x,
float y,
float z)
const
556 patch.transform(fRec->fMatrix);
557 return patch.dotWith(x, y, z);
560void S3DView::getMatrix(
SMatrix *matrix)
const
565 patch.transform(fRec->fMatrix);
566 fCamera.patchToMatrix(patch, matrix);
572 : m_priv(new (S3DView))
586void SCamera::restore()
591void SCamera::translate(
float x,
float y,
float z)
593 m_priv->translate(x, y, z);
596void SCamera::rotateX(
float deg)
598 m_priv->rotateX(deg);
601void SCamera::rotateY(
float deg)
603 m_priv->rotateY(deg);
606void SCamera::rotateZ(
float deg)
608 m_priv->rotateZ(deg);
611void SCamera::setCameraLocation(
float x,
float y,
float z)
613 m_priv->setCameraLocation(x, y, z);
616float SCamera::getCameraLocationX()
618 return m_priv->getCameraLocationX();
622float SCamera::getCameraLocationY()
624 return m_priv->getCameraLocationY();
627float SCamera::getCameraLocationZ()
629 return m_priv->getCameraLocationZ();
632void SCamera::getMatrix(
SMatrix *out)
const
634 return m_priv->getMatrix(out);
The SMatrix class holds a 3x3 matrix for transforming coordinates. SMatrix does not have a constructo...
void set(int index, float value)
Sets the matrix element at the specified index.