math.h

来源:互联网 发布:unity3d ai插件 编辑:程序博客网 时间:2024/05/22 00:22
#pragma once#include "PhysicsConfig.h"#include <iostream>#include <stdexcept>#include <vector>#include <assert.h>namespace Physics{const float MAX_FLOAT = 1e30f;const float MIN_FLOAT = -MAX_FLOAT;const float MIN_DIST = 0.001f;const float MIN_DIST_SQ = MIN_DIST * MIN_DIST;typedef D3DXMATRIX Matrix4x4;enum SIDE{    SIDE_ON     = 0,    SIDE_FRONT  = 1,    SIDE_BACK   = 2,    SIDE_BOTH   = 3,    SIDE_FORCE_DWORD = 0x7fffffff};enum AXIS_INDEX{    AXIS_X,    AXIS_Y,    AXIS_Z};inline float min2(float a, float b){    return a < b ? a : b;}inline float max2(float a, float b){    return a > b ? a : b;}inline bool amostZero(float d, float epsilon=0.0004f){    return d>-epsilon && d<epsilon;}////////////////////////////////////////////////////////////////////////////2维向量//////////////////////////////////////////////////////////////////////////class Vector2 : public D3DXVECTOR2{public:    Vector2() : D3DXVECTOR2(0.0f, 0.0f) {}    Vector2(float x_, float y_) : D3DXVECTOR2(x_, y_) {}    void init(float x_, float y_)    {        x = x_;        y = y_;    }    Vector2 operator+(const Vector2 & r)    {        return Vector2(x + r.x, y + r.y);    }    Vector2 operator-(const Vector2 & r)    {        return Vector2(x - r.x, y - r.y);    }};//////////////////////////////////////////////////////////////////////////// 3D vector//////////////////////////////////////////////////////////////////////////class Vector3 : public D3DXVECTOR3{public:    Vector3()    {}    Vector3(float fx, float fy, float fz)        :D3DXVECTOR3(fx, fy, fz)    {}    Vector3(const D3DXVECTOR3 & v)        : D3DXVECTOR3(v.x, v.y, v.z)    {}    Vector3(const Vector3 & v)        : D3DXVECTOR3(v.x, v.y, v.z)    {}    inline bool isZero() const    {        return x==0.0f && y==0.0f && z==0.0f;    }    inline void zero()    {         x = 0.0f; y=0.0f; z=0.0f;    }    //求负    inline void negative()    {        x = -x; y = -y; z=-z;    }    inline void set(float fx, float fy, float fz)     {         x = fx; y = fy; z = fz;    }    float lengthSq() const    {        return D3DXVec3LengthSq(this);    }    float length() const    {        return D3DXVec3Length(this);    }    float distToSq(const Vector3 & p) const    {        return D3DXVec3LengthSq(&(*this - p));    }    float distTo(const Vector3 & p) const    {        return D3DXVec3Length(&(*this - p));    }    void normalize()    {        D3DXVec3Normalize(this, this);    }    void normalize(Vector3 & out) const    {        D3DXVec3Normalize(&out, this);    }        //点乘    float dot(const Vector3& v) const    {        return (*this) * v;    }    //差乘    Vector3 cross(const Vector3& v) const    {        Vector3 temp;        D3DXVec3Cross(&temp, this, &v);        return temp;    }    //差乘    void cross(Vector3 & out, const Vector3& v) const    {        D3DXVec3Cross(&out, this, &v);    }    void toD3DXVec3(D3DXVECTOR3 & left) const    {        left.x = x;        left.y = y;        left.z = z;    }    void applyMatrix(const Matrix4x4 & mat)    {        D3DXVec3TransformCoord(this, this, &mat);    }    void applyNormalMatrix(const Matrix4x4 & mat)    {        D3DXVec3TransformNormal(this, this, &mat);    }    void applyMatrix(Vector3 & out, const Matrix4x4 & mat) const    {        D3DXVec3TransformCoord(&out, this, &mat);    }    void applyNormalMatrix(Vector3 & out, const Matrix4x4 & mat) const    {        D3DXVec3TransformNormal(&out, this, &mat);    }    bool tooClose(const Vector3 & v) const    {        return distToSq(v) <= MIN_DIST_SQ;    }    void projectTo2D(Vector2 & p) const;    void projectTo2D(int & u, int & v) const;int maxAxis() const;    float minValue() const    {        return min2(x, min2(y, z));    }    //////////////////////////////////////////////////////////////////////////    ///运算符重载    //////////////////////////////////////////////////////////////////////////        Vector3 operator - (const Vector3& v) const    {        return Vector3(x - v.x, y - v.y, z - v.z) ;    }    Vector3 operator-() const    {        return Vector3(-x, -y, -z);    }    Vector3 operator + (const Vector3& v) const    {        return Vector3(x + v.x, y + v.y, z + v.z) ;    }    float operator * (const Vector3& v) const    {        return x*v.x + y*v.y + z*v.z;    }    Vector3 operator * (float f) const    {        return Vector3(x * f, y * f, z * f) ;    }    Vector3 operator / (float f) const    {        return Vector3(x / f, y / f, z / f) ;    }    const Vector3 & operator=(const Vector3 & r)    {        set(r.x, r.y, r.z);        return *this;    }    const Vector3 & operator=(const D3DXVECTOR3 & r)    {        set(r.x, r.y, r.z);        return *this;    }    const Vector3 & operator+=(const Vector3 & r)    {        x += r.x; y += r.y; z += r.z;        return *this;    }    const Vector3 & operator-=(const Vector3 & r)    {        x -= r.x; y -= r.y; z -= r.z;        return *this;    }    const Vector3 & operator*=(float f)    {        x *= f; y *= f; z *= f;        return *this;    }    const Vector3 & operator /= (float f)    {        x /= f; y /= f; z /= f;        return *this;    }    float & operator[](int index)    {        if (index == AXIS_X) return x;        if (index == AXIS_Y) return y;        if (index == AXIS_Z) return z;        assert( 0 && "Vector3 index out of range");        return x;    }    float operator[](int index) const    {        if (index == AXIS_X) return x;        if (index == AXIS_Y) return y;        if (index == AXIS_Z) return z;        assert( 0 && "Vector3 index out of range");        return x;    }    friend std::ostream & operator<<(std::ostream & out, const Vector3 & v);    friend std::istream & operator>>(std::istream & in, Vector3 & v);};namespace MathConst{    const Vector3 vec3Max = Vector3(MAX_FLOAT, MAX_FLOAT, MAX_FLOAT);    const Vector3 vec3Min = Vector3(MIN_FLOAT, MIN_FLOAT, MIN_FLOAT);    const Vector3 vec3Zero = Vector3(0.0f, 0.0f, 0.0f);    const Vector3 vec3x = Vector3(1.0f, 0.0f, 0.0f);    const Vector3 vec3y = Vector3(0.0f, 1.0f, 0.0f);    const Vector3 vec3z = Vector3(0.0f, 0.0f, 1.0f);}////////////////////////////////////////////////////////////////////////////直线//////////////////////////////////////////////////////////////////////////class Line{public:    Line(){}    Line(const Vector3 & s, const Vector3 & e)        : start(s), end(e)    {}    float length() const    {        return start.distTo(end);    }    Vector3 direction() const    {        Vector3 dir = end - start;        dir.normalize();        return dir;    }    //线性插值    Vector3 interpolation(float ratio) const    {        return end*ratio + start*(1.0f-ratio);    }        //线性插值    Vector3 interpolation(float rs, float re) const    {        float down = rs + re;        if(down == 0.0f)        {            return start;        }        down = 1.0f/down;        //return interpolation(rs*down);        return (end*rs + start*re)*down;    }    //点在直线上的投影    Vector3 project(const Vector3 & point);    bool intersect(Vector3 & cross, const Line & line);public:    Vector3 start;    Vector3 end;};////////////////////////////////////////////////////////////////////////////三角形//////////////////////////////////////////////////////////////////////////class Triangle{public:    Triangle(){}    Triangle(const Vector3 & A, const Vector3 & B, const Vector3 & C)        :a(A), b(B), c(C)    {}    Vector3 normal() const    {        Vector3 ab = b - a;        Vector3 bc = c - b;        Vector3 n = ab.cross(bc);        n.normalize();        return n;    }    Vector3 & operator[](int i)    {        if(i == 0) return a;        if(i == 1) return b;        if(i == 2) return c;        throw std::out_of_range("Triangle index out of range");    }    const Vector3 & operator[](int i) const    {        if(i == 0) return a;        if(i == 1) return b;        if(i == 2) return c;        throw std::out_of_range("Triangle index out of range");    }    bool isPointIn(const Vector3 & p) const;    bool isLineIntersect(const Line & line, Vector3 * cross=NULL) const;    bool isSphereIntersect(const Vector3 & center, float radius, Vector3 * cross=NULL) const;        void applyMatrix(const Matrix4x4 & mat)    {        a.applyMatrix(mat);        b.applyMatrix(mat);        c.applyMatrix(mat);    }    bool intersect(const Triangle & triangle, const Vector3 & offset) const;    bool intersectRay(const Vector3 & start, const Vector3 & dir, float *pDist=NULL) const;public :    Vector3 a, b, c;};////////////////////////////////////////////////////////////////////////////平面//////////////////////////////////////////////////////////////////////////class Plane{public:    Plane()  : distance(0.0f)  {}    Plane(const Vector3 & n, const Vector3 & p)        : normal(n)    {        distance = normal.dot(p);    }    Plane(const Vector3 & n, float d)         : normal(n), distance(d)     {}    Plane(const Triangle & tri)         : normal(tri.normal())    {         distance = normal.dot(tri.a);    }    void set(const Vector3 & n, const Vector3 & p)       {        normal = n;        distance = normal.dot(p);    }    float distToPoint(const Vector3 & p) const    {        return normal.dot(p) - distance;    }    bool isIntersect(const Line & line, Vector3 * cross=NULL) const;    bool isIntersect(const Vector3 & start, const Vector3 & end, float * pPos=NULL) const;    bool isSphereIntersect(const Vector3 & center, float radius, Vector3 * cross=NULL);    int witchSide(const Vector3 & pt) const    {        float dt = distToPoint(pt);        if (amostZero(dt)) return SIDE_ON;        if (dt > 0) return SIDE_FRONT;        return SIDE_BACK;    }    int witchSide(const Triangle & tri)    {        int side = 0;        side |= witchSide(tri.a);        side |= witchSide(tri.b);        side |= witchSide(tri.c);        return side;    }    bool operator==(const Plane & p)    {        return normal == p.normal && distance == p.distance;    }public:    Vector3 normal;    float distance;};////////////////////////////////////////////////////////////////////////////多边形//////////////////////////////////////////////////////////////////////////typedef std::vector<Vector3> PolygonBase;class Polygon : public PolygonBase{public:    Polygon(): PolygonBase() {}    Polygon(int size) : PolygonBase(size) {}    Polygon(const Polygon& p) : PolygonBase(p) {}    Polygon(const Triangle & tri)    {        *this = tri;    }    const Polygon & operator=(const Triangle & tri)    {        addTriangle(tri);        return *this;    }    void genPanel(Plane & panel) const    {        assert(size() >= 3);        const_iterator it = begin();        const Vector3 &a = *it++;        const Vector3 &b = *it++;        const Vector3 &c = *it;        Vector3 ab = b - a;        Vector3 bc = c - b;        Vector3 n = ab.cross(bc);        n.normalize();        panel.set(n, a);    }    void addTriangle(const Triangle & tri)    {        addPoint(tri.a);        addPoint(tri.b);        addPoint(tri.c);    }    void split(const Plane & panel, Polygon & frontPoly, Polygon & backPoly) const;    void splitFront(const Plane & panel, Polygon & frontPoly) const;    bool choiceFront(const Plane & panel);    void addPoint(const Vector3 & p);    void adjudge();    float minDistToPanel(const Plane & panel);};class AABB{public:    Vector3 min;    Vector3 max;    void zero()    {        min = MathConst::vec3Max;        max = MathConst::vec3Min;    }    //正规化。aabb经过变换后,min可能要大于max。    void normalization();    void addPoint(const Vector3 & pt)    {        min.x = min2(min.x, pt.x);        min.y = min2(min.y, pt.y);        min.z = min2(min.z, pt.z);        max.x = max2(max.x, pt.x);        max.y = max2(max.y, pt.y);        max.z = max2(max.z, pt.z);    }    void addTriangle(const Triangle & tri)    {        addPoint(tri.a);        addPoint(tri.b);        addPoint(tri.c);    }    void getCenter(Vector3 & center) const    {        center = (max + min) * 0.5f;    }    void getDiameter(Vector3 & diameter) const    {        diameter = max - min;    }    void sub(const AABB & aabb)    {        min.x = max2(min.x, aabb.min.x);        min.y = max2(min.y, aabb.min.y);        min.z = max2(min.z, aabb.min.z);        max.x = min2(max.x, aabb.max.x);        max.y = min2(max.y, aabb.max.y);        max.z = min2(max.z, aabb.max.z);    }    void add(const AABB & aabb)    {    }    bool intersectsRay(const Vector3 & origin, const Vector3 & dir ) const;    bool intersect(const AABB & aabb) const;    bool clipLine(Vector3 & start, Vector3 & end ) const;    void applyMatrix(const Matrix4x4 & mat);    void applyMatrix(AABB & out, const Matrix4x4 & mat) const;};typedef std::vector<int> TriangleIndices;typedef std::vector<Triangle> TriangleSet;class FRect{public:    float left, top, right, bottom;    FRect() : left(0.0f), top(0.0f), right(0.0f), bottom(0.0f)    {    }    FRect(float l, float t, float r, float b)        : left(l), top(t), right(r), bottom(b)    {    }    float width() const { return right - left; }    float height() const { return bottom - top; }    bool isIn(float x_, float y_) const    {        if(x_ < left || x_ > right) return false;        if(y_ < top || y_ > bottom) return false;        return true;    }    void expand(const FRect & rc)    {        left = min2(left, rc.left);        top = min2(top, rc.top);        right = max2(right, rc.right);        bottom = max2(bottom, rc.bottom);    }    void expand(float x, float y)    {        left = min2(left, x);        top = min2(top, y);        right = max2(right, x);        bottom = max2(bottom, y);    }    void delta(float dx, float dy)    {        left -= dx;        right += dx;        top -= dy;        bottom += dy;    }    ///正规化。aabb经过变换后,min可能要大于max。    void normalization();    ///两个区域是否相交    bool isIntersect(const FRect & rc) const;    ///三角形xz所在区域,是否与当前区域相交    bool isTriangleXZIn(const Triangle & tri) const;};}//namespace Physics