3d 中的点 space 无故接近 3d 中的平面 space

Point in 3d space approaching Planes in 3d space without reason

Java,程序,我有一个 Point3d class w/ x,y,z 坐标,以及以下平均函数:

public static Point3d average(Point3d a, Point3d b){
    a.add(b);
    a.x/=2;
    a.y/=2;
    a.z/=2;
    return a;
}

我也有这个 class 用于 3d 中的 2dPlane space 由 3 个 3d 点之间的三角形组成:

package com.funguscow.model;

import com.funguscow.obj.Point3d;
import com.funguscow.obj.Vector3d;

public class TriPlane {

    public Point3d a, b, c;
    private Vector3d normal;
    private float d;

    public TriPlane(Point3d x, Point3d y, Point3d z){
        a = x;
        b = y;
        c = z;
        Vector3d ab = Vector3d.Vector3dPMinus(a, b);
        //System.out.println(ab.x + ", " + ab.y + ", " + ab.z);
        normal = Vector3d.crossProduct(
                Vector3d.Vector3dPMinus(a, b),
                Vector3d.Vector3dPMinus(a, c));
        d = Vector3d.dotProduct(normal, Vector3d.VectorFromPoint3d(a));
    }

    public Vector3d getNormal(){
        return normal;
    }

    public float getRelativeOnPlane(Point3d test){
        //System.out.println(normal.x + ", " + normal.y + ", " + normal.z);
        return Vector3d.dotProduct(normal, Vector3d.VectorFromPoint3d(test)) - d;
    }

}

getRelativeOnPlane 是找出特定点在平面的哪一侧。它看起来对你有用吗?你能看到它有什么问题吗?

无论如何,这是个大问题,我有以下 class 的 CubeCollider,扩展了抽象的 class Collider,它设置了六个 TriPlanes 来检查一个点是否在立方体内或不是:

package com.funguscow.model;

import com.funguscow.obj.Point3d;
import com.funguscow.obj.Vector3d;

public class CubeCollider extends Collider{
    public Point3d a, b, c, d, e, f, g, h;

    public CubeCollider(){
        a = new Point3d(0, 0, 0);
        b = new Point3d(0, 0, 0);
        c = new Point3d(0, 0, 0);
        d = new Point3d(0, 0, 0);
        e = new Point3d(0, 0, 0);
        f = new Point3d(0, 0, 0);
        g = new Point3d(0, 0, 0);
        h = new Point3d(0, 0, 0);
    }

    public CubeCollider setCube(Cube cube){
        return setCube((float)cube.lines.get(0).start.x,
                (float)cube.lines.get(0).start.y, (float)cube.lines.get(0).start.z,
                (float)cube.lines.get(11).end.x, (float)cube.lines.get(11).end.y, (float)cube.lines.get(11).end.z);
    }

    public CubeCollider setCube(float x, float y, float z, float m, float n, float o){
        //System.out.println(x + ", " + y + ", " + z + ", " + m + ", " + n + ", " + o);
        a.x = b.x = c.x = d.x = x;
        e.x = f.x = g.x = h.x = m;
        a.y = c.y = e.y = g.y = y;
        b.y = d.y = f.y = h.y = n;
        a.z = b.z = e.z = f.z = z;
        c.z = d.z = g.z = h.z = o;
        return this;
    }

    public boolean shouldBother(Point3d p){
        Point3d center = Point3d.average(a, h);
        float dist = Vector3d.Vector3dPMinus(p, center).getMagnitude();
        if(dist > Vector3d.Vector3dPMinus(center, a).getMagnitude())return false;
        if(dist > Vector3d.Vector3dPMinus(center, d).getMagnitude())return false;
        if(dist > Vector3d.Vector3dPMinus(center, g).getMagnitude())return false;
        return true;
    }

    public boolean isInBounds(Point3d p){
        //System.out.println((a.x - b.x) + ", " + (a.y - b.y) + ", " + (a.z - b.z));
        TriPlane[] collider = new TriPlane[]{new TriPlane(a, b, c),
                new TriPlane(a, b, e),
                new TriPlane(e, f, g),
                new TriPlane(c, d, g),
                new TriPlane(a, c, e),
                new TriPlane(b, d, f)};
        Point3d center = Point3d.average(a, h);

        for(TriPlane plane : collider){
            float should = plane.getRelativeOnPlane(center);
            int sign = (should < 0) ? -1 : (should == 0) ? 0 : 1;
            float real = plane.getRelativeOnPlane(p);
            int rSign = (real < 0) ? -1 : (real == 0) ? 0 : 1;
            System.out.println("Center: " + center.x + ", " + center.y + ", " + center.z);
            System.out.println("Bound check: " + should + ", " + real);
            if(sign != rSign && real != 0 && should != 0)return false;
        }
        return true;
    }
}

函数isInBounds中的点'center'使用了点a和h的平均值,但是有一些问题。来自 isInBounds 函数的 "Bound check: " 之类的调试报告 'should'(平面法向量和点中心的点积)接近零,直到经过几次(十几个)迭代检查,它正好变成 0.0。有人可以告诉我为什么会这样吗? 如果我没记错的话,函数 getRelativePointOnPlane 返回零应该意味着该点在 on 平面上,但是它正在测试(中心)的点,如果我没记错的话,应该是所有平面之间,而不是任何平面之间。是我使用这些函数的逻辑错了,还是我写函数的代码写错了?

这是控制台读取的内容:

Center: 100.0, 100.0, 40.0
Bound check: -4000000.0, -1.2E7
Center: 100.0, 100.0, 40.0
Bound check: 4000000.0, 4800000.0
Center: 100.0, 100.0, 40.0
Bound check: 4000000.0, -4000000.0
Center: 50.0, 50.0, -10.0
Bound check: -2000000.0, -1000000.0
Center: 50.0, 50.0, -10.0
Bound check: 2000000.0, 5000000.0
Center: 50.0, 50.0, -10.0
Bound check: 2000000.0, -4000000.0
Center: 25.0, 25.0, -35.0
Bound check: -1000000.0, 5100000.0
Center: 12.5, 12.5, -47.5
Bound check: -500000.0, 8650000.0
Center: 6.25, 6.25, -53.75
Bound check: -250000.0, 1.0875E7
Center: 3.125, 3.125, -56.875
Bound check: -125000.0, 1.24125E7
Center: 1.5625, 1.5625, -58.4375
Bound check: -62500.0, 1.359375E7
Center: 0.78125, 0.78125, -59.21875
Bound check: -31250.0, 1.4590625E7
Center: 0.390625, 0.390625, -59.609375
Bound check: -15625.0, 1.5492187E7
Center: 0.1953125, 0.1953125, -59.8046875
Bound check: -7812.5, 1.6344532E7
Center: 0.09765625, 0.09765625, -59.90234375
Bound check: -3906.25, 1.7171484E7
Center: 0.048828125, 0.048828125, -59.951171875
Bound check: -1953.0, 1.7985352E7
Center: 0.0244140625, 0.0244140625, -59.9755859375
Bound check: -976.5, 1.879248E7
Center: 0.01220703125, 0.01220703125, -59.98779296875
Bound check: -488.25, 1.9596142E7
Center: 0.006103515625, 0.006103515625, -59.993896484375
Bound check: -244.25, 2.0398024E7
Center: 0.0030517578125, 0.0030517578125, -59.9969482421875
Bound check: -122.25, 2.1198986E7
Center: 0.00152587890625, 0.00152587890625, -59.99847412109375
Bound check: -61.0, 2.1999482E7
Center: 7.62939453125E-4, 7.62939453125E-4, -59.999237060546875
Bound check: -30.5, 2.2799734E7
Center: 3.814697265625E-4, 3.814697265625E-4, -59.99961853027344
Bound check: -15.25, 2.3599864E7
Center: 1.9073486328125E-4, 1.9073486328125E-4, -59.99980926513672
Bound check: -7.5, 2.439993E7
Center: 9.5367431640625E-5, 9.5367431640625E-5, -59.99990463256836
Bound check: -4.0, 2.5199964E7
Center: 4.76837158203125E-5, 4.76837158203125E-5, -59.99995231628418
Bound check: -2.0, 2.599998E7
Center: 2.384185791015625E-5, 2.384185791015625E-5, -59.99997615814209
Bound check: -1.0, 2.6799992E7
Center: 1.1920928955078125E-5, 1.1920928955078125E-5, -59.999988079071045
Bound check: -0.5, 2.7599994E7
Center: 5.9604644775390625E-6, 5.9604644775390625E-6, -59.99999403953552
Bound check: 0.0, 2.8399998E7
Center: 5.9604644775390625E-6, 5.9604644775390625E-6, -59.99999403953552
Bound check: 0.25, 2.4399998E7
Center: 5.9604644775390625E-6, 5.9604644775390625E-6, -59.99999403953552
Bound check: 0.23841858, -4000000.0
Center: 2.9802322387695312E-6, 2.9802322387695312E-6, -59.99999701976776
Bound check: 0.0, 2.92E7

您的 average 方法更改了 a 的值,使其与平均点相同。所以你的立方体不是立方体,在你调用 average 之后 - 其中三个面已经旋转到新的位置。因此 collider 循环中发生的任何事情都是错误的。