Click event on 3D primitive

Hey all,

any idea how to fire an event when a 3D primitive is clicked. In my case, I’m trying to click on a rotating box and link to another html page. Please help meeh.

let cnv;
let brand;
let clientH;
let clientW;
let col;

let theta = 0;

function preload() {
    brand = loadImage('/sources/images/actOut.png');
}

function setup() {
    clientH = document.getElementById('brand-ctn').clientHeight;
    clientW = document.getElementById('brand-ctn').clientWidth;
    cnv = createCanvas(clientW, clientH, WEBGL);
    cnv.parent('brand-ctn');
    col = getComputedStyle(document.documentElement)
        .getPropertyValue('--emphasized-text');

}

function draw() {
    ortho();
    background(0, 0);
    push();
    rotateZ(theta * 0.1);
    rotateX(theta * 0.1);
    rotateY(theta * 0.1);
    texture(brand);
    strokeWeight(2);
    stroke(col);
    if (clientW >= clientH) {
        box(clientH / 2);
    } else {
        box(clientW / 2);
    }
    pop();

    theta += 0.005;
}

function windowResized() {
    canvas = resizeCanvas(clientW, clientH);
}
1 Like

Hello and welcome,

If you can please provide the code for your sketch, it will be a lot easier for forum members to help with your question!
:slightly_smiling_face:

2 Likes

There are 2 easy ways :

  • look at screenX and screenY (see reference), store those. Compare to mouse position with dist(). If dist<70 it’s a hit. if(dist(mouseX,mouseY,myScreenX,myScreenY)<70) hit = true;

  • Use color myColor = get(mouseX, mouseY); to measure the color underneath the mouse when you click. Compare to background color. When it’s not equal it’s a hit.
    Take a look at Jeremy‘s post here: Problem with hover on area curves

  • reference: https://www.processing.org/reference/

Use lights(); in 3D - looks much better

And welcome to the forum! Nice to have you here!

Chrisir

Example for the first approach:


ArrayList<SphereClass> list = new ArrayList();  

void setup() {
  size(1300, 900, P3D);

  // init all spheres 
  SphereClass newSphere=new SphereClass(360, 230, -130);
  list.add(newSphere);

  newSphere=new SphereClass(530, 230, -230);
  list.add(newSphere);

  newSphere=new SphereClass(230, 230, 130);
  list.add(newSphere);
}

void draw() {
  background(0);
  lights(); 

  // loop over all spheres 
  for (SphereClass sphere : list) { 
    // show it
    sphere.display();
  }//for
} 

void mousePressed() {
  // loop over all spheres 
  for (SphereClass sphere : list) {
    // select / unselect depending on mouse pos 
    sphere.selectWhenMouseOver();
  }//for
}

// ===========================================================

class SphereClass {

  PVector pos; // 3D vector
  PVector screenPos=new PVector(0, 0); // 2D vector  

  boolean selected=false; 

  // constr
  SphereClass(float x, float y, float z) {
    pos = new PVector(x, y, z); // 3D vector
  }// constr

  void display() {
    // draw sphere at pos (x, y, z) coordinate and store 2D screen pos

    pushMatrix();
    translate(pos.x, pos.y, pos.z);
    noStroke(); 

    // we choose the color depending on selected 
    if (selected)
      fill(255, 0, 0); // red 
    else
      fill(0, 0, 255); // blue 

    // draw the sphere 
    sphere(50);

    // we monitor the 2D screen pos throughout and store it
    screenPos.set(screenX(0, 0, 0), screenY(0, 0, 0));
    popMatrix();

    // show the 2D screen pos
    if (keyPressed)
      drawSignX(screenPos);
  }

  void drawSignX( PVector pos ) { 
    // Draw a "X" sign
    // 
    float sizeHalf=60; 
    float x=pos.x;
    float y=pos.y;
    float z=pos.z;  
    stroke(255);
    line(x-sizeHalf, y-sizeHalf, z, x+sizeHalf, y+sizeHalf, z); 
    line(x+sizeHalf, y-sizeHalf, z, x-sizeHalf, y+sizeHalf, z);
  }

  void selectWhenMouseOver() {
    // select / unselect 
    if (mouseOver()) 
      selected=true;
    else 
    selected=false;
  }

  boolean mouseOver() {
    return 
      dist(mouseX, mouseY, screenPos.x, screenPos.y) < 30;
  }
  //
}//class
//
1 Like

You need to share some code. It shows your attempt, your coding level and it makes helping you easier.

Check these links, one is a previous discussion and the second one is mPicker, a p5.js lib made exactly for this:

Kf

3 Likes

The “object picking” method is something that you can implement on your own, but there are existing examples, as linked above. For more (and more discussion), also
search “3d picking” or “object picking” + “p5.js”:

https://www.google.com/search?q=3d+picking+for+p5.js