Map texture onto PATH shape

Hello,
I have a shape, which has a texture applied to it, but I would like the shape to be of type PATH, since this will allow the use of the contains(x,y) method. The problem is, if I change the shape type to PATH, no texture is shown. Is it possible to have a texture on a PATH shape?

Code:

public class View extends PApplet {
     PImage img;
     PShape myShape;

     public void setup() {
         img = loadImage("assets\\images\\test.jpg");

         myShape = createShape(PShape.PATH);
         textureMode(NORMAL);
         myShape.beginShape();
         myShape.texture(img);
         myShape.vertex(0, 0, 0, 0);
         myShape.vertex(100, 0, 1, 0);
         myShape.vertex(100, 100, 1, 1);
         myShape.vertex(0, 100, 0, 1);
         myShape.endShape(CLOSE);
     }

     public void settings() {
        size(displayHeight*3>>2, displayHeight*3>>2, P3D);
     }

     public void draw() {
         background(255);
         shape(myShape);
     }
 }

Hi @Frinkel ,

Please link to the previous thread for context (and the image file).

It depends on which graphics renderer you’re committing to. If you use the default JAVA2D you can use underlying AWT classes and methods to accomplish what you’ve described, both for contains and the mask.

cap

import processing.awt.PGraphicsJava2D;
import java.awt.geom.Path2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.Point;

PGraphicsJava2D graphics;
Image img;
Path2D.Float path = new Path2D.Float();

void settings() {
  size(400, 400, JAVA2D);
}

void setup() {
  graphics = (PGraphicsJava2D)getGraphics();

  float whalf = graphics.width / 2;
  float hhalf = graphics.height / 2;
  float s = 175.0f;
  float t = s * 0.552125f;

  path.moveTo(whalf + s, hhalf);
  path.curveTo(whalf + s, hhalf + t, whalf + t, hhalf + s, whalf, hhalf + s);
  path.curveTo(whalf - t, hhalf + s, whalf - s, hhalf + t, whalf - s, hhalf);
  path.curveTo(whalf - s, hhalf - t, whalf - t, hhalf - s, whalf, hhalf - s);
  path.curveTo(whalf + t, hhalf - s, whalf + s, hhalf - t, whalf + s, hhalf);
  path.closePath();

  // In case file test.jpeg is misplaced.
  //PImage pimg = createImage(512, 512, ARGB);
  //checker(0xff7f00ff, 0xff007fff, 8, 8, pimg);
  
  PImage pimg = loadImage("test.jpeg");
  pimg.resize(pimg.width/2, pimg.height/2);
  img = convertPImageToNative(pimg);
}

void draw() {
  blendMode(BLEND);
  background(0xff202020);
  graphics.g2.setClip(path);
  graphics.g2.drawImage(img, 0, 0, null);
  graphics.g2.setClip(null);

  Point point = new Point(mouseX, mouseY);
  boolean inside = path.contains(point);
  if (inside) {
    stroke(0xffffff00);
    strokeWeight(20);
    point(mouseX, mouseY);
  }
}

public static Image convertPImageToNative(PImage pimg) {

  int pw = pimg.pixelWidth;
  int ph = pimg.pixelHeight;
  pimg.loadPixels();
  BufferedImage imgNtv = new BufferedImage(pw, ph, pimg.format
    == PConstants.RGB ? BufferedImage.TYPE_INT_RGB
    : BufferedImage.TYPE_INT_ARGB);
  imgNtv.getRaster().setDataElements(0, 0, pw, ph, pimg.pixels);
  return imgNtv;
}

public static PImage checker(int a, int b, int cols,
  int rows, PImage target ) {

  target.loadPixels();

  int w = target.pixelWidth;
  int h = target.pixelHeight;
  int pd = target.pixelDensity;

  int limit = 2 * pd;
  int vcols = cols < 2 ? 2 : cols > w / limit ? w / limit : cols;
  int vrows = rows < 2 ? 2 : rows > h / limit ? h / limit : rows;

  int[] px = target.pixels;
  int len = px.length;

  int wch = w / vcols;
  int hchw = w * h / vrows;

  for ( int i = 0; i < len; ++i ) {
    px[i] = ( i % w / wch + i / hchw ) % 2 == 0 ? a : b;
  }

  target.format = PConstants.ARGB;
  target.updatePixels();
  return target;
}

For P2D, you could try reverse engineering the contains method

and then write a fragment shader to get a mask.

Best,
Jeremy

1 Like