p5.js not drawing a 3d box - processing

I am creating a simulator using P5.js. Within the simulator, I need a green box, however it does not seem to be appearing. The code is below:
var outputs = [];
function setup() {
createCanvas(600, 400, WEBGL);
background(200);
for (var i = 0; i < 1; i++) {
drop = new Water(width / 2, height / 2, 0, 1);
outputs[i] = drop;
}
}
function draw() {
push();
translate(200, 150, 0);
stroke(0, 100, 0);
fill(0, 255, 0);
box(150, 150, 150);
pop();
for (var i = 0; i < outputs.length; i++) {
outputs[i].update();
}
background(200);
}
Here is the water class:
function Water(x_, y_, z_, yVel_) {
this.r = random(0.25, 1);
this.xOff = random(-(this.r / 10), (this.r / 10));
this.zOff = random(-(this.r / 10), (this.r / 10));
this.x = x_ + this.xOff;
this.y = y_;
this.z = z_ + this.zOff;
this.yVel = yVel_;
this.pos = createVector(this.x, this.y, this.z);
this.show = function() {
push();
translate(this.pos.x, this.pos.y, this.pos.z);
noStroke();
fill(0, 0, 255);
sphere(this.r * 2);
pop();
}
this.update = function() {
this.vel = createVector(random(-(this.r / 10), (this.r / 10)),
this.yVel, random(-(this.r / 10),
(this.r / 10)));
this.pos.add(this.vel);
this.show();
}
}
This is a web based simulation, with another module which appears to be working fine.
Any help would be greatly appreciated. Thanks in advance!

Removing the parts that require the Water class, and moving the background function call to the top of draw, it seems to work just fine.
So, the problem is
Either that you forgot to put background on top
Or something's wrong with the Water class.
Here's your code with the mentioned problems fixed.
var outputs = [];
function setup() {
createCanvas(600, 400, WEBGL);
}
function draw() {
background(200);
push();
translate(200, 150, 0);
stroke(0, 100, 0);
fill(0, 255, 0);
box(150, 150, 150);
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.1/p5.min.js"></script>

Its not rendering because you're background is over your scene
function draw() {
background(200);
push();
translate(200, 150, 0);
stroke(0, 100, 0);
fill(0, 255, 0);
box(150, 150, 150);
pop();
for (var i = 0; i < outputs.length; i++) {
outputs[i].update();
}
}
What your doing is drawing the box and the drops and you cover it all up with your background
if you don't have a background you will see how p5.js renders animation
p5.js not moving it, its just looping through draw every frame and the background covers up the previous frame

Related

setInterval function running indefinitely on two activations?

I'm using setInterval in a simple sketch that generates a shape + text in random colors, rotation, and locations five times (using a counter). It activates on button press and works when the button is pressed once. However, when the button is pressed before the first five are down being drawn, the function repeats indefinitely. Would love tips on how to fix.
var canvas;
var interval;
var counter = 0;
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '-1')
background('white');
inp = createInput();
inp.position(80, 150);
inp.input(inputEvent);
button = createButton('Go');
button.position(85 + inp.width, 150);
button.mousePressed(indefSomewhere);
}
function inputEvent() {
console.log(this.value())
}
function goSomewhere() {
const place = inp.value();
// for (let i = 0; i < 20; i++) {
push();
fill(random(255), random(255), random(255));
translate(random(width), random(height));
rotate(random(2*PI));
noStroke();
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
scale(0.5);
endShape(CLOSE);
push();
fill(random(255), random(255), random(255));
text(place, 100, 124);
pop();
pop();
counter++;
console.log(counter);
if(counter >= 5) {
counter = 0;
clearInterval(interval);
console.log(counter);
} else if(counter === 0 ) {
clearInterval(interval);
}
// }
}
function indefSomewhere() {
interval = setInterval(goSomewhere, 100);
}
function draw() {
fill(0);
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
endShape(CLOSE);
fill(255);
if(inp.value() != null) {
textSize(32);
text(inp.value(), 87.5, 125);
}
}
EDIT: Okay, I've added a clear interval to the indefSomewhere() function and it prevents the indefinite drawing of shapes. However double clicking doesn't activate the drawing twice. Is setInterval simply the wrong choice for this situation?
If the problem comes when setInterval() is called while the interval is already set, I would make so that if the interval hasn't been set, it calls setInterval(), but if it has, it adds +5 to the limit of the counter.
This could be the code:
var canvas;
var interval;
var intervalSet;
var counter = 0;
var maxCounter;
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}
function setup () {
canvas = createCanvas(windowWidth, windowHeight);
canvas.position(0, 0);
canvas.style('z-index', '-1')
background('white');
inp = createInput();
inp.position(80, 150);
inp.input(inputEvent);
button = createButton('Go');
button.position(85 + inp.width, 150);
button.mousePressed(indefSomewhere);
}
function inputEvent() {
console.log(this.value())
}
function goSomewhere() {
const place = inp.value();
// for (let i = 0; i < 20; i++) {
push();
fill(random(255), random(255), random(255));
translate(random(width), random(height));
rotate(random(2*PI));
noStroke();
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
scale(0.5);
endShape(CLOSE);
push();
fill(random(255), random(255), random(255));
text(place, 100, 124);
pop();
pop();
counter++;
console.log(counter);
if(counter >= maxCounter) {
counter = 0;
intervalSet = false;
clearInterval(interval);
console.log(counter);
} else if(counter === 0 ) {
intervalSet = false;
clearInterval(interval);
}
// }
}
function indefSomewhere() {
if(!intervalSet){
maxCounter = 5;
intervalSet = true;
interval = setInterval(goSomewhere, 100);
}else{
maxCounter += 5;
}
}
function draw() {
fill(0);
beginShape();
vertex(80, 50);
vertex(300, 50);
vertex(350, 95);
vertex(300, 140);
vertex(80, 140);
endShape(CLOSE);
fill(255);
if(inp.value() != null) {
textSize(32);
text(inp.value(), 87.5, 125);
}
}
This is a related question.

How to use custom shapes in a repeating loop pattern?

I already made a custom shape (myFunction), and I also made patterns using simpler shapes. I want to know how to replace those simple shapes with my custom shape while maintaining the pattern drawn on processing...
You're already calling functions such as noFill(), noStroke(), etc.
It's the same for your function: call it by simply using it's name and () (because it has no arguments): myFunction();
Let's say you want to draw it in pattern 1, you could do something like:
if (pattern==1) {
for (int x=50; x<width; x+=100) {
for (int y=20; y<height; y+=100) {
myFunction();
}
}
}
You will need to pay attention to rendering though.
Running the above will not display anything you call in noFill() in myFunction() and also noStroke() in draw(), right after background(): you won't be able to see a shape with no fill and no stroke :)
One suggestion is to add a stroke:
void myFunction() {
noFill();
stroke(255);
ellipse(300, 300, 200, 400);
ellipse(300, 300, 400, 200);
translate(300, 300);
rotate(radians(130));
ellipse(0, 0, 200, 400);
translate(0, 0);
rotate(radians(0));
ellipse(0, 0, 400, 200);
}
Of course feel free to experiment and make this look nicer.
Here's a modified version of your sketch that uses a few key presses to change the pattern type and shape type at runtime:
int pattern = 1;
// 0 = pluseEllipseCluser, 1 = blobs, 2= myFunction spirograph circles
int shape = 0;
void setup() {
size(600, 600);
println("press 1,2 to change pattern");
println("press p/b/c to change shapes");
}
void draw() {
background(30);
noStroke();
if (pattern==1) {
for (int x=50; x<width; x+=100) {
for (int y=20; y<height; y+=100) {
drawSelectedShapes(x, y);
}
}
}
if (pattern==2) {
float rando = random(10, 90);
for (float x= rando; x >= 0; x-=random(2.5)) {
for (float y= rando; y >= 0; y-=random(2.5)) {
drawSelectedShapes(x, y);
}
}
}
}
void drawSelectedShapes(float x, float y){
if(shape == 0){
plusEllipseCluser(x, y);
}
if(shape == 1){
blobs();
}
if(shape == 2){
myFunction();
}
}
void plusEllipseCluser(float x, float y){
fill(random(255), random(255), random(255), random(255));
ellipse(x, y+30, 50, 20); //plus ellipse cluster
ellipse(x, y+30, 20, 50);
}
void blobs(){
noStroke();
fill(random(250), random(120), random(100));
ellipse(random(width), random(height), 20, 50);
noFill();
stroke(random(255));
ellipse(random(width), random(height), 50, 20);
}
void myFunction() {
noFill();
stroke(255);
ellipse(300, 300, 200, 400);
ellipse(300, 300, 400, 200);
translate(300, 300);
rotate(radians(130));
ellipse(0, 0, 200, 400);
translate(0, 0);
rotate(radians(0));
ellipse(0, 0, 400, 200);
}
void keyPressed(){
if(key == '1') {
pattern = 1;
}
if(key == '2') {
pattern = 2;
}
if(key == 'p'){
shape = 0;
}
if(key == 'b'){
shape = 1;
}
if(key == 'c'){
shape = 2;
}
}
Notice that the example above also calls plusEllipseCluser() passing two arguments: it's a basic example of defining and calling a function that takes two arguments. Of course you've already called functions with arguments before (e.g. random(min,max), ellipse(x,y,w,h), etc.)
Have fun with shapes and patterns.

p5.js Add a dissapearing ellipse trail to Lissajous curve line

I have a simple code that traces the Liss cruve with a small ellipse. I was wondering how to add a fading trail to this shape so it represents the cruve more clearly. I only know a bit about adding trails that follows the mouse but I'm not sure how to do this one.
Any help is appreciated, here is the code:
var t = 0;
function setup() {
createCanvas(500, 500);
fill(255);
}
function draw() {
background(0);
for (i = 0; i < 1; i++) {
y = 160*sin(3*t+PI/2);
x = 160*sin(1*t);
fill(255);
ellipse(width/2+x, height/2+y, 5, 5);
t += .01;
}
}
Try changing background(0) to background(0, 0, 0, 4) :)
Here is a working example:
https://editor.p5js.org/chen-ni/sketches/I-FbLFDXi
Edit:
Here is another solution that doesn't use the background trick:
https://editor.p5js.org/chen-ni/sketches/HiT4Ycd5U
Basically, it keeps track of each point's position and redraws them in every frame with updated alpha to create the "fading out" effect.
var t = 0;
var particleArray = [];
function setup() {
createCanvas(500, 500);
}
function draw() {
background(0);
y = width / 2 + 160 * sin(3 * t + PI / 2);
x = height / 2 + 160 * sin(1 * t);
particleArray.push(new Particle(x, y, t));
for (i=0; i<particleArray.length; i++) {
particleArray[i].show(t);
}
//keep the array short, otherwise it runs very slow
if (particleArray.length > 800) {
particleArray.shift();
}
t += .01;
}
function Particle(x, y, t) {
this.x = x;
this.y = y;
this.t = t;
this.show = function(currentT) {
var _ratio = t / currentT;
_alpha = map(_ratio, 0, 1, 0, 255); //points will fade out as time elaps
fill(255, 255, 255, _alpha);
ellipse(x, y, 5, 5);
}
}

p5.js this._renderer.image is not a function issue

var adobe1bar1;
function preload() {
adobe1bar1 = loadImage("1-1.png");
}
function setup() {
createCanvas(500, 500, WEBGL);
center = createVector(width / 2, height / 2, height / 2);
cameraZ = -500;
}
function draw() {
background(40); // backgraound white
var cameraX = map(mouseX, 0, width, -500, 500); // map
var cameraY = map(mouseY, 0, height, -500, 500);
console.log(cameraY, cameraX);
if (cameraZ < -500) {
cameraZ = -500;
}
if (cameraZ > 0) {
cameraZ = 0;
}
camera(center.x + cameraX, center.y + cameraY, center.z + cameraZ, center.x, center.y, center.z, 0, 1, 0);
translate(center.x, center.y, center.z);
translate(0, 0, 0);
image(adobe1bar1, -250, -250, 500, 500);
}
Here is my p5.js code.
When I use the image() function
The following error message keeps appearing.
Uncaught TypeError: this._renderer.image is not a function
Is there a solution?
When not using 'WEBGL',
it uploads images without error,
but the camera() function does not work.
image is not a WEBGL function.
Try to apply an image texture to a plane instead.
texture(adobe1bar1);
translate(-250, -250, 0);
plane(500);
https://github.com/processing/p5.js/wiki/Getting-started-with-WebGL-in-p5
EDIT:
To use transparent texture you need to enable blend mode which can be done by using:
fill(0,0,0,0);
In setup

Clearing out canvas

I'm trying to program an intro. I want the canvas to erase itself after it. I already have the trigger, but I do not know how to clear the canvas. Would just changing the background work? I still want to make stuff after it.
Here is the code:
void setup () {
frameRate(10);
stroke(255, 255, 255);
noFill();
rect(100,155,300,300);
size(500, 500);
}
void square () {
for (int x = 100; x <= 300; x += 100) {
for (int y = 155; y <= 355; y += 100) {
fill(random(0, 255), random(0, 255), random(0, 255));
rect(x, y,100,100);
}
}
};
void draw () {
int time = 0;
int logoLength = 100;
if (time < logoLength) {
fill(255, 255, 255);
background(0, 0, 0);
textFont(createFont("Lucida console", 19));
textAlign(CENTER,CENTER);
text("Ghost Cube Games presents",250,59);
time++;
print(time);
square();
} else if (time == logoLength) {
background(255, 255, 255);
}
}
You can simply call the background() function.
background(0); draws a black background.
background(255); draws a white background.
background(255, 0, 0); draws a red background.
More info can be found in the reference.
For a more specific example, if you want to show an intro screen, you can simply keep track of whether the intro screen is showing in a boolean variable. If that variable is true, then draw the intro screen. If not, then draw whatever else you want to draw. If you do this from the draw() function, then you don't really have to worry about clearing the screen, since calling the background() function will do that for you:
boolean showingIntro = true;
void draw() {
background(0);
if (showingIntro) {
text("INTRO", 20, 20);
} else {
ellipse(50, 50, 25, 25);
}
}
void mouseClicked() {
showingIntro = false;
}

Resources