scale() and shape() in Processing - java

UPDATE: I think I figured it out. The scaleMultiplier also applied to the translate that I was trying to do. I had a suspicion this was the case but couldn't figure out exactly how it got affected.
Anyone familiar with a spinoff of Java called Processing? I'm trying to do something simple, scale a shape and place it in the center of the sketch. This is my code in a nutshell:
pushMatrix();
float scaleX, scaleY, scaleMultiplier, resetX, resetY, transX, transY;
scaleX = 500 / (float)clickState.bounds.getWidth();
scaleY = 500 / (float)clickState.bounds.getHeight();
scaleMultiplier = min(scaleX,scaleY);
resetX = -(float)clickState.bounds.getX();
resetY = -(float)clickState.bounds.getY();
transX = resetX + ((800 - ((float)clickState.bounds.getWidth() * scaleMultiplier))/2);
transY = resetY + ((550 - ((float)clickState.bounds.getHeight() * scaleMultiplier))/2);
scale(scaleMultiplier);
shape(clickState.pshape, transX, transY);
popMatrix();
What I'm trying to do is scale a state on a US Map. clickState is the state that the user clicked on. clickState.bounds is a Rectangle that surrounds the shape of the state. getX() and getY() return the x and y coords of the upper left hand corner of said box. I want to scale the state so that it's no bigger than 500x500 pixels. After that, I want to translate it so that it's in the middle of the sketch, which is 800x550.
Here's where I run into trouble: When I do
shape(clickState.pshape, resetX, resetY);
It draws the state in the upper left hand corner of the sketch. That's exactly what it should do. Then from there I want to add the number of pixels that it would take to center the shape, which is what transX and transY are for. However, when I use transX and transY, the shape gets drawn almost completely off the canvas, depending on where the state is located (even if its only being moved 50 pixels to the right from 0,0). It doesn't make any sense to me whatsoever. I've tried all sorts of combinations of translate(), and even skipping scale() altogether and using a width and height in shape(). It's like Processing is trying to frustrate me on purpose. Any help is appreciated.

I'm not familiar with Processing, but matrix operations are not commutative—the order matters. Typically, operations are applied in an apparent last-specified-first-applied order, as shown in this example.

Vince, I think I was trying to do something very similar last week. Sounds like you figured it out, but check out the answers on this board:
http://forum.processing.org/topic/how-do-i-move-svg-child-shapes#25080000000689051

Related

JavaFX: PannableCanvas: get CenterX/Y

I've been using a customized PannableCanvas that was presented here, and I've run into a bit of trouble. My software is almost finished, and the last thing I need to do is add support for spawning the Nodes on the center of the screen. So what I did originally was:
nodeTranslateX/Y = -pannableCanvas.getTranslateX/Y
And that worked until I realized that if you zoom in/out (where scale no longer = 1.0), it completely messes it up and the node starts getting placed in weird spots. So then I tried:
nodeTranslateX/Y = -pannableCanvas.getTranslateX/Y * pannableCanvas.getScale()
And that didn't work either! It gets thrown even further out of whack.
I tried numerous combinations of transformations such as dividing the scale, inverting the scale, using screenToLocal(), you name it. None of them have worked. The problem is that when you zoom out, the translateX/Y of the canvas is adjusted for the scale, but that gives you stuff like 1500 when the nodes should be spawn with sane coordinates like 300.
Is there a way to get the coordinates of the top-left corner of the screen relative to the canvas? I'm completely at a loss on how to fix this. Again, I just need to be able to spawn the node at the center of the screen. What should I do?
Thank you for your time!
I got it to work by doing this:
Window window = scene.getWindow();
double screenCenterX = (window.getX() + window.getWidth()/2);
double screenCenterY = (window.getY() + window.getHeight()/2);
Point2D point = pannablePane.screenToLocal(screenCenterX, screenCenterY);
double nodeX = point.getX() - MyNodeImplementation.WIDTH/2;
double nodeY = point.getY() - MyNodeImplementation.HEIGHT/2;
I had mistaken screenX/Y for being within the window (I.E. center = WIDTH/2, HEIGHT/2), but instead you actually have to take the actual window position into account too.

Java planetary orbit simulation: centering planets

I've created a simple planetary simulation where a planet orbits a star.
The code for the orbit is this:
a = a + vel * delta;
planetX = Math.cos(a) * orbitRadius + parentStar.getX();
planetY = Math.sin(a) * orbitRadius + parentStar.getY();
Now that works just fine, but my problem is that the orbit is not from the center of the planet around the center of the star.
This is what happens
As you can see, the first red dot on the small circle is the Position of the planet wich orbits around the second small red dot, this is because the circle is drawn from (0,0), so both the planets (0,0) circles around the (0,0) of the star.
I need the the center of the planet to circle the stars center, not their origin point.
Is there a good fix for this?
Your calculation of the orbit is fine. The only problem seems to be that you treat "position" differently when calculating orbits and when drawing the planets: When you draw them, you treat x and y as one of the corner points, but when you calculate the oribit, you treat them as the centre of the body. The simplest way would be to change the visualisation, not the calculation.
Since you did not post the code you use to draw the shapes, I can only guess, but I assume it looks somewhat like this (obviously Pseudocode):
for (Planet p : starsAndPlanets) {
drawCircle(p.x, p.y, p.radius * 2, p.radius * 2);
}
Change this to something like this:
for (Planet p : starsAndPlanets) {
drawCircle(p.x - p.radius, p.y - p.radius, p.radius * 2, p.radius * 2);
}
This way, x and y are the position of the centre of the planet, and with p.x - p.radius and p.y - p.radius you get the corner point. Of course, you could in a similar way change all your orbital mechanic formulas to calculate the centre from the corner point, but IMHO it is much simpler and more natural to treat x and y as the centre.
For now the most suitable way I can think of is getting the star's world coordnates and passing them every frame to the child's coordinates. As you do so, the child would have the same coordinates everyframe.
The next part is translating it and rotating it around the Star - the way you can achieve that is by setting the planet's position to be transposed by the Star's position with a sin(x)*cos(x).
Let me show you an example:
planet[0] = star[0] + sin(angle)*scale
planet[1] = star[1] + cos(angle)*scale
Where the angle would change incrementally and the scale will just shift the child object further from its parent, keeping it a constant (or modifying it if you wish) thus increasing the radius from its 'new' center.
I know some people may mention matrices or other types of transformations, but for this situation I think the above solution would be most relevant and cleanest in my opinionp
The way it works is you take the parent's 'WORLD coordinates' and set them to be the child's. By modifying the Scale value you increase the distance of the object from the center (so they won't overlap) and you multiply this with the sin and cos of the angle you specified to make it rotate.
P.S. Keep in mind that if you're dealing an FPS-dependant engine to render, the more FPS the faster the simulation will be, and vice-versa, because if you render at 1000 fps, this means you execute your code 1000 times, compared to 100 for example. Therefore, you will increment the angle 1000 times or 100 respectively. If you have this issue, try setting a constant framerate if you can - it's the simplest workaround for lightweight simulations.
Edit: I forgot to mention that the concept works for all objects in your case. You just have to work our the relationships and use the function for eqch object seperately where each object has a position and angle of orbit (if it orbits around a different object).

Android translated canvas collision of rectangles

im trying do develop a Zelda like game. So far i am using bitmaps and everything runs smooth. At this point the camera of the hero is fixed, meaning, that he can be anywhere on the screen.
The problem with that is scaling. Supporting every device and keeping every in perfect sized rects doesnt seem to be that easy :D
To prevent that i need a moving camera. Than i can scale everything to be equally sized on every device. The hero would than be in the middle of the screen for the first step.
The working solution for that is
xCam += hero.moveX;
yCam += hero.moveY;
canvas.translate(xCam,yCam);
drawRoom();
canvas.restore();
drawHero();
I do it like this, because i dont wand to rearrange every tile in the game. I guess that could be too much processing on some devices. As i said, this works just fine. the hero is in the middle of the screen, and the whole room is moving.
But the problem is collision detection.
Here a quick example:
wall.rect.intersects(hero.rect);
Assuming the wall was originally on (0/0) and the hero is on (screenWitdh/2 / screenHeight/2) they should collide on some point.
The problem is, that the x and y of the wall.rect never change. They are (0/0) at any point of the canvas translation, so they can never collide.
I know, that I can work with canvas.getClipBounds() and then use the coordinates of the returned rect to change every tile, but as I mentioned above, I am trying to avoid that plus, the returned rect only works with int values, and not float.
Do you guys know any solution for that problem, or has anyone ever fixed something like this?
Looking forward to your answers!
You can separate your model logic and view logic. Suppose your development dimension for the window is WxH. In this case if your sprite in the model is 100x100 and placed at 0,0, it will cover area from 0,0 to 100, 100. Let's add next sprite (same 100x100 dimension) at 105,0 (basically slightly to the right of the first one), which covers area from 105,0 to 205,100. It is obvious that in the model they are not colliding. Now, as for view if your target device happens to be WxH you just draw the model as it is. If your device has a screen with w = 2*W, h = 2*H, so twice as big in each direction. You just multiply the x and y by w / W and h / H respectively. Therefore we get 2x for x and y, which on screen becomes 1st object - from 0,0 to 200, 200, 2nd object - from 210,0 to 410, 200. As can be seen they are still not colliding. To sum up, separate your game logic from your drawing (rendering) logic.
I think you should have variables holding the player's position on the "map". So you can use this to determine the collision with the non changing wall. It should look something like (depensing on the rest of your code):
canvas.translate(-hero.rect.centerX(), -.rect.centerY());
drawRoom();
canvas.restore();
drawHero();
Generally you should do the calculations in map coordinates, not on screen. For rendering just use the (negative) player position for translation.

Making a rectangle go around in a circle - Java/Swing

My maths isn't that good so I'm having a bit of trouble in one of my applications that I'm trying to do where I want a rectangle to represent a vehicle and I want that vehicle/rectangle to "drive" around in a circle. Imagine a roundabout with only 1 vehicle in it, just circling around forever.
If I can get some help how to do that then I'll be able to build on the example and most importantly learn.
If someone could write up a simple example for me I'd be grateful. No background no images, just a rectangle "driving" around in a circle. I'm using java and Swing.
Sorry, I am not sure if could understand clear you exactly need. If you need to draw rectangle which is moving around inside of circle, you can use sin/cos functions.
Something like that:
double r = 50.0; // radius (it might radius of your circle, but consider dimensions of rectangle to make sure you are drawing inside of circle, e.g. circleRadius - rectangeDimesion / 2.0)
for (int f = 0; f < 360; f++) {
double x = Math.sin(Math.toRadians((double)f)) * r;
double y = Math.cos(Math.toRadians((double)f)) * r;
// draw rectangle on [x, y] coordinates
}
If you know the radius of the round about, all the you would need would be a trigonometric function and the angle which the vehicle makes to the round about. You could take a look at this simple introduction which should get you started in the right direction.
On another hand, another approach would be to use a Transformation Matrix where you start with a matrix containing two points (your X and Y co-ordinates) and you transform them to become the new co-ordinates.
You can then rotate the rectangle to mimic a vehicle turning.
If you have a limited background in Mathematics, the first option might be easier for you to grasp.
This is more an extended comment than an answer.
I would divide the problem up into several easier problems, and work on each of them separately:
Draw your rectangle with a specified center location and long axis orientation.
Determine the center point and long axis orientation for an object orbiting around the origin. Note that to get make the long axis a tangent it needs to be perpendicular to the radius through the center.
Translate the whole system so that it orbits the desired point, rather than the origin.

Rotation in OpenGl ES to place objects then rotate the world

I am developing an augmented reality application for android and trying to use openGl to place cubes at locations in the world. My current method can be seen in the code below:
for(Marker ma: ARData.getMarkerlist().values()) {
Log.d("populating", "");
gl.glPushMatrix();
Location maLoc = new Location("loc");
maLoc.setLatitude(ma.lat);
maLoc.setLongitude(ma.lng);
maLoc.setAltitude(ma.alt);
float distance = currentLoc.distanceTo(maLoc);
float bearing = currentLoc.bearingTo(maLoc);
Log.d("distance", String.valueOf(distance));
Log.d("bearing", String.valueOf(bearing));
gl.glRotatef(bearing,0,0,1);
gl.glTranslatef(0,0,-distance);
ma.cube.draw(gl);
gl.glPopMatrix();
}
gl.glRotatef(y, 0, 1, 0);
gl.glRotatef(x, 1, 0, 0);`
Where y is yaw and x is the pitch. currently I am getting a single cube on the screen at a 45 degree angle someway in the distance. It looks like I am getting sensible bearing and distance values. Could it have something to do with the phones orientation? If you need more code let me know.
EDIT: I updated bearing rotation to gl.glRotatef(bearing,0,1,0); I am now getting my cubes mapped horizontally along the screen at different depths. Still no movement using heading and pitch but #Mirkules has identified some reasons why that might be.
EDIT 2: I am now attempting to place the cubes by rotating the matrix by the difference in angle between heading and bearing to a marker. However, all I get is a sort of jittering where the cubes appear to be rendered in a new position and then jump back to there old position. Code as above except for the following:
float angleDiff = bearing - y;
gl.glRotatef((angleDiff),0,1,0);
gl.glTranslatef(0,0,-distance);
bearing and y are both normalised to a 0 - 360 scale. Also, I moveed my "camera rotation" to above the code where I set the markers.
EDIT 3: I have heading working now using, float angleDiff = (bearing + y)/2;. However, I cant seem to get pitch working. I have attempted to use gl.glRotatef(-x,1,0,0); but that doesn't seem to work.
It's tricky to tell exactly what you're trying to do here, but there are a few things that stick out as potential problems.
Firstly, your final two rotations don't seem to actually apply to anything. If these are supposed to represent a movement of the world or camera (which mostly amounts to much the same thing) then they need to happen before drawing anything.
Then your rotations themselves perhaps won't entirely do what you intend.
Your cube is rotated around the Z axis. The usual convention in GL is for the camera to look down the Z axis, with the Y axis being considered 'up'. You can naturally interpret axes however you like, but a rotation around 'Z' would not typically be 'bearing', but 'roll'. 'Bearing' to me would be analogous to 'yaw'.
As you translate along the Z axis, I assume you are trying to position the object by rotating and translating, but obviously if the rotation is around the same axis as you translate along, it won't actually alter the position of the cube - it will always just be directly in front of the camera, spinning on its axis.
I'm not really clear on why you're trying to position the cube like that when it seems like you start off with a more specific location. You could probably directly construct a more appropriate matrix.
Finally, your camera/world rotation is two concatenated rotations around Y and X. You call these pitch and roll, but typically using euler angles for a camera rotation does not result in an intuitive result where terms like pitch and roll make complete sense. It is common to maintain an orientation and apply individual rotations to that in order to update it, rather than attempting to update several dependent rotations.
So yes, I would expect that this code, in the absence of other matrix operations, would likely result in drawing one or more cubes straight ahead which are simply rotated by some angle around the view direction.

Categories

Resources