Copying a PShape?

If I want to have several of the same 3D model (.obj file loaded), is there a way to to load it once and then copy that PShape. I want to avoid several calls to loadFile.

-Carmine

1 Like
PShape shape;
PShape shape1;
PShape shape2;

void setup() {

// load once
shape = loadShape("path/to/shape.obj");

// Same shape now in 3 PShapes
// Note that if you modify any of shape, shape1 and shape2 they will all be modified
shape1 = shape;
shape2 = shape;

// To avoid to have same instance in 3 variables, use this 'copy' trick
// Put shape as a child in a GROUP shape
shape1 = createShape(GROUP);
shape1.addChild(shape);

shape2 = createShape(GROUP);
shape2.addChild(shape);

}

void draw() {

//If you only need to show 3 of the same shape just call shape multiple times with the same shape
pushMatrix();
translate(0, 0, 0);
shape(shape);
translate(100, 0, 0);
shape(shape);
translate(100, 0, 0);
popMatrix();

}

There is no function like shape.copy() for the moment so you can’t entirely copy a PShape.
If you really want a complete copy, this is the way, but it is slow because we rebuild the shape :

PShape clone(PShape obj) {
  PShape shape = createShape();
  shape.beginShape();
  
  for(int i=0; i<obj.getVertexCount(); i++) {
    PVector vertex = obj.getVertex(i);

    obj.vertex(vertex.x, vertex.y, vertex.z);
  }

  shape.endShape();

  return shape;
}

You will need to iterate obj.getChildCount() and obj.getChild(i).getVertexCount() if your shape contains child PShape

1 Like

If you modify shape, will that be reflected when you draw shape1?

I’m not sure any of the available solutions are better than just loading the file multiple times.

Well a PShape.copy() would be the best solution here but it does not exist yet. It really depends on what you want to do, by putting the shape in a GROUP shape you now have acess to shape.translate(), shape.rotate() and shape.scale() whitout affecting the other shapes so it can help in some cases. But I think if you really want to modify a shape reconstruct it is faster than loading it i think.

It looks like there is currently draft code in PShape for using createShape as a copy command, like this:

PShape newShape = createShape(oldShape);    
1 Like

static protected PShape createShape(PApplet parent, PShape src) {

But they should stop limiting useful methods w/ private & protected! :japanese_ogre:

I believe (?) the dev team philosophy is to only make public those methods that they intend to support – in general they don’t make public interface that they can’t (or can’t yet) commit to ongoing support for, so that changing things won’t break stuff in ways that makes development harder and generates support tickets about internals.

For those planning to fork Processing and make custom changes who still want to use the full PDE app, the build instructions are on the wiki, here:

I did a full custom build once when I really really wanted a custom PGraphics methods for a project and couldn’t get an extended class to integrate due to createGraphics().

Note that for Mac you need to do the building on a Mac.

If you are on Linux, you can even build in a Docker container if you want, like this:

# Dockerfile for building Processing PDE on Linux using ant/jdk8
FROM frekele/ant:1.10.3-jdk8
WORKDIR /root
RUN apt-get -y install git
# point at your altered fork here:
RUN git clone https://github.com/processing/processing.git --depth 1
WORKDIR /root/processing/build/
RUN ant clean
RUN ant build

Here is a hack to access protected functions in classes :slight_smile:

public static class PShapeAcess extends PShape {
  
  public static PShape copyShape(PApplet parent, PShape shape) {
    return createShape(parent, shape);
  }
  
}

PShape shape;
PShape shapeCopy;

public void setup() {
  
  // Copy the shape
  shapeCopy = PShapeAcess.copyShape(this, shape);
}
3 Likes

Interesting static copy class hack! The key problem I recall having with trying to extend PGraphics in a non-static way was that createGraphics() returned PGraphics – so extending PGraphics with new methods did me no good without also writing my own create method. In this case, however, all we want are PShapes, so the hack fits the bill even though createShape() and loadShape() would present similar problems if we were trying to add non-static methods.

Here is a full demo sketch of Stephcraft’s PShape copy hack. Keep in mind – protected, not supported, not documented = could break anytime!

PShape mySquare;
PShape mySquareCopy;

void setup() {
  mySquare = createShape(RECT, 0, 0, 50, 50);
  mySquareCopy = PShapeAccess.copyShape(this, mySquare);
  mySquareCopy.setFill(0);
  shape(mySquare, 10, 10);
  shape(mySquareCopy, 40, 40);
}

static class PShapeAccess extends PShape {
  static PShape copyShape(PApplet parent, PShape src) {
    return createShape(parent, src);
  }
}
2 Likes