How do I fill a vertex' shape with an image in processing? - processing

When I use my code it says: No uv text coordinates supplied with vertex() call.
This is the code I use:
PImage img;
void setup() {
size(720, 360, P3D);
}
void draw() {
beginShape();
img = loadImage("image.png");
texture(img);
vertex(50, 20);
vertex(105, 20);
vertex(105, 75);
vertex(50, 75);
endShape();
}

Like your error and George's comment say, to use a texture you need to pass in 4 parameters to the vertex() function instead of 2 parameters.
From the reference:
size(100, 100, P3D);
noStroke();
PImage img = loadImage("laDefense.jpg");
beginShape();
texture(img);
vertex(10, 20, 0, 0);
vertex(80, 5, 100, 0);
vertex(95, 90, 100, 100);
vertex(40, 95, 0, 100);
endShape();
(source: processing.org)
Also note that you should not be loading your image inside the draw() function, because that causes you to load the same image 60 times per second. You should load it once from the setup() function.

Related

Move a group of shapes in Processing

I have the below code which moves a group of rectangles and circles, but for some reason it always keeps the previous shapes. I want to delete the previous shapes and only draw the new shapes (so it looks like my shapes are moving). I end up with this:
But it should look like a truck is moving. Below is my code:
public class Truck extends Vehicle {
public Truck(float size, float speed) {
super(size, speed);
}
int x = width-250;
void display() {
while (x > -100) {
scale(size);
translate(-1, 0);
fill(255, 0, 0);
rect(x, 500, 200, 100); //body
rect(x-75, 525, 75, 75); //front
fill(0);
rect(x-75, 525, 45, 45); //window
ellipse(x-60, 610, 45, 45);
ellipse(x-20, 605, 35, 35);
ellipse(x+160, 610, 45, 45);
ellipse(x+117, 605, 35, 35);
delay(1);
x--;
}
}
}
So I have quite a bit of experience with the JavaScript version of processing, and if you add:
background(255);
before you draw everything I think that will fix your issue.
This is because the shapes leave a "trail" of sorts behind them when they move. Unless you draw the background periodically, that trail will be visible.

How to fill the color inside the curve?

I want to create a picture that has some closed areas using function curve(...), but I do not know how to fill the color inside.
Is there any way to fill inside the head and body?
void setup(){
size(800,800);
}
void draw(){
background(170,243,255);
fish();
}
void fish(){
translate(width/2, height/2);//mouseX, mouseY
//eye
fill(231,255,188);
stroke(0);
ellipse(-100,-100,50,45);
fill(0);
ellipse(-100,-100,30,28);
//head
noFill();
strokeWeight(2);
stroke(157,88,255);
curve(-400,-100,-200,-200,50,-150,150,50);
curve(-100,-400,-200,-200,-150,50,0,100);
curve(-300,50,-150,50,50,-150,50,-300);
//body
curve(-200,-350,50,-150,250,250,600,300);
curve(-200,-200,-150,50,250,250,500,250);
}
You could use the curveVertex() function.
This doesn't do exactly what you want, but you can play around with it until it does:
//body
fill(255, 0, 0);
beginShape();
curveVertex(-200, -350);
curveVertex(50, -150);
curveVertex(250, 250);
curveVertex(-150, 50);
curveVertex(-200, -200);
endShape();
Note that you can have multiple blocks like this to fill in different pieces with the same color.

Can't set nofill() when using PGraphics

I Can't set noFill while rendering to a PGraphics object.
Trying to draw an arc gets me this.
While what i want is this.
I used the following code in the processing application for 64 bit windows 7
PGraphics pg;
void setup() {
size(123, 123);
pg = createGraphics(123, 123);
pg.strokeWeight(5);
pg.stroke(255);
pg.noFill();
noFill();
}
void draw() {
pg.beginDraw();
pg.background(0);
pg.translate(width/2, height/2);
pg.arc(0, 0, 100, 100, 0, PI+1);
pg.endDraw();
image(pg, 0, 0);
}
It is better to set modes and style for PG inside draw block and it works like you want:
pg.beginDraw();
pg.background(0);
pg.strokeWeight(5);
pg.stroke(255);
pg.noFill();
pg.translate(width/2, height/2);
pg.arc(0, 0, 100, 100, 0, PI+1);
pg.endDraw();

Change object by pressing button while showing animation

I'm trying to add animation in my code. What I have so far is an object that can be changed by pressing a button. So every time you press the button, the object changes (it is a tree and I'm changing its branches). Is it possible to add some kind of animation like snow? The problem with that is that I have to put it inside the draw method so it will be called automatically and make us think that it is animation. Thus, I also have to add the background / button and everything all the time. But I can't do that with my main object (tree) as I want to change it only when you press the button.
Is there any solution to that?
Thanks in advance
To persist some objects while refreshing others, you either:
Refresh only part of the screen. Like, draw a shape (rect or whatever) with background colour erasing only part of screen
Conditionally draw selected objects. Use flags to selective draw what you need, every draw, and use background() to clear the whole screen every draw cycle.
Use layers. Erase one layer and not other as you need, display all them in draw. This is usually done with PGraphics objects. Search processing + layers to see samples. Here and/or in processing forum.
EDIT:
Here some simple examples of each approach:
1.
/**
* A very simple example of erasing just part of the screen to
* selective persist draws
**/
void setup() {
size(400, 400);
background(0);
noStroke();
}
void draw() {
fill(0);
rect(0, 0, width/2, height);
fill(120);
ellipse(width/4, frameCount%width, 100, 100);
}
void mouseMoved() {
fill(255);
ellipse(mouseX, mouseY, 10, 10);
}
2.
/**
* A very simple example of conditionally draw stuf
* to selective persist draws
**/
ArrayList <PVector> points = new ArrayList <PVector>();
boolean showBalls = true; // any key to toogle
void setup() {
size(400, 400);
background(0);
noStroke();
}
void draw() {
background(0);
fill(30);
rect(frameCount%width, 100, 200, 200);
fill(120);
ellipse(width/2, frameCount%width, 150, 150);
fill(255);
if (showBalls) {
for (PVector p : points) {
ellipse(p.x, p.y, 10, 10);
}
}
if (points.size() > 500) {
points.clear();
}
}
void mouseMoved() {
ellipse(mouseX, mouseY, 10, 10);
points.add(new PVector(mouseX, mouseY));
}
void keyPressed() {
showBalls = !showBalls;
}
3.
/**
* A very simple example of using PGraphics as layers
* to selective persist draws
**/
PGraphics layer;
void setup() {
size(400, 400);
layer = createGraphics(width, height);
layer.beginDraw();
layer.fill(255);
layer.endDraw();
background(0);
noStroke();
}
void draw() {
background(0);
fill(30);
rect(frameCount%width, 100, 200, 200);
fill(120);
ellipse(width/2, frameCount%width, 150, 150);
image(layer, 0, 0);
}
void mouseMoved() {
layer.beginDraw();
layer.ellipse(mouseX, mouseY, 10, 10);
layer.endDraw();
}

Processing: Performance issues with background()

I'm creating a stereoscopic test application where the scene is rendered into a PGraphics left and a PGraphics right with different camera angles for the two eye points. The two images is then combined into a side-by-side output in the draw() function.
The scene consists of a pre-rendered background, stored in a separate PGraphics, rendered once, and a rotating box() rendered for each frame.
The problem is that the call to gfx.background(gfxBackground); in render() is very CPU intensive. If I replace it with a gfx.background(0); call, the sketch runs smoothly.
My assumption was that blit'ing data from one PGraphics to another would be done with hardware acceleration, but it seems it isn't. Am I doing something wrong?
My sketch:
PGraphics leftBackground;
PGraphics rightBackground;
PGraphics left;
PGraphics right;
int sketchWidth() { return 1920; }
int sketchHeight() { return 1200; }
int sketchQuality() { return 8; }
String sketchRenderer() { return P3D; }
void setup()
{
noCursor();
leftBackground = createGraphics(width / 2, height, P3D);
renderBackground(leftBackground, "L");
rightBackground = createGraphics(width / 2, height, P3D);
renderBackground(rightBackground, "R");
left = createGraphics(width / 2, height, P3D);
left.beginDraw();
left.endDraw();
left.camera(-10, 0, 220,
0, 0, 0,
0, 1, 0);
right = createGraphics(width / 2, height, P3D);
right.beginDraw();
right.endDraw();
right.camera( 10, 0, 220,
0, 0, 0,
0, 1, 0);
}
void draw()
{
render(left, leftBackground);
render(right, rightBackground);
image(left, 0, 0);
image(right, left.width, 0);
}
void renderBackground(PGraphics gfx, String str)
{
gfx.beginDraw();
gfx.background(0);
gfx.stroke(255);
gfx.noFill();
gfx.rect(0, 0, gfx.width, gfx.height);
gfx.scale(0.5, 1.0, 1.0);
gfx.textSize(40);
gfx.fill(255);
gfx.text(str, 30, 40);
gfx.endDraw();
}
void render(PGraphics gfx, PGraphics gfxBackground)
{
gfx.beginDraw();
gfx.background(gfxBackground);
gfx.scale(0.5, 1, 1);
gfx.rotateY((float)frameCount / 100);
gfx.rotateX((float)frameCount / 90);
gfx.stroke(255);
gfx.fill(0);
gfx.box(30);
gfx.endDraw();
}
You've got multiple options to achieve the same visual output.
Here are a few options:
Simply overlay the "L"/"R" text:
in draw():
render(left, bgl);
render(right, bgr);
image(right, 0, 0);
image(right, left.width, 0);
text("L",100,100);
text("R",width/2+100,100);
using gfx.background(0) in render().
PGraphics extends PImage so instead of
gfx.background(gfxBackground);
you can use
gfx.image(gfxBackground,xoffset,yoffset);
You will need to offset because of the camera call, also, you will need to translate the box in Z direction since by default it will be at (0,0,0) and will intersect with the quad rendering the background image.
If you want to go deeper and find other bottlenecks sample the CPU using jvisualvm (if you have the JDK installed and PATH set to it you should be able to run this from terminal/commandline, otherwise there's an application in YOUR_JDK_INSTALL_PATH\bin).
Take a couple snapshots at different intervals and compare performance. You might find some other draw commands that could be changed to gain a few ms per frame.

Resources