Show Image in P3D space?

I have a P3D window in full screen mode: fullScreen(P3D). I am rotating a 3d model around, and would like to overlay an image over the screen, so that it is always on top of all elements. How can I do this?

I’ve tried just image, and it doesn’t work for me.

Have a look at this: https://processing.org/reference/texture_.html Remember that you are in 3D, so you need to control the depth of the placement of this image if you dont want to obstruct the view of your previous laid out elements.

Kf

I don’t see anything. There’s no error message, it just doesn’t show. Here’s my code:

  noStroke();
  beginShape();
  texture(shuttleSpecs);
  vertex(0, 0, 10, 0);
  vertex(500, 0, 10, 0);
  vertex(500, 500, 10, 100);
  vertex(0, 500, 10, 100);
  endShape();

I’ve tried changing the z to 10, just in case the background image occupies 0. It had no effect.

shuttleSpecs is defined correctly. Thanks for the help.

Hi Mandelbrot,

I don’t see where you load the image into your sketch, so I’m assuming you’ve tested that and everything’s all good there. Vertex winding looks ok to me, too – clockwise from top-left, to top-right, to bottom-right, to bottom-left. I noticed that you’ve applied the same texture coordinates, (10, 0) to the first two vertex calls and again, with (10, 100), to the second two. All four should be different, but then again I imagine you’d be seeing streaks, rather than nothing.

I find it helps to set textureMode and textureWrap when applying textures to shapes in P3D. When textureMode is NORMAL you can use UV coordinates in the range [0, 1] without worrying about the texture image’s width and height as measured in pixels. Setting it to the default IMAGE allows you to work with pixel units. textureWrap set to CLAMP will leave streaks when the UV coordinates are out of bounds, while REPEAT speaks for itself. I supply int constants to beginShape and endShape just to be explicit, but I don’t see why it would matter here.

Here’s a sample setup:

001

float cx, cy, hw, hh, txscale = 2.0;
PImage texture;

size(500, 500, P3D);
textureMode(NORMAL);
textureWrap(REPEAT);
hw = width * 0.25;
hh = height * 0.25;
cx = width * 0.5;
cy = height * 0.5;
texture = loadImage("https://upload.wikimedia.org/" + 
  "wikipedia/commons/thumb/d/d6/" +
  "STS120LaunchHiRes-edit1.jpg/93px-STS120" +
  "LaunchHiRes-edit1.jpg");

beginShape(QUADS);
noStroke();
texture(texture);
vertex(cx - hw, cy - hh, 0.0, 0.0);
vertex(cx + hw, cy - hh, txscale, 0.0);
vertex(cx + hw, cy + hh, txscale, txscale);
vertex(cx - hw, cy + hh, 0.0, txscale);
endShape(CLOSE);

Hope that helps. Best,

1 Like

Thanks. I didn’t translate the text so it ended up rotating with the model. After adding:

translate(0, 0, 10), the image rotates with the model I have rotating around the screen. Why would that happen?

Thanks for the help!

Hi Mandelbrot,

Without seeing some code, or a screen capture, it’s hard to picture what you’re going for against what your current results are. To isolate transformations (translations, rotations and scales), you can wrap them in pushMatrix and popMatrix. This works a little differently with models loaded into a PShape object. Reviewing the P3D and/or 2D transformations tutorials may be helpful.

This is the previous example, updated so two elements are translated and rotated independently of one another.

001%20(2)

float cx, cy, hw, hh, txscale = 2.0;
PImage texture;
void setup() {
  size(500, 500, P3D);
  textureMode(NORMAL);
  textureWrap(REPEAT);
  textAlign(CENTER, CENTER);
  textMode(SHAPE);
  textSize(20.0);
  hw = width * 0.25;
  hh = height * 0.25;
  cx = width * 0.5;
  cy = height * 0.5;
  texture = loadImage("https://upload.wikimedia.org/" + 
    "wikipedia/commons/thumb/d/d6/" +
    "STS120LaunchHiRes-edit1.jpg/93px-STS120" +
    "LaunchHiRes-edit1.jpg");
}

void draw() {
  background(255.0);
  
  pushMatrix();
  translate(cx, cy);
  rotate(frameCount * 0.01);
  beginShape();
  noStroke();
  texture(texture);
  vertex(- hw, - hh, 0.0, 0.0, 0.0);
  vertex(+ hw, - hh, 0.0, txscale, 0.0);
  vertex(+ hw, + hh, 0.0, txscale, txscale);
  vertex(- hw, + hh, 0.0, 0.0, txscale);
  endShape();
  popMatrix();
  
  pushMatrix();
  fill(0.0);
  translate(mouseX, mouseY);
  rotate(frameCount * -0.05);
  text("Lorem ipsum", 0, 0);
  popMatrix();
}

Cheers!

Here’s a pastebin with all of my code: https://pastebin.com/HX9vKKYW

Essentially, the rotated shuttlecraft drags the text along with it.

Hi Mandelbrot,

Hmm, I wonder if creating a second graphics renderer with createGraphics would simplify things? This second P3D renderer could deal with the 3D elements in the sketch like the shuttle. The main renderer could then sandwich it between background and foreground elements (title menus, GUI/HUD). The technique is explained in more depth in the tutorial “Render Techniques.”

I tried to keep the following sample simple while respecting the complexity of your code. There was an error on line 38 because bg(0); was called without the function bg being defined, so I can’t say I got the full effect.

753

The teapot.obj file I used is from this Github gist.

PGraphics3D scene3d;
PShape teapot;

void setup() {
  size(512, 256, P3D);
  textAlign(CENTER, CENTER);
  textSize(20.0);
  scene3d = (PGraphics3D)createGraphics(width, height, P3D);
  teapot = loadShape("teapot.obj").getTessellation();
  float s = min(width, height) * 0.2;
  teapot.scale(s, -s, s); /* Flip model upside-down*/
}

void draw() {

  // Background elements.
  background(0.0, 0.0, 127.0);
  fill(255.0);
  text("BACKGROUND", width * 0.175, height * 0.5);

  draw3DScene();

  // After updating the 3d render, it can be displayed in
  // the main renderer with image or texture.
  image(scene3d, 0.0, 0.0, width, height);

  // Foreground elements.
  fill(127.0, 0.0, 0.0);
  ellipse(width * 0.75, height * 0.75, 150.0, 150.0);
  fill(255.0);
  text("FOREGROUND", width * 0.75, height * 0.75);
}

void draw3DScene() {
  float t = frameCount * 0.01;

  scene3d.beginDraw();
  scene3d.clear();
  scene3d.camera(
    0.0, 0.0, scene3d.height * 0.86602, 
    0.0, 0.0, 0.0, 
    0.0, 1.0, 0.0);
  scene3d.directionalLight(
    255.0, 255.0, 255.0, 
    0.0, -0.8, 0.6);

  // Translate and rotate both text label and teapot.
  scene3d.pushMatrix();
  scene3d.translate(cos(t) * 100.0, 0.0);
  scene3d.rotateY(t);
  scene3d.shape(teapot);

  // Turn lights off for text.
  scene3d.noLights();
  scene3d.fill(255.0);
  scene3d.text("LABEL", -teapot.getWidth(), 0.0);
  scene3d.popMatrix();

  scene3d.endDraw();
  scene3d.flush();
}

I just used ellipses, solid colors and text - but the idea should work with textures.

1 Like

Thanks! I ultimately decided to use PeasyCam’s convenient camera.beginHUD();, and it’s working so far.

2 Likes