Java, програма, имам клас Point3d с координати 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;
}
Имам и този клас за 2dPlane в 3d пространство, образувано от триъгълник между 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 е да намерите от коя страна на равнината е определена точка. Изглежда ли, че трябва да работи за вас? Виждате ли някакви проблеми с него?
Както и да е, тук е големият проблем, имам следния клас за CubeCollider, разширяващ абстрактния клас 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 използва средната стойност на точките a и h, но има някакъв проблем. Отстраняването на грешки като "Bound check: " от функцията isInBounds съобщава "трябва" (точковото произведение на нормалния вектор на равнината и центъра на точката), доближава нула, докато след няколко (десетки) повторения на проверката стане точно 0,0. Може ли някой да ми каже защо се случва това? Ако не греша, връщането на нула за функцията getRelativePointOnPlane трябва да означава, че точката е на равнината, но точката, която тества (център), ако не греша, трябва да е междувсички самолети, а ненаникоя от тях. Грешна ли е логиката ми за това как да използвам тези функции или греша в кодирането, което използвах, за да напиша функциите?
Ето какво прочете конзолата:
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
System.out.println("Center: " + center.x + ", " + center.y + ", " + center.z);
и ето какво прочете конзолата: Център: 100.0, 100.0, 40.0 Обвързана проверка: -4000000.0, -1.2E7 Център: 100.0, 100.0, 40.0 Обвързана проверка: 4000000.0, 4800000.0 Център: 100.0, 100.0, 40 .0 Обвързан чек : 4000000.0, -4000000.0 Център: 50.0, 50.0, -10.0 Обвързана проверка: -2000000.0, -1000000.0 Оттам нататък първата стойност на обвързаната проверка продължи да се доближава до 0.0. Не можах да публикувам повече от това в коментара. - person Yaakov Schectman   schedule 18.01.2015