13d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips/*
23d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips * Copyright 2015 Google Inc.
33d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips *
43d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips * Use of this source code is governed by a BSD-style license that can be
53d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips * found in the LICENSE file.
63d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips */
73d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
83d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#ifndef SkPoint3_DEFINED
93d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#define SkPoint3_DEFINED
103d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
113d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#include "SkScalar.h"
123d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
133d32d768cd8b66c49c070495c08f7933b9dd2423robertphillipsstruct SK_API SkPoint3 {
143d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkScalar fX, fY, fZ;
153d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
163d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    static SkPoint3 Make(SkScalar x, SkScalar y, SkScalar z) {
173d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 pt;
183d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        pt.set(x, y, z);
193d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return pt;
203d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
213d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
223d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkScalar x() const { return fX; }
233d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkScalar y() const { return fY; }
243d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkScalar z() const { return fZ; }
253d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
263d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    void set(SkScalar x, SkScalar y, SkScalar z) { fX = x; fY = y; fZ = z; }
273d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
283d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    friend bool operator==(const SkPoint3& a, const SkPoint3& b) {
293d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return a.fX == b.fX && a.fY == b.fY && a.fZ == b.fZ;
303d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
313d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
323d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    friend bool operator!=(const SkPoint3& a, const SkPoint3& b) {
333d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return !(a == b);
343d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
353d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
363d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Returns the Euclidian distance from (0,0,0) to (x,y,z)
373d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
383d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    static SkScalar Length(SkScalar x, SkScalar y, SkScalar z);
393d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
403d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Return the Euclidian distance from (0,0,0) to the point
413d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
423d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkScalar length() const { return SkPoint3::Length(fX, fY, fZ); }
433d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
443d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Set the point (vector) to be unit-length in the same direction as it
453d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        already points.  If the point has a degenerate length (i.e., nearly 0)
463d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        then set it to (0,0,0) and return false; otherwise return true.
473d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
483d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    bool normalize();
493d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
503d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Return a new point whose X, Y and Z coordinates are scaled.
513d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
523d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkPoint3 makeScale(SkScalar scale) const {
533d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 p;
543d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        p.set(scale * fX, scale * fY, scale * fZ);
553d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return p;
563d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
573d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
583d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Scale the point's coordinates by scale.
593d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
603d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    void scale(SkScalar value) {
613d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        fX *= value;
623d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        fY *= value;
633d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        fZ *= value;
643d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
653d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
663d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Return a new point whose X, Y and Z coordinates are the negative of the
673d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        original point's
683d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
693d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkPoint3 operator-() const {
703d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 neg;
713d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        neg.fX = -fX;
723d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        neg.fY = -fY;
733d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        neg.fZ = -fZ;
743d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return neg;
753d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
763d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
773d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Returns a new point whose coordinates are the difference between
783d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        a and b (i.e., a - b)
793d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
803d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    friend SkPoint3 operator-(const SkPoint3& a, const SkPoint3& b) {
813d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 v;
823d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        v.set(a.fX - b.fX, a.fY - b.fY, a.fZ - b.fZ);
833d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return v;
843d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
853d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
863d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Returns a new point whose coordinates are the sum of a and b (a + b)
873d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
883d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    friend SkPoint3 operator+(const SkPoint3& a, const SkPoint3& b) {
893d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        SkPoint3 v;
903d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        v.set(a.fX + b.fX, a.fY + b.fY, a.fZ + b.fZ);
913d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return v;
923d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
933d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
942880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    /** Add v's coordinates to the point's
952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    */
962880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    void operator+=(const SkPoint3& v) {
972880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fX += v.fX;
982880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fY += v.fY;
992880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fZ += v.fZ;
1002880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1012880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1022880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    /** Subtract v's coordinates from the point's
1032880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    */
1042880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    void operator-=(const SkPoint3& v) {
1052880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fX -= v.fX;
1062880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fY -= v.fY;
1072880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        fZ -= v.fZ;
1082880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    }
1092880df2609eba09b555ca37be04b6ad89290c765Tom Hudson
1103d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    /** Returns the dot product of a and b, treating them as 3D vectors
1113d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    */
1123d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    static SkScalar DotProduct(const SkPoint3& a, const SkPoint3& b) {
1133d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return a.fX * b.fX + a.fY * b.fY + a.fZ * b.fZ;
1143d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
1153d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
1163d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    SkScalar dot(const SkPoint3& vec) const {
1173d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips        return DotProduct(*this, vec);
1183d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips    }
1193d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips};
1203d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
1213d32d768cd8b66c49c070495c08f7933b9dd2423robertphillipstypedef SkPoint3 SkVector3;
1222880df2609eba09b555ca37be04b6ad89290c765Tom Hudsontypedef SkPoint3 SkColor3f;
1233d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips
1243d32d768cd8b66c49c070495c08f7933b9dd2423robertphillips#endif
125