public void Drag(Vector2d pt)
        {
            edPt = pt;
            edVec = MapToSphere(pt);

            double epsilon = 1.0e-5;
            Vector3d prep = stVec.Cross(edVec);

            if (prep.Length() > epsilon)
                quat = new Vector4d(prep, stVec.Dot(edVec));
            else
                quat = new Vector4d();
        }
        public static Matrix3d QuatToMatrix3d(Vector4d q)
        {
            double n = q.Dot(q);
            double s = (n > 0.0) ? (2.0 / n) : 0.0f;

            double xs, ys, zs;
            double wx, wy, wz;
            double xx, xy, xz;
            double yy, yz, zz;
            xs = q.x * s;  ys = q.y * s;  zs = q.z * s;
            wx = q.w * xs; wy = q.w * ys; wz = q.w * zs;
            xx = q.x * xs; xy = q.x * ys; xz = q.x * zs;
            yy = q.y * ys; yz = q.y * zs; zz = q.z * zs;

            Matrix3d m = new Matrix3d();
            m[0,0] = 1.0 - (yy + zz); m[1,0] =        xy - wz;  m[2,0] =        xz + wy;
            m[0,1] =        xy + wz;  m[1,1] = 1.0 - (xx + zz); m[2,1] =        yz - wx;
            m[0,2] =        xz - wy;  m[1,2] =        yz + wx;  m[2,2] = 1.0 - (xx + yy);
            return m;
        }
 public Matrix4d OuterCross(Vector4d v)
 {
     Matrix4d m = new Matrix4d();
     m[0, 0] = x * v.x;
     m[0, 1] = x * v.y;
     m[0, 2] = x * v.z;
     m[0, 3] = x * v.w;
     m[1, 0] = y * v.x;
     m[1, 1] = y * v.y;
     m[1, 2] = y * v.z;
     m[1, 3] = y * v.w;
     m[2, 0] = z * v.x;
     m[2, 1] = z * v.y;
     m[2, 2] = z * v.z;
     m[2, 3] = z * v.w;
     m[3, 0] = w * v.x;
     m[3, 1] = w * v.y;
     m[3, 2] = w * v.z;
     m[3, 3] = w * v.w;
     return m;
 }
 public double Dot(Vector4d v)
 {
     return x*v.x + y*v.y + z*v.z + w*v.w;
 }
 public static Vector4d Min(Vector4d v1, Vector4d v2)
 {
     return new Vector4d(
         (v1.x < v2.x) ? v1.x : v2.x,
         (v1.y < v2.y) ? v1.y : v2.y,
         (v1.z < v2.z) ? v1.z : v2.z,
         (v1.w < v2.w) ? v1.w : v2.w
         );
 }
 public static Vector4d Max(Vector4d v1, Vector4d v2)
 {
     return new Vector4d(
         (v1.x > v2.x) ? v1.x : v2.x,
         (v1.y > v2.y) ? v1.y : v2.y,
         (v1.z > v2.z) ? v1.z : v2.z,
         (v1.w > v2.w) ? v1.w : v2.w
         );
 }
 public void End()
 {
     quat = new Vector4d();
     type = MotionType.None;
 }
 public void Transform(Matrix4d tran)
 {
     for (int i=0,j=0; i<vertexCount; i++,j+=3)
     {
         Vector4d v = new Vector4d(vertexPos[j], vertexPos[j + 1], vertexPos[j + 2], 1.0);
         v = tran * v;
         vertexPos[j] = v.x;
         vertexPos[j+1] = v.y;
         vertexPos[j+2] = v.z;
     }
 }
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            this.currMousePosition = new Vector2d(e.X, this.Height - e.Y);

            if (currMeshRecord == null) return;

            switch (Program.currentMode)
            {
                case Program.EnumOperationMode.Viewing:
                    switch (e.Button)
                    {
                        case MouseButtons.Left: ball.Drag(currMousePosition); break;
                        case MouseButtons.Middle: ball.Drag(currMousePosition / this.scaleRatio); break;
                        case MouseButtons.Right: ball.Drag(currMousePosition); break;
                    }
                    this.Refresh();
                    break;

                case Program.EnumOperationMode.Selection:
                    if (isMouseDown)
                        this.Refresh();
                    break;
                case Program.EnumOperationMode.Sketching:
                    if (e.Button == MouseButtons.Left  && currMeshRecord.CrossBoundaryBrushes != null)
                    {
                        if ((currMousePosition - prevMousePosition).Length() > 1)
                        {

                            this.strokeScreenPos.Add(currMousePosition);
                            prevMousePosition.x = currMousePosition.x;
                            prevMousePosition.y = currMousePosition.y;

                        }
                        this.Refresh();
                    }
                    break;

                case Program.EnumOperationMode.Moving:
                    if (isMouseDown)
                    {
                        Vector2d p = currMousePosition - new Vector2d(projectedCenter.x, projectedCenter.y);
                        int d = 0;
                        p.x += 100;
                        p.y += 100;
                        switch (e.Button)
                        {
                            case MouseButtons.Right: movingBall.Drag(p); break;
                            case MouseButtons.Left: movingBall.Drag(p / this.scaleRatio); d = 1; break;
                            case MouseButtons.Middle: movingBall.Drag(p); break;
                        }
                        Matrix4d currInverseTransformation = this.currTransformation.Inverse();
                        Matrix4d tran = currInverseTransformation * this.movingBall.GetMatrix() * currTransformation;
                        //Matrix4d tran = currTransformation * this.movingBall.GetMatrix() * currInverseTransformation;
                        double[] pos = this.currMeshRecord.Mesh.VertexPos;
                        for (int i = 0; i < handleIndex.Count; i++)
                        {
                            int j = handleIndex[i] * 3;
                            Vector4d q = new Vector4d((Vector3d)this.oldHandlePos[i], d);
                            q = tran * (q - this.handleCenter) + this.handleCenter;
                            pos[j] = q.x;
                            pos[j + 1] = q.y;
                            pos[j + 2] = q.z;
                        }

                        this.Refresh();
                    }
                    break;
            }
        }
        private void SortFaces()
        {
            Mesh m = currMeshRecord.Mesh;
            Matrix4d tran = ball.GetMatrix() * currTransformation;

            //sort faces
            FaceDepth[] d = new FaceDepth[m.FaceCount];
            for (int i = 0; i < m.FaceCount; i++)
            {
                Vector4d v = new Vector4d(new Vector3d(m.DualVertexPos, i * 3), 1.0);
                v = tran * v;
                d[i] = new FaceDepth(i, v.z);
            }
            Array.Sort(d);
            faceDepth = new int[m.FaceCount];
            for (int i = 0; i < m.FaceCount; i++)
                faceDepth[i] = d[i].index;
        }
 public static Vector4d operator *(Matrix4d m, Vector4d v)
 {
     Vector4d ret = new Vector4d();
     ret.x = m[0]*v.x  + m[1]*v.y  + m[2]*v.z  + m[3]*v.w;
     ret.y = m[4]*v.x  + m[5]*v.y  + m[6]*v.z  + m[7]*v.w;
     ret.z = m[8]*v.x  + m[9]*v.y  + m[10]*v.z + m[11]*v.w;
     ret.w = m[12]*v.x + m[13]*v.y + m[14]*v.z + m[15]*v.w;
     return ret;
 }
 public Matrix4d(Vector4d u, Vector4d v, Vector4d w, Vector4d x)
 {
     for (int i = 0; i < row_size; i++)
     {
         this[i, 0] = u[i];
         this[i, 1] = v[i];
         this[i, 2] = w[i];
         this[i, 3] = x[i];
     }
 }