使用pushMatrix()函数创建可点击的3D形状以显示消息。

huangapple go评论57阅读模式
英文:

Clickable 3d shape using pushmatrix() function to show a message?

问题

你好,我想知道如何在点击3D柱体时显示一条消息。例如,我在2D图像上有一个3D柱体,当我将鼠标悬停在其上并点击一次时,它应该在同一屏幕上显示消息;如果我再次点击它,消息应该消失。

我的代码:

boolean drawText = false;

void setup() {
  size(800, 600, P3D);
}

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

  pushMatrix();
  fill(204, 0, 0, 151);
  translate(42, 75, 0);
  box(5, 5, 10);
  if (dist(mouseX, mouseY, 27, -22) < 0) {
    cursor(HAND);
  } else {
    cursor(ARROW);
  }
  if (drawText) {
    fill(#FFFF00);
    text("Hi!", 27, -22);
  }
  popMatrix();

  pushMatrix();
  fill(204, 0, 0, 151);
  translate(42, 75, 0);
  box(5, 5, 10);
  popMatrix();
}

void mousePressed() {
  if (mouseButton == LEFT && dist(mouseX, mouseY, 27, -22) < 0) {
    drawText = drawText ? false : true;
  }
}

我想知道如果我有多个3D形状,如何使用mousePressed()创建一个按钮,允许我在点击形状时使用左键单击。另外,由于我使用了pushMatrix()函数,它是否仍然能够正常工作?

英文:

Hello i would like to know how i can make my 3D bars to display a message everytime its clicked on it.

For example i've got a 3D bar on a 2D image and when i hover over it and click it once it should display the message on the same screen and if i click on it again it should make the message dissapear.

My code:

boolean drawText = false;

void setup() {
size(800, 600, P3D);
}

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

pushMatrix();
fill(204, 0, 0, 151);
translate(42, 75, 0);
box (5, 5, 10);
if(dist(mouseX,mouseY,27,-22)&lt;0){
cursor(HAND);
} else {
cursor(ARROW);
}
if (drawText) {
fill(#FFFF00);
text(&quot;Hi!&quot;, 27, -22);
}
popMatrix(); 

pushMatrix();
fill(204, 0, 0, 151);
translate(42, 75, 0);
box (5, 5, 10);
popMatrix(); 

}
void mousePressed() {
if (mouseButton == LEFT &amp;&amp; dist(mouseX,mouseY,27,-22)&lt;0) {
drawText = drawText ? false : true;
}
}

I would like to know if i have more than one 3D shape how would i create a button using mousePressed() to allow me to use LEFT button click when the shape is clicked. Also since im using pushMatrix() function is it still possible for it to work?

答案1

得分: 0

首先,我建议缩进你的代码(在Windows/Linux上按下Ctrl + T,在OSX上按下CMD+T即可)。这将使你的代码更易于阅读/快速扫描。

从长远来看,你会意识到你花在阅读/调试代码上的时间要比实际打字的时间多,所以我强烈建议做任何能让你的生活更轻松的事情 使用pushMatrix()函数创建可点击的3D形状以显示消息。

根据我在你的代码中了解到的情况,看起来你对坐标和坐标系感到困惑。请查阅 坐标系统2D变换 教程。

我之所以这样说是因为你在坐标42, 75处同时绘制了两个盒子。此外,你正在检查鼠标坐标与27,-22之间的距离(你还在这里绘制了文本)。顺便说一句,距离永远不会小于0

要调试你的程序,将其分解为各个部分,一次测试一个事物,是一个很好的方法。个人而言,我会编写最小的草图来测试假设,然后再将它们应用到更大的程序中。

例如,用一个简化的草图来证明dist() < 0是很容易的。新建一个草图,粘贴以下内容并运行:

void draw(){
  background(255);
  line(50,50,mouseX,mouseY);
  fill(0);
  text("x:" + mouseX + ",y:" + mouseY + "\nd:" + dist(mouseX,mouseY,50,50), mouseX, mouseY);
}

另一件需要注意的事情是,在检查围绕盒子的2D屏幕边界时,你将使用全局坐标,而不是相对坐标(使用translate()偏移)。下面是一个经过调整的使用dist()的版本:

boolean drawText = false;

float radius = 22.5;
float diameter = radius * 2;

void setup() {
  size(800, 600, P3D);
}

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

  pushMatrix();
  // visualise radius
  fill(255, 30);
  
  ellipse(44, 80, diameter, diameter);
  ellipse(108, 80, diameter, diameter);
  
  fill(204, 0, 0, 151);
  translate(42, 75, 0);
  box(50, 50, 10);
  
  if (isOver(mouseX, mouseY, 44, 80, radius) ||
      isOver(mouseX, mouseY, 108, 80, radius)) {
    cursor(HAND);
  } else {
    cursor(ARROW);
  }
  if (drawText) {
    fill(#FFFF00);
    text("Hi!", 27, -22);
  }
  popMatrix(); 

  pushMatrix();
  fill(35, 198, 13, 151);
  translate(110, 75, 0);
  box(50, 50, 10);
  popMatrix();
}

void mousePressed() {
  if (mouseButton == LEFT) {
    
    if (isOver(mouseX, mouseY, 44, 80, radius) ||
        isOver(mouseX, mouseY, 108, 80, radius)) {
         
      drawText = !drawText;
      
     }
  }
}

boolean isOver(int mx, int my, float x, float y, float radius){
  return dist(mx, my, x, y) < radius;
}

值得注意的是,附近绘制的圆圈作为按钮的活动区域,以及光标在盒子角落处不会改变。可以调整半径,以便更多地覆盖盒子,但由于椭圆的形状,活动区域要么会错过角落,要么会超出边缘。另一个考虑因素是,如果你有很多个盒子按钮,例如,dist() 可能会变慢(因为它在幕后使用了 sqrt())。

在特定情况下,我建议使用 Button 示例中的 overRect() 函数:矩形将更好地适应该方向的 3D 盒子形状,并且计算速度更快:

boolean drawText = false;

void setup() {
  size(800, 600, P3D);
}

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

  pushMatrix();
  fill(204, 0, 0, 151);
  translate(42, 75, 0);
  box(50, 50, 10);
  
  if (isOver(mouseX, mouseY, 13, 47, 57, 57) ||
      isOver(mouseX, mouseY, 82, 47, 57, 57)) {
    cursor(HAND);
  } else {
    cursor(ARROW);
  }
  if (drawText) {
    fill(#FFFF00);
    text("Hi!", 24, -38);
  }
  popMatrix(); 

  pushMatrix();
  fill(35, 198, 13, 151);
  translate(110, 75, 0);
  box(50, 50, 10);
  popMatrix();
}

void mousePressed() {
  if (mouseButton == LEFT) {
    if (isOver(mouseX, mouseY, 13, 47, 57, 57) ||
        isOver(mouseX, mouseY, 82, 47, 57, 57)) {
         
      drawText = !drawText;
      
     }
  }
}

boolean isOver(int mx, int my, int x, int y, int w, int h){
  return ((mx >= x && mx <= x + w) &&
          (my >= y && my <= y + h));
}

作为一种改进,你可以在草图顶部为每个按钮的全局2D边界框(x、y、宽度和高度)创建变量,以便轻松重用,而不是使用复制/粘贴的常量值。优势在于

英文:

First off I recommend indenting your code (Ctrl + T on Windows/Linux, CMD+T on OSX does the work for you). This makes your code much easier to read / scan quickly.

On the long run you will realise you spend more time reading/debugging code than actually typing, so I warmly recommend doing whatever makes your life easier 使用pushMatrix()函数创建可点击的3D形状以显示消息。

From what I gather in your code it looks like you're confused about coordinates and coordinate systems. Please review the Coordinate Systems and 2D Transformation tutorials

I say that because you're drawing both boxes on top of each other at coordinates 42, 75.
Additionally you're checking the distance between mouse coordinates and 27,-22 (where you also draw text. The distance will never be &lt; 0 by the way.

To debug your program it's a good idea to break it down to it's sections and test one thing at a time. Personally I write minimal sketch to test assumptions before implementing them into a bigger program.

For example disproving dist() &lt; 0 is easy with a minimal test sketch.
Make a new sketch, paste the following and run:

void draw(){
background(255);
line(50,50,mouseX,mouseY);
fill(0);
text(&quot;x:&quot;+mouseX+&quot;,y:&quot;+mouseY + &quot;\nd:&quot; + dist(mouseX,mouseY,50,50),mouseX,mouseY);
}

The other thing to bare in mind is you would use global coordinates when checking 2D screen bounds around the boxes, not the relative coordinates (offset using translate()).

Here's a tweaked version of your sketch using dist():

boolean drawText = false;
float radius = 22.5;
float diameter = radius * 2;
void setup() {
size(800, 600, P3D);
}
void draw() {
background(0);
noStroke();
pushMatrix();
// visualise radius
fill(255,30);
ellipse(44, 80, diameter, diameter);
ellipse(108, 80, diameter, diameter);
fill(204, 0, 0, 151);
translate(42, 75, 0);
box (50, 50, 10);
if(isOver(mouseX, mouseY, 44, 80, radius) ||
isOver(mouseX, mouseY, 108, 80, radius)) {
cursor(HAND);
} else {
cursor(ARROW);
}
if (drawText) {
fill(#FFFF00);
text(&quot;Hi!&quot;, 27, -22);
}
popMatrix(); 
pushMatrix();
fill(35, 198, 13, 151);
translate(110, 75, 0);
box (50, 50, 10);
popMatrix();
}
void mousePressed() {
if (mouseButton == LEFT) {
if(isOver(mouseX, mouseY, 44, 80, radius) ||
isOver(mouseX, mouseY, 108, 80, radius)) {
drawText = !drawText;
}
}
}
boolean isOver(int mx, int my, float x, float y, float radius){
return dist(mx,my,x,y) &lt; radius;
}

Bare in mind I am using a couple of shortcuts:

  • drawText = drawText ? false : true; is the same as drawText = !drawText; using logical NOT)
  • the isOver() function is similar to the button example overCircle() function, however it simply returns a boolean (using &lt; as a conditional operator)

Also notice the circles drawn near the boxes which act as the button's active areas and how the cursor doesn't change around the box corners. The radius can be tweaked so it covers more of the boxes, however due to the shape of the ellipse the active area will either miss the corners or go over the sides. Another considation if you were to have many many box buttons for example dist() may turn slow (as it uses sqrt() behind the scenes).

In the particular I recommend something like the overRect() function from the Button example: a rectangle will fit the 3D box shape in that orientation better and be faster to compute:

boolean drawText = false;
void setup() {
size(800, 600, P3D);
}
void draw() {
background(0);
noStroke();
pushMatrix();
fill(204, 0, 0, 151);
translate(42, 75, 0);
box (50, 50, 10);
if(isOver(mouseX, mouseY, 13, 47, 57, 57) ||
isOver(mouseX, mouseY, 82, 47, 57, 57)) {
cursor(HAND);
} else {
cursor(ARROW);
}
if (drawText) {
fill(#FFFF00);
text(&quot;Hi!&quot;, 24, -38);
}
popMatrix(); 
pushMatrix();
fill(35, 198, 13, 151);
translate(110, 75, 0);
box (50, 50, 10);
popMatrix();
}
void mousePressed() {
if (mouseButton == LEFT) {
if(isOver(mouseX, mouseY, 13, 47, 57, 57) ||
isOver(mouseX, mouseY, 82, 47, 57, 57)) {
drawText = !drawText;
}
}
}
boolean isOver(int mx, int my, int x, int y, int w, int h){
return ((mx &gt;= x &amp;&amp; mx &lt;= x + w) &amp;&amp;
(my &gt;= y &amp;&amp; my &lt;= y + h));
}

As an improvement you could create variables at the top of your sketch for each button's global 2D bounding box x,y, width and height to re-use easily instead of using copy/pasted constant values. The advantage is it would make the code more flexible: easier to change button position, size, etc.

If you are confused over functions and return values I recommend Daniel Shiffman's function tutorials:

  1. 7.2: Functions Basics - Processing Tutorial
  2. 7.3: Modularity with Functions - Processing Tutorial
  3. 7.4: Reusability with Functions - Processing Tutorial

huangapple
  • 本文由 发表于 2020年4月10日 23:13:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/61143261.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定