anchor.diff:      return this;
     }
   
  -  void frustum(double left, double right, double bottom, double top, double near, double far) {
  -    double rl = (right - left),
  -        tb = (top - bottom),
  -        fn = (far - near);
  +  void frustum(double left, double right, double bottom, double top,
  +      double near, double far) {
  +    double rl = (right - left), tb = (top - bottom), fn = (far - near);
       clear();
       array[0] = (near * 2) / rl;
       array[5] = (near * 2) / tb;
  
positive.code:   }
  
    void transposeRotation() {
      double a01 = array[1],
          a02 = array[2],
          a12 = array[6];
  
      array[1] = array[4];
      array[2] = array[8];
  
negative.code:  *  0, 0, 1, 0,
   *  x, y, z, 0]
   */
  class Matrix3 {
    Float32List array = new Float32List(3 * 3);
  
    Matrix3.fromM4(Matrix4 m) {
      array[0] = m.array[0];
      array[1] = m.array[1];
      array[2] = m.array[2];
      //
      array[3] = m.array[4];
      array[4] = m.array[5];
      array[5] = m.array[6];
      //
      array[6] = m.array[8];
      array[7] = m.array[9];
      array[8] = m.array[10];
    }
  
    void invert() {
      Float32List m = array;
      double a11 = m[8] * m[5] - m[5] * m[7];
      double a21 = -m[8] * m[1] + m[2] * m[7];
      double a31 = m[5] * m[1] - m[2] * m[4];
      double a12 = -m[8] * m[3] + m[5] * m[6];
      double a22 = m[8] * m[0] - m[2] * m[6];
      double a32 = -m[5] * m[0] + m[2] * m[3];
      double a13 = m[7] * m[3] - m[4] * m[6];
      double a23 = -m[7] * m[0] + m[1] * m[6];
      double a33 = m[4] * m[0] - m[1] * m[3];
  
      double det = m[0] * a11 + m[1] * a12 + m[2] * a13;
      if (det == 0) {
        throw "zero determinant ${m}";
      }
      double idet = 1.0 / det;
      m[0] = idet * a11;
      m[1] = idet * a21;
      m[2] = idet * a31;
      //
      m[3] = idet * a12;
      m[4] = idet * a22;
      m[5] = idet * a32;
      //
      m[6] = idet * a13;
      m[7] = idet * a23;
      m[8] = idet * a33;
    }
  
    void transpose() {
      Float32List m = array;
      double t;
  
      t = m[1];
      m[1] = m[3];
      m[3] = t;
  
      t = m[2];
      m[2] = m[6];
      m[6] = t;
  
      t = m[5];
      m[5] = m[7];
      m[7] = t;
    }
  }
  
  class Matrix4 {
    Float32List array = new Float32List(4 * 4);
  
    Matrix4() {
      identity();
    }
  
    static int RIGHTX = 0, RIGHTY = 4, RIGHTZ = 8;
    static int UPX = 1, UPY = 5, UPZ = 9;
    static int BACKX = 2, BACKY = 6, BACKZ = 10;
    static int POSX = 12, POSY = 13, POSZ = 14;
  
    double operator [](int index) {
      return array[index];
  