简体   繁体   中英

Possible Java/Eclipse compiler bug? (no, just more stupidity as usual)

So I'm making a simple 3D graphics program. But I have a bug which is not directly related to the graphics.

I have a Triangle class that can translate, rotate, etc. I also have a Shape class that makes shapes from these triangles. So when I want to move a shape I can use a shape object to move all shapes uniformly.

The bug occurs when I try to move a shape. What happens is the translation is meant to be passed to all triangles in a row. But some of them are having the translation doubled.

After a lot of debugging I have found some weird results as it seems that some of the vertexes take on the translation of the vertex of the previous iteration, but only some of them . So therefore having the translation doubled.

I would include screenshots but my rep is not high enough.

My only explanation so far is either that either some of the vertexes share data. Or the data of some of these vertexes is being stored in run time and being used because the vertexes are similar.

Shape Class -> holds Triangle Objects

Triangle Class -> holds 3 Vertex Objects -> also has methods for display & translation

Vertex Class -> holds double x, double y, double z

May be worth noting that some of the vertexes for different triangles in the shape shape class have the same vertexes. But this should not be an issue as they are passed to different triangles.

Index: 0 // First Triangle
next check: 1.0 // The z value of the first vertex int the next triangle(index 1) 
1.0 // z val. before translation
1.010356248053852, dz: 0.009999833334166664 // z val. after translation
1.0 // z val. before translation
1.010356248053852, dz: 0.009999833334166664 // z val. after translation
1.0 // z val. before translation
1.010356248053852, dz: 0.009999833334166664 // z val. after translation

Index: 1 // Second triangle
next check: 1.5 // next check
1.010356248053852 // z val. before translation
1.0207124961077039, dz: 0.009999833334166664 // z val. after translation

The last two lines are the important ones. The first one should say 1.0, as the Index 0 said it would be (next check: 1.0). Yet when we get to the second triangle it has had the translation of the first triangle. So therefore giving the effect again.

This does not happen to all only some.

Thanks for any help or direction to articles in advance.

public Triangle(Point x, Point y, Point z, byte r, byte g, byte b, double fov)
{
    points = new Point[]{x, y, z};

    m_r = r;
    m_g = g;
    m_b = b;

    FOV = fov;
}
public void move(double x, double y, double z, double delta)
{
    for (int i = 0; i < 3; i++)
    {
        points[i].setDX(points[i].getDX() + (x * delta));
        points[i].setDY(points[i].getDY() + (y * delta));
        points[i].setDZ(points[i].getDZ() + (z * delta));
    }
}

/\\ important triangle code

public void move(double x, double y, double z, double delta)
{
    for (int i = 0; i < index.length; i++)
    {
        rs.triMove(index[i], x, y, z, delta);
    }
}

/\\ Shape move code rs is a collective space for all triangles but the bug started before this was added. The index is what position the triangle is being held in the array in rs.

public void triMove(int index, double x, double y, double z, double delta)
{
    triangles.get(index).move(x, y, z, delta);
}

/\\ RS class movement code.

Some maybe helpful pics. 制作矩形的两个三角形 Fine at the moment /\\ when still

搬家后 /\\ Bit broken now. two of these have doubled z values the other two are fine.

与立方体相同有些问题搞得一团糟 But they are still the same points going wrong and the same amount of broken?

But Some thing very Strange if the same rec is made with four triangles. 四个三角形还是一个三角形 But obviously this is a hacked way of fixing this and it won't work with more complex shapes.

A bit of a shot in the dark here since it's hard to know what the actual problem is since you posted so little code, but this really stood out to me:

May be worth noting that some of the vertexes for different triangles in the shape shape class have the same vertexes. But this should not be an issue as they are passed to different triangles.

I'd have each Triangle make a copy of each input Point to ensure that they're not interfering with another Triangle 's points.

ie:

public Triangle(Point x, Point y, Point z, byte r, byte g, byte b, double fov)
{
    // This is just an example since I have no idea what your
    // Point class actually looks like
    points = new Point[]{
        new Point(x.getX(), x.getY(), x.getZ()),
        new Point(y.getX(), y.getY(), y.getZ()),
        new Point(z.getX(), z.getY(), z.getZ()),
    };

    m_r = r;
    m_g = g;
    m_b = b;

    FOV = fov;
}

Update:

To explain what was happening, here is a short example:

Point.java :

public class Point {
    int x;
    int y;

    public Point(final int x, final int y) {
        this.x = x;
        this.y = y;
        System.out.printf("Created point %s at (%s,%s)%n", this, x, y);
    }

    void move(int dx, int dy) {
        x += dx;
        y += dy;
        System.out.printf("Moved point %s (%s,%s) from (%s,%s) to (%s,%s)%n", this, dx, dy, x - dx, y - dy, x, y);
    }
}

Triangle.java :

public class Triangle {
    Point a;
    Point b;
    Point c;

    public Triangle(final Point a, final Point b, final Point c) {
        this.a = a;
        this.b = b;
        this.c = c;
        System.out.printf("Created triangle %s with points (%s, %s, %s)%n", this, this.a, this.b, this.c);
    }

    void move(int dx, int dy) {
        System.out.printf("Moving triangle %s (%s,%s)%n", this, dx, dy);
        a.move(dx, dy);
        b.move(dx, dy);
        c.move(dx, dy);
    }
}

Demo.java :

public class Demo {

    public static void main(String[] args) {
        Point p1 = new Point(0, 0);
        Point p2 = new Point(1, 0);
        Point p3 = new Point(0, 1);
        Point p4 = new Point(1, 1);

        Triangle t1 = new Triangle(p1, p2, p3);
        Triangle t2 = new Triangle(p2, p3, p4);

        t1.move(1, 1);
        t2.move(1, 1);
    }
}

When run, this produces the following output:

Created point Point@448139f0 at (0,0)
Created point Point@7cca494b at (1,0)
Created point Point@7ba4f24f at (0,1)
Created point Point@3b9a45b3 at (1,1)
Created triangle Triangle@7699a589 with points (Point@448139f0, Point@7cca494b, Point@7ba4f24f)
Created triangle Triangle@58372a00 with points (Point@7cca494b, Point@7ba4f24f, Point@3b9a45b3)
Moving triangle Triangle@7699a589 (1,1)
Moved point Point@448139f0 (1,1) from (0,0) to (1,1)
Moved point Point@7cca494b (1,1) from (1,0) to (2,1)
Moved point Point@7ba4f24f (1,1) from (0,1) to (1,2)
Moving triangle Triangle@58372a00 (1,1)
Moved point Point@7cca494b (1,1) from (2,1) to (3,2)
Moved point Point@7ba4f24f (1,1) from (1,2) to (2,3)
Moved point Point@3b9a45b3 (1,1) from (1,1) to (2,2)

As you can see, because the two triangles share some point objects, those points are moved twice.

If we change the constructor in Triangle to look like this instead:

public Triangle(final Point a, final Point b, final Point c) {
    this.a = new Point(a.x, a.y);
    this.b = new Point(b.x, b.y);
    this.c = new Point(c.x, c.y);
    System.out.printf("Created triangle %s with points (%s, %s, %s)%n", this, this.a, this.b, this.c);
}

we instead get the following output:

Created point Point@448139f0 at (0,0)
Created point Point@7cca494b at (1,0)
Created point Point@7ba4f24f at (0,1)
Created point Point@3b9a45b3 at (1,1)
Created point Point@7699a589 at (0,0)
Created point Point@58372a00 at (1,0)
Created point Point@4dd8dc3 at (0,1)
Created triangle Triangle@6d03e736 with points (Point@7699a589, Point@58372a00, Point@4dd8dc3)
Created point Point@568db2f2 at (1,0)
Created point Point@378bf509 at (0,1)
Created point Point@5fd0d5ae at (1,1)
Created triangle Triangle@2d98a335 with points (Point@568db2f2, Point@378bf509, Point@5fd0d5ae)
Moving triangle Triangle@6d03e736 (1,1)
Moved point Point@7699a589 (1,1) from (0,0) to (1,1)
Moved point Point@58372a00 (1,1) from (1,0) to (2,1)
Moved point Point@4dd8dc3 (1,1) from (0,1) to (1,2)
Moving triangle Triangle@2d98a335 (1,1)
Moved point Point@568db2f2 (1,1) from (1,0) to (2,1)
Moved point Point@378bf509 (1,1) from (0,1) to (1,2)
Moved point Point@5fd0d5ae (1,1) from (1,1) to (2,2)

And this works as expected since the two triangles no longer share any point objects.

A good way to avoid pitfalls like this is to always make copies of constructor arguments ( defensive copying ) or use immutable objects .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM