Saving a PDF with P3D or P2D renderer

Hello everyone,

So basically, I’m trying to draw Mars in a 3D space, which I have to save to a PDF file. In order to do that more easily, I made a second project where I only make the texture which will overlay the sphere. It is looking how I want it to and I can copy this code to my original (3D) project without any problems. But when I want to save it to a PDF file (which I have to do because that’s the assignment), I just get a blank file and this error:
"texture() is not available with this renderer.
vertex(x, y, u, v) is not available with this renderer."

In order to simulate the exact same problem in the more simple code where I made the texture, I am using the P2D renderer. Just like expected, the same thing happens with the same error. I will be sharing this simplified code with you, because if we can solve the problem in this file, I think I can also solve it in my 3D file.

With only 1 month of programming experience so far, I really have no idea what to do anymore. If someone would be able to help me with this, that would be really appreciated.

import processing.pdf.*;

// A boolean variable that when set to true triggers the PDF recording process
boolean recordPDF = false;

PShape marsShape;
PGraphics marsGraphic;
PImage marsTexture;
PImage marsMask;

void draw() {
  // Begin making the PDF
  if (recordPDF) {
    beginRaw(PDF, "surface.pdf" ); // If you include "####" in the filename -- "3D-####.pdf" -- separate, numbered PDFs will be made for each frame that is rendered.
  }

  // End making the PDF

  if (recordPDF) {
    endRaw();
    recordPDF = false;
    println("done");
  }
}

// Make the PDF when the mouse is pressed

void mousePressed() {
  recordPDF = true;
  print("recording pdf...");
}

void setup() {
  size(1000, 1000, P2D);
  //beginRaw(PDF, "surface.pdf");
  background(0);
  noiseSeed(16);
  //Setting up a graphic, to draw a terrain which will overlay the sphere.
  marsGraphic = createGraphics(1000, 1000);
  //Creating an image which will serve as a mask, to generate a more natural terrain.
  marsMask = createImage(marsGraphic.width, marsGraphic.height, ARGB);
  float ydiff = 0; 
  float diff = 0.01;
  for (int y = 0; y <= marsGraphic.height; y++) {
    float xdiff = 0;
    for (int x = 0; x <= marsGraphic.width; x++) {
      float mask = map(noise(xdiff, ydiff), 0, 1, 0, 100);
      //float mask = random(0,100);
      color c = color(0, 0, 255-mask);
      marsMask.set(x, y, c);
      xdiff = xdiff + diff;
    }
    ydiff = ydiff + diff;
  }
  //Creating an image which will overlay the sphere.
  marsTexture = createImage(marsGraphic.width, marsGraphic.height, ARGB);
  //Calling the function which draws the graphics.
  graphic();
  //Copying the Graphics to the picture with will overlay the sphere.
  arrayCopy(marsGraphic.pixels, marsTexture.pixels);
  //Updating the image which will overlay the sphere.
  marsTexture.updatePixels();
  //Masking the picture which will overlay the sphere to make it look more natural.
  marsTexture.mask(marsMask);
  image(marsTexture, 0, 0);
  //endRaw();
}

color marsColor = color(158, 70, 46);

void graphic() {
  marsGraphic.beginDraw();
  marsGraphic.background(marsColor);
  marsGraphic.fill(139, 54, 32);
  //marsGraphic.strokeWeight(3);
  marsGraphic.stroke(100, 28, 10);

  for (int i = 0; i < 50; i++) {
    float r = random(50, 100);
    float x = random(marsGraphic.width);
    float y = random(marsGraphic.height);
    crater(x, y, r);
  }

  marsGraphic.endDraw();
}

void crater(float x, float y, float r) {
  float k = (sqrt(sq(r) / 2 ));
  float[] mx = new float[8];
  float[] my = new float[8];
  int var = 5;
  mx[0] = x + random(-r/10, r/10);
  my[0] = (y - r) + random(-r/var, r/var);
  mx[1] = (x + k) + random(-r/var, r/var);
  my[1] = (y - k) + random(-r/var, r/var);
  mx[2] = (x + r) + random(-r/var, r/var);
  my[2] = y + random(-r/var, r/var);
  mx[3] = (x + k) + random(-r/var, r/var);
  my[3] = (y + k) + random(-r/var, r/var);
  mx[4] = x + random(-r/var, r/var);
  my[4] = (y + r) + random(-r/var, r/var);
  mx[5] = (x - k) + random(-r/var, r/var);
  my[5] = (y + k) + random(-r/var, r/var);
  mx[6] = (x - r) + random(-r/var, r/var);
  my[6] = y + random(-r/var, r/var);
  mx[7] = (x - k) + random(-r/var, r/var);
  my[7] = (y - k) + random(-r/var, r/var);

  if (marsGraphic.get( int(x), int(y)) == marsColor &&
    marsGraphic.get( int(mx[0]), int(my[0])) == marsColor &&
    marsGraphic.get( int(mx[1]), int(my[1])) == marsColor &&
    marsGraphic.get( int(mx[2]), int(my[2])) == marsColor &&
    marsGraphic.get( int(mx[3]), int(my[3])) == marsColor &&
    marsGraphic.get( int(mx[4]), int(my[4])) == marsColor &&
    marsGraphic.get( int(mx[5]), int(my[5])) == marsColor &&
    marsGraphic.get( int(mx[6]), int(my[6])) == marsColor &&
    marsGraphic.get( int(mx[7]), int(my[7])) == marsColor) {

    marsGraphic.strokeWeight(map(r, 50, 100, 1, 3));

    marsGraphic.beginShape();
    marsGraphic.curveVertex(mx[7], my[7]); //7
    marsGraphic.curveVertex(mx[0], my[0]); //0
    marsGraphic.curveVertex(mx[1], my[1]); //1
    marsGraphic.curveVertex(mx[2], my[2]); //2
    marsGraphic.curveVertex(mx[3], my[3]); //3
    marsGraphic.curveVertex(mx[4], my[4]); //4
    marsGraphic.curveVertex(mx[5], my[5]); //5
    marsGraphic.curveVertex(mx[6], my[6]); //6
    marsGraphic.curveVertex(mx[7], my[7]); //7
    marsGraphic.curveVertex(mx[0], my[0]); //0
    marsGraphic.curveVertex(mx[1], my[1]); //1
    marsGraphic.endShape();
  }
}
1 Like

Hi, and welcome!

This worked. But the colors are a bit lighter, I’m not sure why that is.
I added a PGraphics pdf to render the pdf file to. I only post the difference here, the rest is as-is.

PGraphics pdf;

void draw() {
  // Begin making the PDF
  if (recordPDF) {
    //beginRaw(PDF, "surface.pdf" ); // If you include "####" in the filename -- "3D-####.pdf" -- separate, numbered PDFs will be made for each frame that is rendered.
    pdf = createGraphics(marsGraphic.width, marsGraphic.height, PDF, "surface.pdf");
    pdf.beginDraw();
    pdf.image(marsTexture, 0, 0);
    pdf.endDraw();
    pdf.dispose();
    recordPDF = false;
    println("done");
  }
}

Hi, @raron thanks for the response! I appreciate it.

After you responded, I’ve taken a look at the code you changed. It indeed worked, but I couldn’t get it to work in my 3D file unfortunately.
Also, the assignment was to submit a vector-based PDF. Since there was no way I was gonna get that to work in just 2 days, I decided to quickly made a new project instead. Now that it has been sumbmitted, I can respond.

I do know why the colors are a bit lighter though, it’s because there is no background in the PGraphics. So adding pdf.background(0); to the code fixes that.

Again tanks for the response. It did teach me another way to generate PDF files with processing, which might come in handy in the future :slight_smile:

1 Like