Skip to content

Getting colors from polygons? #53

Closed

Description

@breiler

I don't know if I have the wrong expectation, but I would like to have the polygons to inherit their colors from the original CSG. I can look into it if this is something that should work.

Right now the colors seems to be random, and they become different every time:

    @Test
    public void polygonsShouldGetColorFromCSG() {
        CSG cube = new Cube()
                .toCSG()
                .setColor(Color.BLUE);
        assertEquals(Color.BLUE, cube.getColor());
        
        String colorAsString = Color.BLUE.getRed() + " " + Color.BLUE.getGreen() + " " + Color.BLUE.getBlue();
        cube.getPolygons().forEach(polygon -> {
            assertTrue(polygon.getStorage().getValue("material:color").isPresent());
            assertEquals("Expected the polygon to get the same color as the CSG", colorAsString, polygon.getStorage().getValue("material:color").get());
        });
    }

The result from the test gives different results every run, here is one example:

Expected the polygon to get the same color as the CSG expected:<[0.0 0.0 1].0> but was:<[1.0 0.6470588445663452 0].0>
Expected :0.0 0.0 1.0
Actual   :1.0 0.6470588445663452 0.0
<Click to see difference>

In the long run I would like to be able to colorize the output like in this example:

CSG cube = new Cube(0.5).toCSG();
CSG sphere = new Sphere(0.36, 64, 32).toCSG();

CSG corners = cube.difference(sphere);
CSG result = cube.difference(corners)
        .setColor(Color.GRAY);

CSG text = CSG.text("Z-", 2)
        .setColor(Color.BLUE)
        .transformed(new Transform().scale(0.01).scale(1, 1, 1).rot(180, 0, 0).translate(-14, -10, 28));
result = result.dumbUnion(text);

text = CSG.text("Z+", 2)
        .setColor(Color.BLUE)
        .transformed(new Transform().scale(0.01).scale(1, 1, 1).translate(-14, -10, 28));
result = result.dumbUnion(text);

text = CSG.text("Y+", 2)
        .setColor(Color.GREEN)
        .transformed(new Transform().scale(0.01).scale(1, 1, 1).rot(90, 0, 180).translate(-14, -10, 28));
result = result.dumbUnion(text);

text = CSG.text("Y-", 2)
        .setColor(Color.GREEN)
        .transformed(new Transform().scale(0.01).scale(1, 1, 1).rot(270, 0, 0).translate(-14, -10, 28));
result = result.dumbUnion(text);

text = CSG.text("X-", 2)
        .setColor(Color.RED)
        .transformed(new Transform().scale(0.01).scale(1, 1, 1).rot(270, 90, 0).translate(-14, -10, 28));
result = result.dumbUnion(text);

text = CSG.text("X+", 2)
        .setColor(Color.RED)
        .transformed(new Transform().scale(0.01).scale(1, 1, 1).rot(270, 270, 0).translate(-14, -10, 28));
result = result.dumbUnion(text);

Activity

  1. breiler commented on Aug 10, 2024

    @breiler
    Author

    Thanks for the merge!

    It works ok for simple shapes, however the texts won't change color. I think that it boils down to the problem given in this scenario. Is it resonable that all polygons would change color to red when setting the color to the unioned shape?

    CSG cube1 = new Cube(10).toCSG()
            .setColor(Color.BLUE);
    
    CSG cube2 = new Cube(10).toCSG()
            .setColor(Color.RED)
            .transformed(new Transform().translate(10, 0, 0));
    
    CSG union = cube1.union(cube2);
    
    // I am expecting this to change the color of all polygons to red
    union.setColor(Color.RED);
  2. madhephaestus commented on Aug 11, 2024

    @madhephaestus
    Member

    Oh, so is the idea that you are trying to have some polygons within the shape to be one color, and other polygons another color? I think the issue you are running into is that the storage object is synced at the end of an operation. I think this is a good idea. In order to make it work we may need to remove the color from the storage object and put it instead in a new, separate variable in both the CSG and Polygon object. That way passing polygons around will preserve the color of that specific polygon through CSG operations. Id be happy to merge a PR with that change. It may have a side effect of increasing the memory footprint of the csg objects. I feel this feature is worth that change.

  3. breiler commented on Aug 11, 2024

    @breiler
    Author

    Oh, so is the idea that you are trying to have some polygons within the shape to be one color, and other polygons another color?

    Yes, and with the previous PR this now works. Gere is an example where I make a cube and color each face and then round its corners. The polygons that had different colors such as RED, GREEN and BLUE will keep its color information after the operations:

    CSG cube = new Cube(0.5).toCSG().setColor(Color.GRAY);
    
    cube = cube.union(new Cube(new Vector3d(0.5 / 2, 0, 0), new Vector3d(0.01, 0.5, 0.5)).toCSG().setColor(Color.RED));
    cube = cube.union(new Cube(new Vector3d(-0.5 / 2, 0, 0), new Vector3d(0.01, 0.5, 0.5)).toCSG().setColor(Color.RED));
    
    cube = cube.union(new Cube(new Vector3d(0, 0.5 / 2, 0), new Vector3d(0.5, 0.01, 0.5)).toCSG().setColor(Color.GREEN));
    cube = cube.union(new Cube(new Vector3d(0, -0.5 / 2, 0), new Vector3d(0.5, 0.01, 0.5)).toCSG().setColor(Color.GREEN));
    
    cube = cube.union(new Cube(new Vector3d(0, 0, 0.5 / 2), new Vector3d(0.5, 0.5, 0.01)).toCSG().setColor(Color.BLUE));
    cube = cube.union(new Cube(new Vector3d(0, 0, -0.5 / 2), new Vector3d(0.5, 0.5, 0.01)).toCSG().setColor(Color.BLUE));
    
    CSG sphere = new Sphere(0.36, 64, 32).toCSG().setColor(Color.GRAY);
    CSG corners = cube.difference(sphere);
    
    CSG result = cube.difference(corners);

    image

    I think the issue you are running into is that the storage object is synced at the end of an operation. I think this is a good idea. In order to make it work we may need to remove the color from the storage object and put it instead in a new, separate variable in both the CSG and Polygon object. That way passing polygons around will preserve the color of that specific polygon through CSG operations.

    I don't want the colors to be synced, I like them to be retained from the original. The problem that I encountered is that once a gemometric operation has been done (such as with a union) there is no way to access the color of all the polygons in a neat way. I expect that the colors should be able to be overridden if I choose to.

    This problem only gets clear when creating an object where the polygons do not share the same storage. Take this for instance, I would expect this to create a text which is black:

    CSG text = CSG.text("Z-", 1).setColor(Color.BLACK);

    But each component of the extruded text will get their own storage (), so setting the color will have no effect (it will use the default randomly generated color from PropertyStorage.java#L65).

    image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions