Picking an object in a scene is basically a matter of clicking on the screen and getting back the serial number of that object. If the object you are looking for is a solid, then pick should apply to solids, if it is a face, then to faces, and so on. You first learn how to pick solids in a scene. The pick method should apply to the MyGroup class, since you have to search a group to find the picked solid.
You start with the x and y coordinates of the screen, acquired when the mouse is clicked. The “pick” algorithm should return an integer, which is the serial number of the picked object. Therefore, the pick method should be in the mouse- Clicked() method and should look (approximately) like this:
for(int i=0; i<group.nsolids; i++)
if(group.solids[i].pick(mouseX,mouseY)) println(“You picked solid number =” + i);
}
This code directs that MyGroup should have a method called pick. MyGroup .pick() will transfer its jurisdiction to the solids[i].pick() one level below:
boolean pick(int xmouse, int ymouse){
for(int i=0; i< nsolids; i++) if(solids[i].pick(xmouse,ymouse)) return true;
return false;
}
The statement:
if(solids[i].pick(xmouse, ymouse)) return true;
indicates that if an object was found, there is no need to continue. This could be changed to allow multiple objects to be picked (i.e., those along the line of sight where the mouse is clicked).
At this point, MyGroup transfers its jurisdiction one level below, asking the MyObject class to find whether an object was selected within its domain. Here, the method is similar to pick() in MyGroup. In turn, MySolid transfers its juris- diction one level below, asking MyFace to find whether a face was selected.
boolean pick(int xmouse, int ymouse){
for(int i=0; i< nfaces; i++) if(faces[i].pick(xmouse,ymouse)) return true;
return false;
}
If a face was indeed picked, then you need to set all the faces of that solid to
“selected”:
void setSelected(boolean what){
isSelected = what;
}
where isSelected is a boolean variable of the MyFace class. At the MyFace level, the pick method is as follows:
boolean pick(int xmouse, int ymouse){
if(!isVisible())return false;//no need to select what is not visible Polygon poly = new Polygon(); //make a polygon
for(int i=0; i<npoints; i++){
float px = screenX(points[i].x,points[i].y,points[i].z);
//get the points on the screen float py = screenY(points[i].x,points[i].y,points[i].z);
poly.addPoint(int(px),int(py));
}
if(poly.contains(xmouse, ymouse)){
//use the contains() operation of the Polygon setSelected(true);
return true; //if one is found no need to continue }
return false;
}
The face is projected on the screen through the screenX() and screenY() operation, and now the problem is simply to find whether a 2D point (xmouse, ymouse) is within a 2D polygon area. This can be done manually or you can use the contains() method of the Java object Polygon. If poly.contains() is true, a face was indeed selected; otherwise, it’s not. Next, you draw the face (or whatever is selected) using the draw() method within the MyFace class:
void draw(){
fill(c); //c is the object’s color stroke(0); //black is default if(isSelected)stroke(255,0,0);
//make the stoke red to indicate selection beginShape(POLYGON);
for(int i = 0; i < npoints; i++){
vertex(points[i].x,points[i].y, points[i].z);
}
endShape(CLOSE);
}
To mark selected entities, you added a boolean member called isSelected for each class (group, solid, face). This is initialized to false and is set to true only if the entity is selected. For example, for the MyGroup class:
class MyGroup { MySolid[] solids;
int numSolids;
boolean isSelected = false;
….
So, the variable isSelected indicates whether a face, solid, or group is selected.
In the main code you can use it to select a face, solid, or group by indicating at which hierarchical level to use the pick() method. For example, below, a solid is picked and (commented out) is the way to pick only a face:
void mouseClicked(){
group.setSelected(false);
for(int i=0; i<group.nsolids; i++)
if(group.solids[i].pick(mouseX,mouseY)){
group.solids[i].setSelected(true);
//for(int ii=0; ii<group.solids[i].nfaces; ii++) //if(group.solids[i].faces[ii].pick(mouseX,mouseY)) return;
}
The output is shown in Figure 9-25.
Figure 9-25: Picking (selecting) a solid in a scene
In this example, you have managed to pick a solid on the screen. This is a significant task. The scene suddenly can become interactive. The user is able to select solids and do things to them such as move, rotate, scale, erase, and so forth. This is the first step to interactivity.