5

I studied this question, but I still don't get it. The shortest possible code below shows a Pyramid totally grey, whereas I try to give the 6 triangles making up the pyramid different colors. So ... why don't these colors show up?

Note that I borrowed the getTexCoords().addAll(..) statement from that question, but clearly I still am doing something wrong. Is it the uv mapping? What is that anyway? I have seen a topological explanation (sphere <-> map), but what has that got to do with textures/colors...?

Appreciate your help - Michael

public class ColoredPyramid extends Application {
    public void start(Stage primaryStage) {
        Group root = new Group();
        Scene scene = new Scene(root, 200, 200, true);
        primaryStage.setTitle("Colored Pyramid");
        primaryStage.setScene(scene);
        primaryStage.show();

        TriangleMesh colouredPyramid = new TriangleMesh();
        float height = 100;
        float hypotenuse = 150;
        colouredPyramid.getPoints().addAll(0, 0, 0); //0-index:: top
        colouredPyramid.getPoints().addAll(0, height, -hypotenuse / 2); //1-index:: x=0, z=-hyp/2 ==> Closest to user
        colouredPyramid.getPoints().addAll(-hypotenuse / 2, height, 0); //2-index:: x=hyp/2,  z=0 ==> Leftest
        colouredPyramid.getPoints().addAll(hypotenuse / 2, height, 0);  //3-index:: x=hyp/2,  z=0 ==> rightest
        colouredPyramid.getPoints().addAll(0, height, hypotenuse / 2); ////4-index:: x=0, z=hyp/2  ==> Furthest from user

        //Next statement copied from stackoverflow.com/questions/26831871/coloring-individual-triangles-in-a-triangle-mesh-on-javafx
        colouredPyramid.getTexCoords().addAll(
            0.1f, 0.5f, // 0 red
            0.3f, 0.5f, // 1 green
            0.5f, 0.5f, // 2 blue
            0.7f, 0.5f, // 3 yellow
            0.9f, 0.5f  // 4 orange
        );

        colouredPyramid.getFaces().addAll(0, 0, 2, 0, 1, 0); //Left front face ---> RED
        colouredPyramid.getFaces().addAll(0, 1, 1, 1, 3, 1); //Right front face ---> GREEN
        colouredPyramid.getFaces().addAll(0, 2, 3, 2, 4, 2); //Right back face ---> BLUE
        colouredPyramid.getFaces().addAll(0, 3, 4, 3, 2, 3); //Left back face ---> RED
        colouredPyramid.getFaces().addAll(4, 4, 1, 4, 2, 4); //Base: left triangle face ---> YELLOW
        colouredPyramid.getFaces().addAll(4, 0, 3, 0, 1, 0); //Base: right triangle face ---> ORANGE

        MeshView meshView = new MeshView(colouredPyramid);
        Group group = new Group(meshView);
        group.setTranslateX(100);
        group.setTranslateY(80);
        root.getChildren().add(group);
    }

    public static void main(String[] args) {
        launch(args);
    }
}
José Pereda
  • 44,311
  • 7
  • 104
  • 132
M. Kemper
  • 75
  • 5
  • 1
    The first question you have to answer: where is the image that you will apply as texture? The texture coordinates you have set will look into that image. Hint: you need an image and set the materials diffuse map. – José Pereda Dec 13 '17 at 13:48
  • Thanks Jose, but ... I don't understand you. Why do I need an image to map vertices to textures? – M. Kemper Dec 13 '17 at 13:58
  • Btw, to the person who recommended I 'highlight' the code bits in my text: how do I do that? Thanks... – M. Kemper Dec 13 '17 at 13:59
  • @M.Kemper The image has the colors of the faces. See the question you originally referred to. For formatting code in your question, see https://meta.stackoverflow.com/questions/251361/how-do-i-format-my-code-blocks – James_D Dec 13 '17 at 14:06

1 Answers1

4

To understand how JavaFX 3D defines the color of any given 3D shape, have a look at the PhongMaterial javadoc (bold is mine):

The PhongMaterial class provides definitions of properties that represent a Phong shaded material. It describes the interaction of light with the surface of the Mesh it is applied to. The PhongMaterial reflects light in terms of a diffuse and specular component together with an ambient and a self illumination term. The color of a point on a geometric surface is mathematical function of these four components.

That means that you need to supply a material in the first place, and then you need to specify any of those components, for instance the diffuse component.

If you copy the image from the cited question:

palette

and create a material instance with it:

PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(new Image(getClass().getResourceAsStream("bB2jV.png")));
meshView.setMaterial(material);

you can see that this image is used to apply colors to your pyramid:

textured pyramid

If you modify the texture indices for the faces, you will get different colors, based on the texture coordinates.

To know more about this, you can have a look at the FXyz3D library, that provides a TexturedMesh class based in this concept. There you will find many different 3D shape "textured" primitives, that can use different texture "modes". Most of those modes don't even require an image, as this is created internally. This allows creating for instance color gradients based on mathematical functions.

This is an example of a TetrahedraMesh, that makes use a 3D function to define the density map:

TetrahedraMesh tetra = new TetrahedraMesh(10, 5, null);
tetra.setTextureModeVertices3D(1530, p -> p.magnitude());

TetrahedraMesh

José Pereda
  • 44,311
  • 7
  • 104
  • 132
  • Jose, many thanks - I got it to work, using a .png file. I am still bemused you cannot index into a color array (as after all that is effectively what that .png file is in a roundabout way, but ... it got me further, so thanks! – M. Kemper Dec 13 '17 at 15:04
  • JavaFX 3D provides in general basic implementations. But those can be easily extended. That's what we did with FXyz3D. Anyone is welcome to contribute with new ideas. And if the answer works for you, please mark it as accepted, so it will be helpful for others as well. – José Pereda Dec 13 '17 at 15:07
  • I'll have a look at FXyz3D (looks like a daunting package! ;-). – M. Kemper Dec 13 '17 at 15:33
  • @M.Kemper There is a [link](https://meta.stackexchange.com/a/5235/274088) on your [previous question](https://stackoverflow.com/a/47764553/2189127) that shows you how to mark an answer as accepted. – James_D Dec 13 '17 at 15:42
  • Just look at the grey check to the top left of the answer, the one close to the up or down votes. Only you can check the answer as valid, anyone, including you, with enough reputation can vote. – José Pereda Dec 13 '17 at 15:58
  • Once again an excellent answer by Jose. @M.Kemper if you have any questions on how to use FXyz3D let either Jose or I know! – Birdasaur Dec 15 '17 at 18:30