求射线与平面的交点,向量点乘和叉乘

 求射线与平面的交点,向量点乘和叉乘_第1张图片

 

    /**
     * 几何点
     */
    public static class Point {
        public final float x,y,z;
        public Point(float x,float y,float z){
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public Point translateX(float value) {
            return new Point(x,y+value,z);
        }
        public Point translateY(float value) {
            return new Point(x,y+value,z);
        }
        public Point translateZ(float value) {
            return new Point(x,y+value,z);
        }
        public Point translate(Vector vector) {
            return new Point(x+vector.x,y+vector.y,z+vector.z);
        }
    }


    /**
     * 方向 向量
     */
    public static class Vector {
        public final float x,y,z;
        public Vector(float x, float y, float z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public float length() {
            return (float) Math.sqrt(x*x + y*y + z*z);
        }
        //叉乘 是这这两个向量平面上,垂直生成新的向量,大小是两个向量构成四边形的面积
        public Vector crossProduct(Vector other) {
            return new Vector(
                    (y*other.z) - (z*other.y),
                    (x*other.z) - (z*other.x),
                    (x*other.y) - (y*other.x)
            );
        }
        //点乘  点乘的结果表示向量A在向量B方向上的投影与向量B模的的乘积
        public float dotProduct(Vector other) {
            return x * other.x +
                    y * other.y +
                    z * other.z ;
        }
        public Vector scale(float f) {
            return new Vector(x*f, y*f, z*f);
        }
    }

    /**
     * 射线 = 起点 + 方向向量
     */
    public static class Ray {
        public final Point point;
        public final Vector vector;

        public Ray(Point point, Vector vector) {
            this.point = point;
            this.vector = vector;
        }
    }

    /**
     * 平面 = 平面切点 + 法向量
     */
    public static class Plane {
        public final Point point;
        public final Vector normal;

        public Plane(Point point,Vector normal) {
            this.point = point;
            this.normal = normal;
        }
    }

    /**
     * 向量相减 A-B = BA
     * @param from A
     * @param to B
     * @return BA
     */
    public static Vector vectorBetween(Point from, Point to) {
        return new Vector(
                to.x-from.x,
                to.y-from.y,
                to.z-from.z);
    }

    // 包围球 与 射线 的相交测试接口
    public static boolean intersects(Ray ray, Sphere sphere) {
        return sphere.radius > distanceBetween(sphere.center, ray);
    }
    // 求出包围球中心点 与 射线的距离
    public static float distanceBetween(Point centerPoint, Ray ray) {
        // 第一个向量:开始点到球心
        Vector vStart2Center = vectorBetween(ray.point, centerPoint);
        // 第二个向量:结束点到球心
        Vector vEnd2Center = vectorBetween(
                ray.point.translate(ray.vector), // 结束点 = 开始点 + 方向向量。
                centerPoint);
        // 两个向量的叉积
        Vector crossProduct = vStart2Center.crossProduct(vEnd2Center);
        // 两个向量叉积的值大小 = 三角形面积 * 2
        float areaOf2 = crossProduct.length();
        // 求出射线的长度 = 三角形的底边长
        float lengthOfRay = ray.vector.length();
        // 高 = 面积*2 / 底边长
        float distanceFromSphereCenterToRay = areaOf2 / lengthOfRay;
        return distanceFromSphereCenterToRay;
    }

    // 射线 与 平面 相交点
    /*  p:交点  p0: 射线起点  u: 射线方向向量   p1: 平面上的点  n: 平面法向量
    p = p0 + tu
    n * (p - p1) = 0    //p 和 p1 都在平面上,所有p和p1组成的向量和法向量垂直
    n * (p0 + tu - p1) = 0   =>  n*p0 + n * tu - n * p1 = 0    =》
    t =  n * (p1 - p0) / n* u
    计算出t后, 可以算出交点 p = p0 + tu;
    */


    public static Point intersectionPoint(Ray ray, Plane tablePlane) {
        // 先找出 射点 到 平面点的 向量
        Vector rayToPlaneVector = vectorBetween(ray.point, tablePlane.point);
        // 然后就是 射点到平面点的向量 与 平面法向量的点积 / 射线方向向量 与 平面法向量的点积
        float scaleFactor = rayToPlaneVector.dotProduct(tablePlane.normal) / ray.vector.dotProduct(tablePlane.normal);
        // 根据缩放因子,缩放射线向量,射线平面交点 = 射点 + 缩放后的方向向量
        Point intersctionPoint = ray.point.translate(ray.vector.scale(scaleFactor));
        return intersctionPoint;
    }

求射线与平面的交点,向量点乘和叉乘_第2张图片

 

向量的点乘和向量的叉乘

向量点乘,是两个向量在一个方向的累计结果,结果只保留大小属性,抹去方向属性,就相等于降维;点积是两个向量的长度与它们夹角余弦的积。点乘的结果表示向量A在向量B方向上的投影与向量B模的的乘积

向量叉乘,是这这两个向量平面上,垂直生成新的向量,大小是两个向量构成四边形的面积。相等于生维。

        点乘(dot product)

求射线与平面的交点,向量点乘和叉乘_第3张图片

           叉乘(cross product)

求射线与平面的交点,向量点乘和叉乘_第4张图片

 

     /**
     * 方向 向量
     */
    public static class Vector {
        public final float x,y,z;
        public Vector(float x, float y, float z) {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        public float length() {
            return (float) Math.sqrt(x*x + y*y + z*z);
        }
        //叉乘 是这这两个向量平面上,垂直生成新的向量,大小是两个向量构成四边形的面积
        public Vector crossProduct(Vector other) {
            return new Vector(
                    (y*other.z) - (z*other.y),
                    (x*other.z) - (z*other.x),
                    (x*other.y) - (y*other.x)
            );
        }
        //点乘  点乘的结果表示向量A在向量B方向上的投影与向量B模的的乘积
        public float dotProduct(Vector other) {
            return x * other.x +
                    y * other.y +
                    z * other.z ;
        }
        public Vector scale(float f) {
            return new Vector(x*f, y*f, z*f);
        }
    }

你可能感兴趣的:(opengl,平面)