# createShape() and lerp()

**URL:** <https://discourse.processing.org/t/createshape-and-lerp/3392>\
**Category:** Libraries\
**Created:** [September 9, 2018, 1:09pm UTC](https://discourse.processing.org/t/createshape-and-lerp/3392 "2018-09-09T13:09:33Z")\
**Posts on this page:** 4\
**Page:** 2

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 26, 2018, 10:38pm UTC](https://discourse.processing.org/t/createshape-and-lerp/3392/21 "2018-09-26T22:38:59Z")

</div>

> [@BrokenCode](#):
>
> ![](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/40/20_1.png) jeremydouglass:
> 
> > Now instead of drawing every pastBoxx every frame, you only draw a single new pastBoxx on top of the existing PGraphics image once every time currentBoxx arrives at a destination.
> 
> Would you please write a direct comparation of the two codes? Because right now I can’t see this behaviour… Please keep it simple as the Boxx example I posted

This is an optimization trick with a PGraphics that relies on a fixed-perspective optical illusion – it has several limitations, the most important being that it only works as long as your 3D camera does not change perspective at all (so, you cannot use this with a PeasyCam in motion).

Here is the sketch output, which looks normal:

 ![27%20PM](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/e/ecb3dc6678c28fab40957d4e208b9e1ab4ec3fa4.jpeg)

…but if we change the perspective, we see that we are periodically drawing a new box into a static backdrop image, rather than re-rendering a full 3D space each frame.

 ![34%20PM](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/f/f9d73d6a7b42b3ca4469f72e55628100e6b31346.jpeg)

Code revised from your example (press any key to switch perspective):

> **Summary**
>
> ```auto
> ArrayList<Boxx> pastBoxxes; // non-moving boxxes -- was ArrayList<PShape> shapes
> Boxx currentBoxx; // the moving boxx -- was ArrayList<PVector> olPosition
> Boxx futureBoxx; // the invisible mouse click target boxx -- ArrayList<PVector> newPosition
> 
> PGraphics pastBoxxesImage;
> 
> float lerpSpeed;
> int lerpNear;
> 
> boolean setback;
> 
> void setup() {
> size(500, 400, P3D);
> 
> pastBoxxesImage = createGraphics(500, 400, P3D);
> pastBoxxesImage.beginDraw();
> pastBoxxesImage.background(255, 0);
> pastBoxxesImage.endDraw();
> 
> noFill();
> hint(ENABLE_DEPTH_SORT);
> 
> pastBoxxes = new ArrayList<Boxx>();
> currentBoxx = new Boxx(width/2, height/2);
> lerpSpeed = 0.05;
> lerpNear = (int)(1/lerpSpeed) + 1;
> }
> 
> void draw() {
> background(255);
> 
> //for (Boxx box : pastBoxxes) {
> // stroke(0);
> // box.display();
> //}
> pushMatrix();
> if(setback){
> translate(0, 0, -40);
> rotateY(PI/8);
> }
> image(pastBoxxesImage, 0, 0);
> rect(0,0,width,height);
> popMatrix();
>   
> if (futureBoxx!=null) {
> currentBoxx.move((int) lerp(currentBoxx.getPosX(), futureBoxx.getPosX(), lerpSpeed), (int) lerp(currentBoxx.getPosY(), futureBoxx.getPosY(), lerpSpeed));
> println(1/lerpSpeed, ':', abs(currentBoxx.getPosX() - futureBoxx.getPosX()));
> if (abs(currentBoxx.getPosX() - futureBoxx.getPosX()) < lerpNear) {
> pastBoxxes.add(currentBoxx.copy());
> currentBoxx.display(pastBoxxesImage);
> futureBoxx = null;
> println(pastBoxxes.size());
> }
> stroke(255,0,0);
> currentBoxx.display();
> }
> }
> 
> void mouseReleased() {
> futureBoxx = new Boxx(mouseX, mouseY);
> for(Boxx boxx : pastBoxxes){
> println(boxx);
> }
> }
> 
> void keyReleased() {
> setback = !setback;
> }
> 
> class Boxx {
> 
> int boxWidth, posX, posY;
> 
> Boxx(int posX, int posY) {
> boxWidth = 50;
> this.posX = posX;
> this.posY = posY;
> }
>   
> void move(int posX, int posY){
> this.posX = posX;
> this.posY = posY;
> }
>   
> Boxx copy() {
> return new Boxx(posX, posY);
> }
> 
> void display() {
> pushMatrix();
> translate(posX, posY);
> box(boxWidth);
> popMatrix();
> }
>   
> void display(PGraphics pg) {
> pg.beginDraw();
> pg.pushMatrix();
> pg.translate(posX, posY);
> pg.noFill();
> pg.box(boxWidth);
> pg.popMatrix();
> pg.endDraw();
> }
> 
> int getPosX() {
> return posX;
> }
> 
> int getPosY() {
> return posY;
> }
>   
> }
> 
> ```

For older discussions of these techniques, see: [[SOLVED] Draw static rect filling the screen infront of PeasyCam - Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/22047/solved-draw-static-rect-filling-the-screen-infront-of-peasycam)

---

<div class="post-metadata">

**Author:** ![BrokenCode](https://avatars.discourse-cdn.com/v4/letter/b/9de0a6/32.png) [@BrokenCode](https://discourse.processing.org/u/BrokenCode)\
**Post date:** [September 28, 2018, 5:17am UTC](https://discourse.processing.org/t/createshape-and-lerp/3392/22 "2018-09-28T05:17:48Z")

</div>

Thank you 🙂  
And all this code is performing better then a simple iteration just because you just use the same object? Wow!

In my future sketch I think I’ll have to rotate the camera so maybe the PImage version will not work.

Also I noticed that if you try to click when the Boxx is moving, you change the point for that Boxx, this means that you can’t have multiple Boxxes moving, only if you create an entirely new one you can have multiple Boxxes moving?

Thank you

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 28, 2018, 5:16pm UTC](https://discourse.processing.org/t/createshape-and-lerp/3392/23 "2018-09-28T17:16:39Z")

</div>

> [@BrokenCode](#):
>
> you can’t have multiple Boxxes moving, only if you create an entirely new one you can have multiple Boxxes moving

Yes. if you want to have many Boxxes moving at the same time, each towards its own target, then you probably want to make futureBoxx part of the Boxx class – that way each Boxx has its own target.

> [@BrokenCode](#):
>
> all this code is performing better then a simple iteration just because you just use the same object?

I’m not sure I understood – which previous code in this thread is the “simple iteration”, and which is the “all this”? If you want to know which of two things performs faster, in general, test them both. However, in your original example you were writing lots of redundant data into your shapes step, which was causing problems – as a rule not writing, storing, or updating or drawing things that are extra is always faster.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [September 28, 2018, 5:50pm UTC](https://discourse.processing.org/t/createshape-and-lerp/3392/24 "2018-09-28T17:50:46Z")

</div>

> [@BrokenCode](#):
>
> In my future sketch I think I’ll have to rotate the camera

Another way of optimizing heavy renders with a rotating camera is to only redraw when the camera moves.

For a very simple system, you can set `noLoop()` and then call `redraw()` to activate the draw() only when certain criteria are met – for example, `mouseDragged()` firing, which give the PeasyCam drag handler its update.

For something slightly more complicated, you can use a flag to track whether you need to redraw the screen or not. Here is an example sketch that draws 20,000 randomly rotated cubes in a 3D environment with PeasyCam. While the mouse is NOT dragging it runs at about 60 fps. When the mouse IS dragging it runs at about 5 fps.

> **Summary**
>
> ```auto
> /**
> * Refresh3D -- only redraw the scene when needed
> * 2018-09-28 Jeremy Douglass - Processing 3.4
> */
> 
> import peasy.*;
> PeasyCam camera;
> 
> int WORKLOAD = 20000;
> int lastMillis = 0;
> boolean refresh = true;
> 
> void setup() {
> size(400, 400, P3D);
> camera = new PeasyCam(this, 0, 0, 0, 450);
> refresh = true;
> }
> 
> void draw() {
> if (refresh) {
> render();
> refresh = false;
> }
> log();
> }
> 
> void render() {
> background(0);
> randomSeed(0);
> for (int i=0; i<WORKLOAD; i++) {
> rotateX(random(PI));
> rotateY(random(PI));
> rotateZ(random(PI));
> box(width/2 + random(width/8));
> }
> }
> 
> void mouseDragged() {
> refresh = true;
> }
> 
> void log() {
> print((int)(1000/(float)(millis()-lastMillis)), "");
> lastMillis = millis();
> }
> 
> ```

 ![Refresh3D](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/737106ff17b8f950aaf9b542ce3bc57bf7f9b58c.png)

[Previous page](https://discourse.processing.org/t/createshape-and-lerp/3392.md?page=1)
