I'm trying to use an image as a texture for a plane in P5js using WEBGL, but for some reason it isn't working.
I've tried to get rid of all the lighting and just use ambientLight() but still it isn't showing. I've tried in a new sketch with just the plane and the same code and it works fine, so I don't understand what the problem is in this sketch?
let bodyShape;
let spacing = 50;
let bgTexture;
function preload() {
bodyShape = loadModel('Human_body_with_net.obj');
bgTexture = loadImage('assets/gormleyline.jpeg');
}
function setup() {
createCanvas(600, 600,WEBGL);
noStroke();
}
function draw() {
background(0);
debugMode();
orbitControl();
ambientLight(255);
// pointLight(102,0,0,0,1,0);
// pointLight(0,102,255,1,0,0);
// directionalLight(255,0,0,0,1,0);
// directionalLight(255,255,255,0,0,-1);
// pointLight(0,0,0,mouseX,mouseY,0);
backgroundShape();
push();
translate(-260,0,0);
for (let x = 0; x<10; x++){
bodyFunction(x+spacing,0,0);
rotateX(50);
}
pop();
}
function bodyFunction(x,y,z,rotation){
specularMaterial(255);
translate(x,y,z);
rotateX(HALF_PI);
model(bodyShape);
}
function backgroundShape(){
push();
translate(0,0,-130);
plane(600,600);
texture(bgTexture)
pop();
}
Here's the link to the sketch in case it's useful: https://editor.p5js.org/rociorey/sketches/4H1eFQpKh
Thank you!
You must specify the texture for the geometry before you draw the geometry (see texture()):
texture(bgTexture);
plane(600,600);
Related
working on the coding train's cocossd tutorial, I cannot seem to find a way to get the squares around the detected things.
Here is the js code:
let img;
let detector;
function preload() {
img = loadImage("images/penguin.jpg");
detector = ml5.objectDetector("cocossd");
}
function gotDetections(error, results) {
if (error) {
console.error(error);
}
console.log(results);
for (let i = 0; i < results.length; i++) {
let object = results[i];
console.log(object.x, object.y, object.width, object.height);
stroke("green");
strokeWeight(4);
noFill();
rect(object.x, object.y, object.width, object.height);
noStroke();
fill(255);
textSize(24);
text(object.label, object.x + 10, object.y + 24);
}
}
function setup() {
createCanvas(640, 480);
image(img, 0, 0, width, height);
detector.detect(img, gotDetections);
}
I've got the image of the penguine on the screen, where it should be on the canvas, and I have the object.x, object.y, object.width, object.height being console.logged correctly, I just cannot figure out why no combination of the drawing stuff in gotDetections function is not working.
I have tried every combination, I have these two CDN's in the html body
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.5.0/p5.min.js"></script>
<script src="https://unpkg.com/ml5#latest/dist/ml5.min.js"></script>
I'm not sure what I'm doing wrong at this point.
Changing the canvas size to match the image size worked reliably on my system. I downloaded a small penguin image from the internet and it correctly identified it as a bird and framed it with a green box.
function setup() {
createCanvas(img.width, img.height);
image(img, 0, 0);
detector.detect(img, gotDetections);
}
I am trying to hide the video (webcam in this case) but keep the detected points of the hand. I have tried different methods, but I am unsuccessful so far. I appreciate the help.
Main code (below) from ml5.js can be found and tested live here: https://editor.p5js.org/ml5/sketches/Handpose_Webcam
let handpose;
let video;
let predictions = [];
function setup() {
createCanvas(640, 480);
video = createCapture(VIDEO);
video.size(width, height);
handpose = ml5.handpose(video, modelReady);
// This sets up an event that fills the global variable "predictions"
// with an array every time new hand poses are detected
handpose.on("predict", results => {
predictions = results;
});
// Hide the video element, and just show the canvas
video.hide();
}
function modelReady() {
console.log("Model ready!");
}
function draw() {
image(video, 0, 0, width, height);
// We can call both functions to draw all keypoints and the skeletons
drawKeypoints();
}
// A function to draw ellipses over the detected keypoints
function drawKeypoints() {
for (let i = 0; i < predictions.length; i += 1) {
const prediction = predictions[i];
for (let j = 0; j < prediction.landmarks.length; j += 1) {
const keypoint = prediction.landmarks[j];
fill(0, 255, 0);
noStroke();
ellipse(keypoint[0], keypoint[1], 10, 10);
}
}
}
Yes, just stop drawing it to the canvas, and add a call to background to fill the canvas.
function draw() {
// image(video, 0, 0, width, height); // <- just delete this line
background(255);
// We can call both functions to draw all keypoints and the skeletons
drawKeypoints();
}
https://editor.p5js.org/Samathingamajig/sketches/BV_kqU0Ik
Can't work out what I'm doing wrong. Looking at the code below my logic is that each time the draw function is called the ellipse's coordinates are changed to be another random number.
However instead of the coordinates being changed, the ellipse is just being redrawn at the 'new' coordinates.
Does anyone care to shed some light on why the shape is being redrawn rather than moved? I'm using the p5 javascript library.
var frate = 10;
var elliX = 500;
var elliY = 400;
function setup() {
createCanvas(100, 100);
frameRate(frate);
}
function draw() {
elliX = (random(0,100));
elliY = (random(0,100));
ellipse(elliX, elliY, 30);
}
p5 doesn't clear the canvas by default, so it's adding a new circle every time you're drawing. To clear, you can call clear() beforehand, like so:
var frate = 10;
var elliX = 500;
var elliY = 400;
function setup() {
createCanvas(100, 100);
frameRate(frate);
}
function draw() {
clear();
elliX = (random(0,100));
elliY = (random(0,100));
ellipse(elliX, elliY, 30);
}
<script src="https://unpkg.com/p5#0.6.1/lib/p5.min.js"></script>
So I'm trying to make a shape move in the canvas with p5.js. However, all it does is redrawing the same shape in the newly assigned position without deleting the shape in the old position, leaving sort of a trail, and not completely moving it like I wanted. You can see the result here.
Below is the code for my "Player" class (the shape that I want to move):
function Player() {
this.hp = 10;
this.x = 230;
this.y = 240;
this.color = "red";
this.r = 10;
this.spawn = function(){
fill(this.color);
noStroke();
rect(this.x, this.y, this.r*2, this.r*2);
}
}
This is my code in the setup and draw functions in p5.js:
var p1;
function setup() {
createCanvas(500, 500);
background("green");
p1 = new Player();;
}
function draw() {
p1.spawn();
if (keyIsDown(LEFT_ARROW)) {
p1.x--;
}
if (keyIsDown(RIGHT_ARROW)) {
p1.x++;
}
if (keyIsDown(UP_ARROW)) {
p1.y--;
}
if (keyIsDown(DOWN_ARROW)) {
p1.y++;
}
}
Any help would be greatly appreciated. Thanks!
You need to clear out old frames using the background() function. You should generally call background() from the first line in the draw() function. Here's an example:
function setup() {
createCanvas(200, 200);
}
function draw() {
background(64);
ellipse(mouseX, mouseY, 25, 25);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.11/p5.min.js"></script>
Try moving the call to the background() function to the setup() function to see what I mean.
you just use
if (keyDown(the key you want to use)) {
}
or
if(keyDown("the key you want to use")){
}
I'm curious to know how applications such as Adobe Photoshop implement their drawing history with the ability to go back or undo strokes on rasterized graphics without having to redraw each stroke from the beginning...
I'm wanting to implement a similar history function on an HTML5 drawing application I'm working on but duplicating the canvas after every stoke seems like it'd use too much memory to be a practical approach, especially on larger canvas'...
Any suggestions on how this might be implemented in a practical and efficient manner?
I may have a solution.....
var ctx = document.getElementById("canvasId").getContext("2d");
var DrawnSaves = new Array();
var Undo = new Array();
var FigureNumber = 0;
var deletingTimer;
function drawLine(startX, startY, destX, destY) {
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(destX, destY);
ctx.stroke();
var Para = new Array();
Para["type"] = "line";
Para["fromX"] = startX;
Para["fromY"] = startY;
Para["toX"] = destX;
Para["toY"] = destY;
DrawnSaves.push(Para);
FigureNumber++;
}
function undo() {
ctx.beginPath();
ctx.clearRect(0, 0, 500, 500);
Undo[FigureNumber] = DrawnSaves[FigureNumber];
DrawnSaves[FigureNumber] = "deleted";
FigureNumber--;
drawEverything();
startTimeoutOfDeleting();
}
function undoTheUndo() {
FigureNumber++;
DrawnSaves[FigureNumber] = Undo[FigureNumber];
drawEverything();
clearTimeout(deletingTimer);
}
function drawEverything() {
for (i = 0; i < DrawnSaves.length; i++) {
if (DrawnSaves[i].type == "line") {
ctx.beginPath();
ctx.moveTo(DrawnSaves[i].fromX, DrawnSaves[i].fromY);
ctx.lineTo(DrawnSaves[i].toX, DrawnSaves[i].toY);
ctx.stroke();
}
}
}
function startTimeoutOfDeleting() {
setTimeout(function() {Undo[FigureNumber] = "deleted";}, 5000);
}
This is really simple, first I draw a line when the function is called and save all his parameters in an array. Then , in the undo function I just start a timer do delete the figure drawn i 2000 miliseconds, clears the whole canvas and makes it can't be redrawn. in the undoTheUndo function, it stops the timer to delete the figure and makes that the figure can be redrawn. In the drawEverything function, it draws everything in the array based on it's type ("line here"). That's it... :-)
Here is an example working : This, after 2sec UNDOs then after 1sec UNDOTHEUNDO