We are about to switch to a new forum software. Until then we have removed the registration on this forum.
The general program is this: I have a target square to match, and a "cursor square" to manipulate. So first I match the centers, then I'm rotating and scaling:
(The red square is the target. I need to change the white outlined square)
My design is to drag the cursor square's corner to the target square's corner, which in the process will scale and rotate to match the square.
The pushMatrix() is set so that the origin is at the center of the cursor square. (Square mode is CENTER too.)
Right now, The rotation is working but the size is weird. Here's one example:
It should match the red square, but right now it's too huge. I printed the distance from my mouse to the center of the square and it's a rather large number...
My suspicion is, I had to use P3D renderer so I could use modelX(), even though the whole thing is just 2D. Somewhere in the 3D might have messed the distance up. But I'm not sure.. I did set Z to 0 every time I have the chance..
Here's an edited version of my code. The parameters for rotation, square size and translation are GLOBAL. I'll really appreciate it if you could take a look!
void draw() {
//omitted background and other things..
//===========DRAW TARGET SQUARE=================
pushMatrix();
translate(width/2, height/2, 0); //center the drawing coordinates to the center of the screen
Target t = targets.get(trialIndex);//generated somewhere else
translate(t.x, t.y, 0); //center the drawing coordinates to the center of the screen
rotateZ(radians(t.rotation));
//omitted fill and strokes
popMatrix();
//===========DRAW CURSOR SQUARE=================
pushMatrix();
translate(width/2, height/2, 0); //center the drawing coordinates to the center of the screen
translate(screenTransX, screenTransY, 0);
rotateZ(radians(screenRotation));
//omitted stroke and fills
rect(0,0, size, size);
//record the corner coordinates using modelX
//up-left
ULX = modelX(-size/2, -size/2, 0);
ULY = modelY(-size/2, -size/2, 0);
//.....
//omitted code for other corners
//other stuff......
}
void mouseMoved()
{
//omitted other code
//rotate and scale the square once the centers line up
if (mode == "rotScale" && rotatingCorner != ""){
//THIS LINE IS THE PROBLEM
size = sqrt(2)* dist(mouseX, mouseY, 0, (ULX+URX)/2, (ULY+DLY)/2, 0);
//THE LINE ABOVE IS THE PROBLEM
//adding multiplies of 45 since I'm rotating the corners
if (rotatingCorner == "UR") screenRotation = degrees(atan2(mouseY-(ULY+DRY)/2, mouseX-(ULX+DRX)/2))-45;
if (rotatingCorner == "DR") screenRotation = degrees(atan2(mouseY-(ULY+DRY)/2, mouseX-(ULX+DRX)/2))+45;
if (rotatingCorner == "UL") screenRotation = degrees(atan2(mouseY-(ULY+DRY)/2, mouseX-(ULX+DRX)/2))-135;
if (rotatingCorner == "DL") screenRotation = degrees(atan2(mouseY-(ULY+DRY)/2, mouseX-(ULX+DRX)/2))+135;
}
}
void mousePressed()
{
//decide which corner the user just picked up
if (mode == "rotScale"){
if (dist(ULX, ULY, 0, mouseX, mouseY, 0)<5){
rotatingCorner = "UL";
//omitted code for other corners
rotating = true;
println(dist(mouseX, mouseY, 0, (ULX+URX)/2, DLY - (ULY+DLY)/2, 0));
}
}
Answers
Share code that actually runs. Include your setup and global variables; they could matter. For example, which renderer are you using?
...ah, I just saw in your comments: P3D. That was my first guess.
Thank you for your reply! As stated in the question, I'm using P3D so I could use the modelX() functions
I was trying to refrain from posting the entire thing which might make the post quite unreadable. But if you're interested, here is the entire code
It is a bit hard to follow your code. Can you comment more on
For step 1, if you want to match the center of the red square and the square cursor, you wouldn't need modelX. A center is a point and it is not affected but rotations.
Step 2: So what I understand, after you match the center, one can trigger the second state where one would match the size and rotation of the cursor square to the target square. You know the size and rotation of the red square (since it was placed when you program was started). You wouldn't need modelX either. I could be missing the point of your program, but what I can see is that going 3D you are making a 2D problem into a 3D problem aka. more complex.
When you match the center of the squares, what usually happen? Do you measure the distances? Do you score it? What happen if there is an offset between the centers? Likewise, what metrics do you use when matching size and rotation which are done simultaneously? If you explain this part of the program, then I can try to understand your code.
Kf
Thank you so much for replying! About the code, it's more of an hci experiment than a graphical design exercise. It's about designing and studying an intuitive system that allows people to quickly and accurately match shapes when there's no snapping. One of the goal is to make all the transformations continuous, which increased the difficulty quite a bit. Subsequent studies and testings will be done.
About why I used modelX: The first idea I had was to** track the corners**. You move the corners to match the position, then after it's matched, click another corner to rotate&scale.. This required knowing the position of the corners. That idea was kind of abandoned, since it would require a second transformation matrix to move the origin to the corner in the rotating stage, which I found hard to do without moving the shape itself. However, I still find this idea more intuitive.
Even in this idea of matching centers, modelX is still somewhat useful. You track which corner the user clicked, and that decides the rotation from that corner, so it doesn't throw the user off.
I will go back to try to write everything without the modelX later tonight.
Here is a demonstration. This program is not as complete as yours, so bare with me. I have created a series of states.
When the program begins, it is in IDLE. Press '1' to change to center select. Press '2' to change to rotation+resizing select. Press any other number to reset to idle. Press the space bar to get the info of the current target and cursor objects.
To move the cursor's center, you need to press 1 and then left click +hold the cursor's center to drag the cursor square. Release the left button to release the cursor square into its new position. Notice this only works if you click close to the center of the cursor square. If the center of the two objects are "close", the border will change from gray to yellow.
Similarly, to rotate, you do the following. Not mandatory but you want to first align the cursor's center with the target's center. Then, you press 2 and then you click the top left corner of the cursor's square (you have to be click as close as you can to this corner) and then you have two options:
Extra to do is that when you align the cursor's top left corner to the biggest blue corner, the figures are align. I did not implement that part. However, I do provide the position of those corners in the tCorners array. I hope this helps.
Kf