Rendering rectangles through other rectangles - processing

For some reason when I draw over another rectangle in my current processing sketch, it draws over all other rectangle fills, but does not appear to draw over other rectangle strokes. when I make another sketch this problem doesn't persist, but it happens consistently in this sketch.
Overlapping rectangles picture
[]
Example
Here's a simplified example which seems to recreate the issue
void setup(){
size(1000, 600 , P3D);
surface.setResizable(true);
//frameRate(120);
}
void draw(){
if(width < 100)
size(100,height,P3D);
if(height < 100)
size(width,100,P3D);
fill(10);
stroke(10);
strokeWeight(10);
rect(100,100,100,100);
fill(255);
stroke(100);
strokeWeight(10);
rect(0,0,300,300);
}

It's because you set size with the "P3D" argument. P3D is a 3D rendering mode. This result is likely due to some eccentricity of rendering the 2D rect() function in a 3D space.

Related

How to draw a fading object trail? Without background manipulation

I have a simple ellipse, moving across the screen, is there any simple code I could implement to have this ellipse draw a trail behind it that has its alpha fade over time to a certain extent? I still want the trail visible in the end but less bright than the casting ellipse.
You could also do something like this:
let positions = [];
function draw(){
positions.push(mouseX);
positions.push(mouseY);
for(let i in positions){
let x = positions[i];
let y = positions[i + 1];
fill(255, 255 - i * 10); noStroke();
ellipse(mouseX, mouseY, x, y)
}
if(positions.length > 20){
positions.shift();
positions.shift();
}
}
Assuming the ellipse is the only thing being drawn then there is a simple solution which is to, instead of drawing a fully opaque background on each frame, draw a semi-transparent background:
function setup() {
createCanvas(windowWidth, windowHeight);
}
function draw() {
background(0, 35);
ellipse(mouseX, mouseY, 20, 20);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
However, there are some caveats, namely that for certain colors/transparency levels you will be left with permanent "ghost" of the trails due to some weird alpha blending math anomalies.

How can I display text always in front on a 3D plot?

I have a complex 3D plot with some text on rollover. It's already a bit cluttered so I'd like to have the text always be in front of all the plot parts. Like here:
Right now, when I hover over some points in the background, the text is sometimes hidden behind plot components, like here:
How can I force the text to always be in the front and facing the camera (which it already is right now).?
Use pushMatrix()/popMatrix() to isolate coordinate spaces: one for the 3D graphics, another for the 2D elements on top:
void setup(){
size(300, 300, P3D);
sphereDetail(9);
noFill();
stroke(255);
textSize(21);
textAlign(CENTER);
}
void draw(){
background(0);
// 3D
pushMatrix();
translate(width * 0.5, height * 0.5, 0);
rotateX(map(mouseY, 0, height, -PI, PI));
rotateY(map(mouseX, 0, width, PI, -PI));
sphere(150);
popMatrix();
// 2D
pushMatrix();
text((int)frameRate, mouseX, mouseY);
popMatrix();
}
(The indenting is not required, just visually emphasising coordinate space nesting.
The last push/pop may not be needed for such as simple example, but is useful if you have more 2D/3D things happening on top of what's already been drawn)
For more info checkout the 2D Transformations Tutorial.
Additionally you might find the PeasyCam library useful.
To draw 2D text on top you'd do something like:
camera.beginHUD();
// draw 2D overlays here
camera.endHUD(); // back to 3D

PGraphics + noSmooth() + alpha = drawing artifacts

Note: I also asked this question on the Processing forum here.
I have this sample code:
PGraphics pg;
void setup() {
size(400, 500);
pg = createGraphics(width, height);
pg.noSmooth();
pg.beginDraw();
pg.background(0, 0, 255);
pg.endDraw();
}
void draw() {
if (mousePressed) {
pg.beginDraw();
pg.stroke(255, 254);
pg.point(mouseX, mouseY);
pg.endDraw();
}
image(pg, 0, 0, width, height);
}
I would expect this code to show a point wherever the user presses the mouse. Instead, I am only able to see points in a couple rectangular areas:
If I remove the call to pg.noSmooth() or if I remove the alpha value in the pg.stroke() call, then it works fine:
If I replace the pg.point() call with pg.ellipse() or pg.rect() then it also works fine.
It seems like the combination of using a PGraphics, the noSmooth() function, the point() function, and an alpha value results in this buggy behavior. I’ve tried in Processing 3.3 and Processing 3.5.2 and I see the same behavior in both.
Am I missing something obvious?
After a wee bit of digging up turns out the JAVA2D renderer draws a point as a diagonal line(line(x, y, x + EPSILON, y + EPSILON);) with a very very very small spacing (static final float EPSILON = 0.0001f;). My guess is this particular configuration the lack aliasing might mean both points of this diagonal line land on the same pixel and end up not being rendered on the top right area which. Why that area and how come this small distance I don't know, but it sounds a bit like the headaches Jakub Valtar and Andres Colubri had to deal with.
FWIW here's a hacky workaround: using a larger distance that does get rendered with transparency and no aliasing:
PGraphics pg;
void setup() {
size(400, 500);
noSmooth();
pg = createGraphics(width/20, height/20);
pg.beginDraw();
// just for debug purposes: rectangle with edge
pg.fill(0, 0, 255);
pg.rect(0,0,pg.width-1,pg.height-1);
pg.stroke(255,255,255, 128);
pg.endDraw();
}
void pointNoSmooth(PGraphics pg, float x,float y){
pg.beginShape();
pg.vertex(x,y);
pg.vertex(x + 0.75,y);//any less than 0.75 distance between vertices and there's nothing to render with aliasing
pg.endShape();
}
void draw() {
background(255);
if (mousePressed) {
pg.beginDraw();
pointNoSmooth(pg,mouseX,mouseY);
pg.endDraw();
}
// render upscaled
image(pg, 0, 0, width, height);
// render small preview in TL corner
image(pg,0,0);
}
Notice that I've set the PGraphics resolution 20 times smaller, then drawn it upscaled so it's easier to see where the pixels land on the PGraphics. I'm not scaling the mouseX,mouseY coordinates though, so you'll need to draw in the small top left preview when testing. That 0.75 distance does the trick: from what I've tested, anything smaller than 0.7499995 starts acting buggy again.

Drawing a line on an image

I have stuck up in a problem. This question is with respect to processing. I have to draw a scratch on an image using this function
line(pmouseX, pmouseY, mouseX, mouseY);
How do I achieve this? I mean, wherever I draw a scratch, pixel corresponding to that image has to be updated.
Thanks for any assistance
I'm not sure what kind of effect do you want to achieve so here is basic usage of drawing line according to mouse position.
PImage img; //global variable for storing image
void setup(){
img = loadImage("image.jpg"); //loading image
size(img.width, img.height); //setting size of sketch
}
void draw(){
image(img, 0, 0); //each time redraw background with Image
line(pmouseX, pmouseY, mouseX, mouseY); //draw line acc to mouse
}
If you want to draw big line just move image() function into setup().
If you want more complicated lines you will have to use mouse events.

Processing.js : how to draw() only parts of the canvas to reduce cpu usage

Right now I have an html page that renders 20 canvases each with its own instance of a processing.js script. To decrease CPU usage, I have mouseover/out events to loop()/noLoop() only the graph the mouse is hovering over.
But I need to take this even further. The canvas right now is 300x400 where there is a 300x300 space that needs to dynamically draw all the time but there's a rectangle with a legend that is the rest of the space which really doesn't need to be redrawn using the framerate() of the rest.
Does any know of a way to essentially specify to the draw() function which pixels to redraw?
I'm pretty sure a 100x300 blank area is not going to add significantly to the computations. But you can of course pass to draw something like:
if(frameCount==1) [draw legend code];
or using if(frameCount % 30 == 0)... for a continuous but less frequent rendering.
Edit:
void setup(){
size(400,400);
noStroke();
background(255);
}
void draw(){
fill(255,255,255,50);
rect(0, 150, width, height-150);
if(frameCount%50 == 1) {
fill(255);
rect(0, 0, width, 150);
fill(0);
text("frame " + frameCount, width/2, 75);
}
fill(255,0,0);
ellipse(random(0, width), random(150, height), 10, 10);
}

Resources