unexpected texture behaviour when combining PShapes via addChild()

edited August 2015 in GLSL / Shaders

I find I'm unable to mix textured and non-textured shapes in a PShape GROUP.

I am combining several 3D shapes into one group via PShapes addChild() method. everything works until I add a shape that has a texture map rather than a simple fill. At that point the other filled shapes inherit this texture map and it overides their former fill. This seems pathological to me. Are Texture maps a property of the shape or are they global to the group?. Since texture maps are set on a specific PShape object, not a GROUP, one expects that it is specific to that object, and not something that will carry over to the whole group. Is this an incorrect assumption? Since its possible to have each shape in a group have a different fill color one would expect that every shape can have a different texture map or no texture map at all. Perhaps, the problem is that one cannot mix texture mapped shapes with non-texture mapped shapes in a GROUP?

DETAILED EXAMPLE: I have 3 shapes:

HEX: an extruded hexagon created using QUAD_STRIP. shaded with a simple transparent fill color

BOX: an extruded square (i.e. a box with no top or bottom) created using QUAD_STRIP

LID: A simple polygon, with a simple fill, intended to be a lid for the hexagon

the BOX has no fill but does have a texture map from a PNG image with an alpha channel.

RESULTS: If I simply execute shape() on these sequentially in any order I get the expected result of seeing all three of these.

If I create the group via addChild() from just LID and HEX then I get back the expected result.

BUT! if I add in the texture mapped BOX to the group in any order what happens is the texture map from the BOX appears on the HEX. The color fill for the HEX or LID is gone. However the HEX appears to inherit the alpha level of it's original fill transparency.

This seems completely bonkers but is 100% reproducible. having one shape leak its texture onto another is unexpected unless, the texturemap were being applied globally to the GROUP and not to the individual shape it was set on.

REGRESSION: I was able to affect how the shape texture coupling happens by a simple change to my program. it still occurs but differently so this may be a clue.

I have a function that generates extruded polygons patterned after one of the PShape examples (for making a textured cylinder textured with an image of a LaChoy chop suey can). I added a selector that either uses a texture map image or sets a fill. However, I left in the (u,v) mapping code on the verticies even when I'm not applying the texture map (just filling). What's interesting about that, is that I noticed that it follows that vestigal (u,v) mapping when it inherits the texture from the other shape. if I remove that vestigal (u,v) mapping in the verticies for the filled shape then what happens is the HEX simply isn't visible at all. (no fill color). so it's acting like it is still being textured but the mapping is null so it gets no texture and no fill.

My conclusion at this point is that you cannot mix textured and non-textured shapes in the GROUP.

the following code is how I generate the extruded 3D polygons and their associated lids. I call this once with an image to generate a texture mapped BOX and then once with a null in the image field to generate a filled HEX. then I combine these shapes into one GROUP.

`
PShape[] extrudedPolygon(float r, float h, int detail, PImage tex) {

      textureMode(NORMAL);
      PShape lid = createShape();
      PShape sh = createShape();

      lid.beginShape();
      lid.fill(255,255,0);

      sh.beginShape(QUAD_STRIP);
      sh.noStroke();
      sh.noFill();

              // Check to see if an image was supplied.  if not, then revert to a fill instead of a texture
      if (tex != null) {
          sh.texture(tex);}
      else {
          sh.fill(50,100,200,100);
      };

      for (int i = 0; i <= detail; i++) {

        float angle = TWO_PI / detail;
        float x = sin(i * angle);
        float z = cos(i * angle);
        float u = (float) i /detail;

        sh.normal(x, 0, z);

               // if I don't have this check then I leave in a vestigal map on untextured shapes
        if (tex != null) { 
            sh.vertex(x * r, -h/2, z * r, 0, u);
            sh.vertex(x * r, +h/2, z * r, 1, u);  
        } else {
            sh.vertex(x * r, -h/2, z * r);
            sh.vertex(x * r, +h/2, z * r); 
        }
        lid.vertex(x * r, h/2,z*r);

      }
      sh.endShape(); 
      lid.endShape(CLOSE);

       return new PShape[]{sh,lid};o
    }`

thank you.

Sign In or Register to comment.