text: /* include/graphics/SkCamera.h
  **
  ** Copyright 2006, Google Inc.
  **
  ** Licensed under the Apache License, Version 2.0 (the "License"); 
  ** you may not use this file except in compliance with the License. 
  ** You may obtain a copy of the License at 
  **
  **     http://www.apache.org/licenses/LICENSE-2.0 
  **
  ** Unless required by applicable law or agreed to in writing, software 
  ** distributed under the License is distributed on an "AS IS" BASIS, 
  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  ** See the License for the specific language governing permissions and 
  ** limitations under the License.
  */
  
  
  
  //  Inspired by Rob Johnson's most excellent QuickDraw GX sample code
  
  #ifndef SkCamera_DEFINED
  #define SkCamera_DEFINED
  
  #include "Sk64.h"
  #include "SkMatrix.h"
  
  class SkCanvas;
  
  #ifdef SK_SCALAR_IS_FIXED
      typedef SkFract SkUnitScalar;
      #define SK_UnitScalar1          SK_Fract1
      #define SkUnitScalarMul(a, b)   SkFractMul(a, b)
      #define SkUnitScalarDiv(a, b)   SkFractDiv(a, b)
  #else
      typedef float   SkUnitScalar;
      #define SK_UnitScalar1          SK_Scalar1
      #define SkUnitScalarMul(a, b)   SkScalarMul(a, b)
      #define SkUnitScalarDiv(a, b)   SkScalarDiv(a, b)
  #endif
  
  struct SkUnit3D {
      SkUnitScalar    fX, fY, fZ;
  
      void set(SkUnitScalar x, SkUnitScalar y, SkUnitScalar z)
      {
          fX = x; fY = y; fZ = z;
      }
      static SkUnitScalar Dot(const SkUnit3D&, const SkUnit3D&);
      static void Cross(const SkUnit3D&, const SkUnit3D&, SkUnit3D* cross);
  };
  
  struct SkPoint3D {
      SkScalar    fX, fY, fZ;
  
      void set(SkScalar x, SkScalar y, SkScalar z)
      {
          fX = x; fY = y; fZ = z;
      }
      SkScalar    normalize(SkUnit3D*) const;
  };
  typedef SkPoint3D SkVector3D;
  
  struct SkMatrix3D {
      SkScalar    fMat[3][4];
      
      void reset();
  
      void setRow(int row, SkScalar a, SkScalar b, SkScalar c, SkScalar d = 0)
      {
          SkASSERT((unsigned)row < 3);
          fMat[row][0] = a;
          fMat[row][1] = b;
          fMat[row][2] = c;
          fMat[row][3] = d;
      }
  
      void setRotateX(SkScalar deg);
      void setRotateY(SkScalar deg);
      void setRotateZ(SkScalar deg);
      void setTranslate(SkScalar x, SkScalar y, SkScalar z);
      
      void preRotateX(SkScalar deg);
      void preRotateY(SkScalar deg);
      void preRotateZ(SkScalar deg);
      void preTranslate(SkScalar x, SkScalar y, SkScalar z);
  
      void setConcat(const SkMatrix3D& a, const SkMatrix3D& b);
      void mapPoint(const SkPoint3D& src, SkPoint3D* dst) const;
      void mapVector(const SkVector3D& src, SkVector3D* dst) const;
  
      void mapPoint(SkPoint3D* v) const
      {
          this->mapPoint(*v, v);
      }
      void mapVector(SkVector3D* v) const
      {
          this->mapVector(*v, v);
      }
  };
  
  class SkPatch3D {
  public:
      SkPatch3D();
  
      void    reset();
      void    transform(const SkMatrix3D&, SkPatch3D* dst = NULL) const;
  
      // dot a unit vector with the patch's normal
      SkScalar dotWith(SkScalar dx, SkScalar dy, SkScalar dz) const;
      SkScalar dotWith(const SkVector3D& v) const
      {
          return this->dotWith(v.fX, v.fY, v.fZ);
      }
  
      // depreicated, but still here for animator (for now)
      void rotate(SkScalar x, SkScalar y, SkScalar z) {}
      void rotateDegrees(SkScalar x, SkScalar y, SkScalar z) {}
  
  private:
  public: // make public for SkDraw3D for now
      SkVector3D  fU, fV;
      SkPoint3D   fOrigin;
      
      friend class SkCamera3D;
  };
  
  class SkCamera3D {
  public:
      SkCamera3D();
  
      void reset();
      void update();
      void patchToMatrix(const SkPatch3D&, SkMatrix* matrix) const;
  
      SkPoint3D   fLocation;
      SkPoint3D   fAxis;
      SkPoint3D   fZenith;
      SkPoint3D   fObserver;
  
  private:
      mutable SkMatrix    fOrientation;
      mutable bool        fNeedToUpdate;
  
      void doUpdate() const;
  };
  
  class Sk3DView : SkNoncopyable {
  public:
      Sk3DView();
      ~Sk3DView();
  
      void save();
      void restore();
  
      void translate(SkScalar x, SkScalar y, SkScalar z);
      void rotateX(SkScalar deg);
      void rotateY(SkScalar deg);
      void rotateZ(SkScalar deg);
  
      void getMatrix(SkMatrix*) const;
      void applyToCanvas(SkCanvas*) const;
  
      SkScalar dotWithNormal(SkScalar dx, SkScalar dy, SkScalar dz) const;
      
  private:
      struct Rec {
          Rec*        fNext;
          SkMatrix3D  fMatrix;
      };
      Rec*        fRec;
      Rec         fInitialRec;
      SkCamera3D  fCamera;
  };
  
  #endif
  
  