GLWidget in Qt only updating on mousemove - user-interface

I am currently playing with Qt trying to set up a small particle system. Therein I've subclassed the GLWidget and hacked away at it. Everything was going well until I made some unknown change and now the widget only repaints when I move the mouse (it should be doing it all the time due to the QTimer I have firing). Relevant code:
OpenGLWidget.h
class OpenGLWidget : public QGLWidget {
Q_OBJECT
public:
OpenGLWidget(QWidget * parent = 0);
~OpenGLWidget();
public slots:
void toggleEmitter();
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
QSize minimumSizeHint() const;
QSize sizeHint() const;
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
protected slots:
void timeOut();
private:
void testFunc(Particle & p, unsigned int t);
QTime time;
QTimer timer;
Emitter emitter;
Relevant code from the .cpp
// in the constructor
time.start();
connect(&timer, SIGNAL(timeout()), this, SLOT(timeOut()));
timer.start(0);
void OpenGLWidget::initializeGL() {
GLuint tex = 0;
qglClearColor(bgColor);
glEnable(GL_DEPTH_TEST);
glClearDepth(1.0f);
glDepthFunc(GL_LEQUAL);
glShadeModel(GL_SMOOTH);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE); // _MINUS_SRC_ALPHA );
glPointSize(3.0f);
tex = bindTexture(QPixmap(QString("testparticle2.png")), GL_TEXTURE_2D);
emitter = Emitter(Vector(0, 0, 0.0f), tex, 50, fastdelegate::FastDelegate2<Particle &, unsigned int>(this, &OpenGLWidget::testFunc));
}
void OpenGLWidget::paintGL() {
makeCurrent();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mainCam.SetView();
glRotatef(xRot, 1, 0, 0);
glRotatef(yRot, 0, 1, 0);
emitter.Process(time.elapsed());
totalTime += time.elapsed();
time.restart();
}
void OpenGLWidget::resizeGL(int width, int height) {
contextWidth = width;
contextHeight = height;
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(55.0f, width / (float) height, 0.01f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void OpenGLWidget::timeOut() {
updateGL();
}
void OpenGLWidget::mousePressEvent(QMouseEvent *event) {
lastX = event->pos().x();
lastY = event->pos().y();
}
void OpenGLWidget::mouseMoveEvent(QMouseEvent *event) {
int dx = event->x() - lastX;
int dy = event->y() - lastY;
if (event->buttons() & Qt::LeftButton) {
xRot += 3 * dy;
yRot += 3 * dx;
} else if (event->buttons() & Qt::RightButton) {
xRot += 3 * dy;
yRot += 3 * dx;
}
lastX = event->pos().x();
lastY = event->pos().y();
}

A QTimer with 0 second time out only fires when the event loop gets the control. I suspect this is not the case. However, when you move the mouse, the event loop processes some events (again) and then delivers the pending timer event(s). Maybe you need to invoke processEvents() in your update loop to make sure that the pending timer event from QTimer gets processed.

considering that updateGL() calls glDraw() which calls paintGL(), you'd think the timer should be calling the same functionality as your mousemove event.
Are you sure the timer is actually ticking?
BTW, there is no need to call makeCurrent() in paintGL().
edit: after the extra information was added:
QTimer says:
"As a special case, a QTimer with
timeout 0 times out as soon as all the
events in the window system's event
queue have been processed."
so, if you want it to go as fast as possible (though 10ms is probably the minimum on Windows and most x386-based systems), then start your timer with a value of 1 instead of 0. I assume that this is the problem, that its only ticking when it has finished reading off messages from the queue.

Timer simply can't work with less than 20ms. It's equals 0 for it. You may use simple loop with measuring time from one iteration to another. Measuring method probably should use API of your operation system.

Related

rotating Processing 3D object overlapped my ui object

void draw(){
//3Dmap
scale = 1+scaleFactor;
background(100);
pushMatrix();
translate(width/2+transX, height/2.5+transY, 0);
rotateX(rotX);
rotateY(-rotY);
scale(scale);
imageMode(CENTER);
image(nyc_map, 0, 0, mapSize, mapSize);
image(compass,0,0,100,100);
popMatrix();
//UI
box.display();
resetMap.update();
resetMap.render();
playButton.update();
playButton.render();
}
//rotation part
void mouseDragged() {
rotY -= (mouseX-pmouseX) * 0.01;
rotX -= (mouseY-pmouseY) * 0.01;
}
void mouseWheel(MouseEvent event) {
float e = event.getCount();
scaleFactor += e * 0.001;
}
when I rotating my main map it's keep overlapped my interactive part. How can I set it to always in the back layer?
this is when program started
when I'm rotate it in z dimension it's overlap my ui obj.

Loading in folder outside of my sketch's data folder (processing)

Im sure there is a pretty straight forward answer to this...cant quite figure it out though.
In my processing sketch's data folder, there is a folder named test_segments. test_segments contains a bunch of images.
I need to load an image from test_segments into my PImage.
It looks like this: http://imgur.com/a/iG3B6
My code:
final int len=25;
final float thresh=170;
boolean newDesign=false;
PImage pic;
ArrayList<PImage> imgContainer;
int n=3;
void setup() {
size(800, 800, P2D);
colorMode(RGB, 255);
background(250, 250, 250);
rectMode(CENTER);
//imageMode(CENTER);
pic=loadImage("hand.jpg");
pic.resize(width, height);
color c1 = color(200,25,25);
color c2 = color(25, 255, 200);
imgContainer=new ArrayList<PImage>();
PImage pimg1=loadImage("this is where test_0.png needs to go")
pimg1.resize(50, 50);
imgContainer.add(pimg1);
noLoop();
noStroke();
}
void draw() {
if (newDesign==false) {
return;
}
pic.loadPixels();
for (int y = 0; y < height; y+=40) {
for (int x = 0; x < width; x+=40) {
int index=y*width+x;
color pixelValue = pic.pixels[index];
color rgb = pixelValue;
int r = (rgb >> 16) & 0xFF; // Faster way of getting red(argb)
int g = (rgb >> 8) & 0xFF; // Faster way of getting green(argb)
int b = rgb & 0xFF;
//How far is the current color from white
float dista=dist(r,g,b,255,255,255);
//50 is a threshold value allowing close to white being identified as white
//This value needs to be adjusted based on your actual background color
//Next block is processed only if the pixel not white
if(dista>30){
float pixelBrightness = brightness(pixelValue);
float imgPicked=constrain(pixelBrightness/thresh, 0, n-1);
image(imgContainer.get((int)imgPicked),x,y);
}
}
}
}
void mouseReleased() {
newDesign=!newDesign;
redraw();
}
Thanks!
You should just be able to do:
PImage pimg1 = loadImage("test_segments/test_0.png");
If that doesn't work, please try to post a MCVE like we talked about before. Here's an example of an MCVE that would demonstrate your problem:
PImage pimg1 = loadImage("test_segments/test_0.png");
image(pimg1, 0, 0);
Don't forget to include exactly what you expect to happen, and exactly what's happening instead. Good luck.

How to remove previous shape after draw() in Processing

I cant figure this out. I have a sketch with little rotating rectangles on it. They rotate on every draw(). However the previous rectangle remains visible. I tried moving background() around but it either gets rid of all the rectangles apart from one or it doesn't clear the screen. I would like to be able to clear all the rectangles after each draw.
Here is the code:
//Create array of objects
ArrayList<Circle> circles = new ArrayList<Circle>();
ArrayList<Connector> centrePoint = new ArrayList<Connector>();
void setup(){
size(800, 800);
frameRate(1);
rectMode(CENTER);
background(204);
for(int i = 1; i < 50; i++){
float r = random(100,height-100);
float s = random(100,width-100);
float t = 20;
float u = 20;
println("Print ellipse r and s " + r,s);
circles.add(new Circle(r,s,t,u,color(14,255,255),random(360),random(5),random(10)));
}
//Draw out all the circles from the array
for(Circle circle : circles){
circle.draw();
float connectStartX = circle.x1;
float connectStartY = circle.y1;
println("PrintconnectStartX and Y " + connectStartX,connectStartY);
for(Circle circleEnd : circles){
float connectEndX = (circleEnd.x1);
float connectEndY = (circleEnd.y1);
centrePoint.add(new Connector(connectStartX,connectStartY,connectEndX,connectEndY));
}
}
//For each ellipse, add the centre point of the ellipse to array
for(Connector connectUp : centrePoint){
println(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
stroke(100, 0, 0);
if (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75){
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
//For the line weight it should equal the fat of the node it has come from ie
//for each circle, for each connectUp if the x==connectStartX and y==connectStartY then make the line strokeWeight==fat
for(Circle circle : circles){
for(Connector connectUp : centrePoint){
if (connectUp.connectStartX == circle.x1 & connectUp.connectStartY == circle.y1 & (dist(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY) < 75)){
print(" true "+ circle.fat);
float authority = circle.fat;
strokeWeight(authority*1.5);
connectUp.draw(connectUp.connectStartX ,connectUp.connectStartY ,connectUp.connectEndX ,connectUp.connectEndY);
}
}
}
}
void update(){
}
void draw() {
for(Circle circle : circles){
circle.rot =+0.02;
circle.draw();
circle.rot = random(-6,6);
}
}
//Need to connect each ellipse to all the other ellipses
class Connector {
public float connectStartX;
public float connectStartY;
public float connectEndX;
public float connectEndY;
public color cB;
public float thickness;
public Connector(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
this.connectStartX = connectStartX;
this.connectStartY = connectStartY;
this.connectEndX = connectEndX;
this.connectEndY = connectEndY;
//this.cB = tempcB;
//this.thickness = thickness;
}
void draw(float connectStartX, float connectStartY, float connectEndX, float connectEndY){
line(connectStartX, connectStartY, connectEndX, connectEndY);
// float fat = random(255);
//fill(fat);
stroke(100, 0, 0);
}
}
class Circle{
public float x1;
public float y1;
public float x2;
public float y2;
public color cB;
public float rot;
public float fat = random(5);
public float fert = 0.1;
public Circle(float x1, float y1, float x2, float y2, color tempcB, float rot, float fat, float fert){
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.cB = tempcB;
//Tilt - I think this is done in radians
this.rot = rot;
//Authority -this is the fill
this.fat = fat;
//Fertility- this is a multiplier for the tilt
this.fert = fert;
}
void draw(){
pushMatrix();
translate(x1, y1);
fert = random(0.5);
rot = random(-6,6);
rotate(rot*fert);
translate(-x1, -y1);
//float fat = random(255);
fill(fat);
rect(x1, y1, 24, 36);
popMatrix();
}
}
You've got a few things going on in your code that I've seen in your previous posts. The way you're doing your drawing doesn't make a ton of sense, and I'll explain why.
Here's what most Processing sketches do:
Use the setup() function to setup any data structures you'll use in your program. Don't do any drawing from the setup() function.
Call background() every frame to clear out old frames.
Draw everything you want to be drawn in the frame in the draw() function.
Modify the data structures to change what you're drawing on the screen.
Your code is a bit too long for an MCVE, so here's a little example that handles the drawing in a more standard way:
ArrayList<PVector> circles = new ArrayList<PVector>();
void setup() {
size(500, 500);
ellipseMode(RADIUS);
//setup your data structures here
circles.add(new PVector(250, 250));
//don't do any drawing yet
}
void mousePressed() {
//modify the data structure whenever you want to change what's on the screen
circles.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
//modify the data structure whenever you want to change what's on the screen
if (!circles.isEmpty()) {
circles.remove(0);
}
}
void draw() {
//call background every frame to clear out old frames
background(0);
//draw everything
for (PVector p : circles) {
ellipse(p.x, p.y, 20, 20);
}
}
Notice how this is different from what you're doing. Here's what you do:
You use the setup() function to setup your data structures, but then you draw the background and some of the objects to the screen.
You then don't call background() from draw(), so you're always stuck with whatever has already been drawn.
You then only draw a subset of what you want on the screen, so you can't redraw your whole scene.
You have to modify your code to no longer draw anything from setup(), to call the background() function every frame, and to draw everything you want on the screen every frame.
What you are doing is printing every single circle or line...ect. You need to have a timer that removes them every so often. If you do it too fast you get a strobe like look. So have a timer that removes the first rect from the array list every so often.

How to make the size of ellipse to get smaller and bigger in processing automatically

I am creating something using classes in order to get used to them and I am trying to get the size of the ellipse I have drawn to get smaller and larger on its own so that it makes it look more interactive however I don't know what code to implement.
I have shown the code I am using below;
void setup()
{
size(640, 480);
}
void draw()
{
background(255);
for (int i = height-50; i > 0; i-= 20)
{
fill(random(255), random(255), random(255));
ellipse(width/2, height/2, i, i);
}
}
Just to add to Kevin's great answer, here are couple of variations on the same idea (keeping track if the size is increasing or not).
The first approach involves using using a growth speed variable that simply flips sign when a limit is reached. If the size is too small (lower limit) or too big (upper limit), flipping the sign ( multiplying the growth speed by -1 ) will change growing to shrinking and vice-versa:
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 1.5;
void setup()
{
size(640, 480);
}
void draw()
{
//if the size is either too small, or too big, flip the size speed sign (if it was positive (growing) - make it negative (shrink) - and vice versa)
if(size < minSize || size > maxSize) {
sizeSpeed *= -1;
}
//increment the size with the size speed (be it positive or negative)
size += sizeSpeed;
background(255);
fill(random(255), random(255), random(255));
ellipse(width/2, height/2, size,size);
}
Note that the motion is fairly linear. Since you want to grow and shrink a circle over time, you could get a smoother animation using the sin() function. It takes an angle as an argument and based on the angle value it returns a value between -1.0 and 1.0. You can use the map() function to remap this range to the desired ellipse size:
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;
void setup()
{
size(640, 480);
}
void draw()
{
size = map(sin(frameCount * sizeSpeed),-1.0,1.0,minSize,maxSize);
background(255);
fill(random(255), random(255), random(255));
ellipse(width/2, height/2, size,size);
}
Update In terms of classes, you can start encapsulating the variables used for drawing the ellipse into a class. The syntax isn't that complex:
Use the class keyword, then the name of the class (Uppercase by convention) and add the class members within {} - the classes scope
Create an instance of the class using the new keyword and use . notation to access the instance members
Here's a really basic example using the above:
Ellipse e = new Ellipse();
void setup()
{
size(640, 480);
}
void draw()
{
e.size = map(sin(frameCount * e.sizeSpeed),-1.0,1.0,e.minSize,e.maxSize);
background(255);
fill(random(255), random(255), random(255));
ellipse(width/2, height/2, e.size,e.size);
}
class Ellipse{
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;
}
That's a nice and easy start, but the drawing part isn't encapsulated.
The same way you declare and use variables in a class, you can declare and use functions. Here's a basic example of simply moving the ellipse drawing functionality into a function:
Ellipse e = new Ellipse();
void setup()
{
size(640, 480);
}
void draw()
{
background(255);
e.render();
}
class Ellipse{
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;
void render(){
size = map(sin(frameCount * sizeSpeed),-1.0,1.0,minSize,maxSize);
fill(random(255), random(255), random(255));
ellipse(width/2, height/2, size,size);
}
}
As you notice, it now takes 2 lines to initialize and render an ellipse from the main sketch. There are still things that can be improved. If a second ellipse is created, the x and y is the same so they'd obscure each other. Adding x,y properties to the class will mean each instance will have independent coordinates.
On a similar note, frameCount is global, which means, each ellipse uses the same
angle/size. We can make that independent too.
Ellipse e1 = new Ellipse(320,240);
Ellipse e2 = new Ellipse(20,20);
void setup()
{
size(640, 480);
}
void draw()
{
background(255);
e1.render();
e2.render();
}
class Ellipse{
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;
//position
float x,y;
//internal frameCount replacement
int tick;
//constructor
Ellipse(float x,float y){
this.x = x;//copy x argument value to the instance (this) x property
this.y = y;//copy x argument value to the instance (this) x property
}
void render(){
tick++;
size = map(sin(tick * sizeSpeed),-1.0,1.0,minSize,maxSize);
fill(random(255), random(255), random(255));
ellipse(x,y, size,size);
}
}
Notice we also added a constructor. A constructor is a very special: it's like an entry point to a new instance. Whenever you create a new instance of a class, the constructor is called, which usually initialises data. The previous example didn't explicitly define a constructor, but Processing provides one with no arguments by default. To take the above concepts a step further, we create a constructor with x,y coordinates:
Ellipse e1 = new Ellipse(320,240);
Ellipse e2 = new Ellipse(20,20);
void setup()
{
size(640, 480);
}
void draw()
{
background(255);
e1.render();
e2.render();
}
class Ellipse{
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;
//position
float x,y;
//internal frameCount replacement
int tick;
//constructor
Ellipse(float x,float y){
this.x = x;//copy x argument value to the instance (this) x property
this.y = y;//copy x argument value to the instance (this) x property
}
void render(){
tick++;
size = map(sin(tick * sizeSpeed),-1.0,1.0,minSize,maxSize);
fill(random(255), random(255), random(255));
ellipse(x,y, size,size);
}
}
This is a very quick overview. For more details, be sure to check out Daniel Shiffman's Objects tutorial.
With that in mind, you can use an ArrayList to create new ellipses at runtime and have some fun randomising ellipse parameters:
ArrayList<Ellipse> ellipses = new ArrayList<Ellipse>();
void setup()
{
size(640, 480);
ellipses.add(new Ellipse(width / 2, height / 2));
}
void draw()
{
background(255);
for(Ellipse e : ellipses){
e.render();
}
}
//add an ellipse every 5th frame if mouse is dragged
void mouseDragged(){
if(frameCount % 5 == 0) ellipses.add(new Ellipse(mouseX,mouseY));
}
//remove all ellipses if SPACE is pressed
void keyPressed(){
if(key == ' ') ellipses.clear();
}
//ellipse class
class Ellipse{
//current size - continuously updated
float size = 10;
//minimum size
float minSize = 10;
//maximum size
float maxSize = 240;
//change speed for size (how much will the size increase/decrease each frame)
float sizeSpeed = 0.025;
//position
float x,y;
//internal frameCount replacement
int tick;
int fill;
//constructor
Ellipse(float x,float y){
this.x = x;//copy x argument value to the instance (this) x property
this.y = y;//copy x argument value to the instance (this) x property
fill = color(random(32,192));
sizeSpeed = random(0.025,0.01);
maxSize = random(120,240);
}
void render(){
tick++;
size = map(sin(tick * sizeSpeed),-1.0,1.0,minSize,maxSize);
fill(fill);
ellipse(x,y, size,size);
}
}
You just need to store the width and height of your circle in a variable, use that variable in the draw() function, and then change it whenever you want to change the circle size.
Here is an example program that changes the circle size when you click the mouse:
float radius = 50;
void setup(){
size(500, 500);
ellipseMode(RADIUS);
}
void mouseClicked(){
radius = 250.0*mouseX/width;
}
void draw(){
background(0);
ellipse(width/2, height/2, radius, radius);
}
Here is an example program that grows and shrinks the circle automatically:
float radius = 0;
boolean grow = true;
void setup() {
size(500, 500);
ellipseMode(RADIUS);
}
void draw() {
if (grow) {
radius++;
if (radius == 250) {
grow = false;
}
} else {
radius--;
if (radius == 0) {
grow = true;
}
}
background(0);
ellipse(width/2, height/2, radius, radius);
}
But the idea is the same in both examples: just store your circle radius in a variable, change that variable to change the size, and use that variable to draw your circle.

Understanding void draw() in processing

I am tinkering with Processing and cannot figure out how to write text over an image I created using the image buffer (rotating squares)...when the square becomes smaller than the text, the changing digits wrote on top of each other. Cannot use resetting the bkg as a solution because that erases the overlapping images. Still having a hard time understanding this area...
Question: How to get the text to appear on top of the rotating squares without resetting the bkg and without the text writing over itself
Code below
Thank you!
float rotateAmount;
int boxColorR = 255;
int boxColorG = 255;
int boxColorB = 255;
int boxW = 480;
void setup () {
size(640,480);
rectMode(CENTER);
}
void drawText() {
//translate(width/2,height/2);
textAlign(LEFT, CENTER);
fill(255, 255, 255);
textSize(32);
text("RED: " + boxColorR,width/2,height/2);
text("GREEN: " + boxColorG,width/2,height/2+30);
text("BLUE: " + boxColorB,width/2,height/2+60);
text("Box Width: " + boxW,width/2,height/2+90);
}
void drawBox() {
translate(width/2,height/2);
rotateAmount += 12;
if (boxColorR <= 0) {
boxColorG--;
}
if (boxColorG <= 0) {
boxColorB--;
}
boxColorR--;
boxW--;
rotateAmount += .05;
rotate(rotateAmount);
fill(boxColorR,boxColorG,boxColorB);
rect(0,0,boxW,boxW);
resetMatrix();
}
void draw() {
//rect(width/2,height/2,640,480); //this solves the text overlapping but erases the cool effect
drawBox();
drawText();
}
Most Processing sketches use a call to the background() function as the first line in the draw() function. This clears out anything drawn in previous frames.
However, you want to keep the stuff drawn in previous frames, so you don't want to clear them out. The problem with this is that since your text isn't cleared out either, your text ends up looking garbled.
The solution to this is to use the PGraphics class to create an off-screen buffer. You draw the squares to the buffer instead of to the screen. Then you draw the buffer to the screen, and finally, you draw the text on top of the buffer.
Since you draw the buffer to the screen each frame, it clears away the old text, but the squares you've previously drawn are maintained in the buffer.
Code speaks louder than words:
float rotateAmount;
int boxColorR = 255;
int boxColorG = 255;
int boxColorB = 255;
int boxW = 480;
//create a buffer to draw boxes to
PGraphics buffer;
void setup () {
size(640, 480);
buffer = createGraphics(640, 480);
}
void drawText() {
//translate(width/2,height/2);
textAlign(LEFT, CENTER);
fill(255, 255, 255);
textSize(32);
text("RED: " + boxColorR, width/2, height/2);
text("GREEN: " + boxColorG, width/2, height/2+30);
text("BLUE: " + boxColorB, width/2, height/2+60);
text("Box Width: " + boxW, width/2, height/2+90);
}
//draw boxes to buffer
void drawBox() {
buffer.beginDraw();
buffer.rectMode(CENTER);
buffer.translate(width/2, height/2);
rotateAmount += 12;
if (boxColorR <= 0) {
boxColorG--;
}
if (boxColorG <= 0) {
boxColorB--;
}
boxColorR--;
boxW--;
rotateAmount += .05;
buffer.rotate(rotateAmount);
buffer.fill(boxColorR, boxColorG, boxColorB);
buffer.rect(0, 0, boxW, boxW);
buffer.resetMatrix();
buffer.endDraw();
}
void draw() {
//draw the boxes to the buffer
drawBox();
//draw the buffer to the screen
image(buffer, 0, 0);
//draw the text on top of the buffer
drawText();
}

Resources