Java Graphical Halfing Mechanism Malfunction - java

g.setColor(c);
double changeFactor = (2<<count);
g.fillRect(x+1, y+1+(int)(boxHeight*(double)(1/changeFactor)), boxWidth-2, boxHeight-2-(int)(boxHeight*(double)(1/changeFactor)));
count++;
if(count == iterations)
{
count = 0;
}
Above is the code for a graphical halfing mechanism that I've been trying to make. In short, the idea for it is a simple graphics exercise that starts with a filled bar and subtracts from its current height by half the height every 250ms. In this way, it is an exponential decline in height. This is the current output:
Link for those of you who are having trouble viewing the image
This is the exact opposite of the output that I want. The white region in the bar is a flipped image of what I want the red region to do. Can you guys help me figure out why the code is not behaving correctly?
Sorry for the newbie question, by the way.
EDIT:
here's the answer:
g.fillRect(x+1, y+1+(int)(boxHeight*(double)((changeFactor-1)/changeFactor)), boxWidth-2, boxHeight-2-(int)(boxHeight*(double)((changeFactor-1)/changeFactor)));
Long story short, it's because I miscalculated the numerator for what I would want the height/y-coordinate to be.

According to the fillRect definition, the second parameter is the location of the top of the box. (In computer graphics, numbers often get bigger as you go downward along the Y axis, which is the opposite from how mathematicians draw graphs.) Assuming you want the top of your bar to keep heading downward (as opposed to the bottom of the bar going upward), that means that the second parameter needs to keep getting larger. However, in your code, the parameter keeps getting smaller, since 1/count keeps getting smaller.
If h is the total height and y is the top of the box, then the successive values you want for this parameter are:
y
y + h/2
y + h/2 + h/4
y + h/2 + h/4 + h/8 ...
or, expressed another way:
y + h - h
y + h - h/2
y + h - h/4
y + h - h/8
Based on that, I think you can see how to make some small modifications to the code and get it to work.
Also, make sure you clear the box in between iterations. fillRect won't touch anything outside the rectangle that you're drawing. So if you want to make the filled part smaller, you have to do something to clear out the part that was previously colored that you don't want colored any more.

Related

generate random location for buttons

I am making a simple game.
I have 6 buttons and i want to shuffle them each time on different locations.
So i've made a simple method to achieve this.
private void changeButtonPlace(ImageView button) {
Random r = new Random();
int newXloc = r.nextInt(getScreenWidth() - (2 * button.getLayoutParams().width));
int newYloc = r.nextInt(getScreenHeight() - (3 * button.getLayoutParams().height));
button.setX(newXloc);
button.setY(newYloc);
}
It works pretty well, but sometimes the buttons override each other which means that it goes on the almost the same location. I want each button to be on a unique location and don't touch other buttons.
Any idea how i can achieve this?
Thanks in advance!
What you are looking for is collision detection, and my answer will greatly simplified this process. I suggest searching for collision detection algorithms to learn more.
So, for super simple starts, we can compare the position, length, and height of 2 boxes. For my example, I am going to assume the origin of these to boxes are their upper left corner.
if((boxA.xPos + boxA.length ) < boxB.xPos || boxA.xPos > (boxB.xPos + boxB.length))
That will check if the two boxes are touching along the x-axis, and we can change the values for the y-axis as well
if((boxA.yPos + boxA.height ) < boxB.yPos || boxA.yPos > boxB.yPos + boxB.height)
Now, this is not a very efficient way of doing this. There are lots and lots of better ways to simplified this logic, and save on resources. But, it is quick and dirty, and probably good enough for a small application like your simple game involving only 6 buttons.
So, with these two equations, you can either nest them then run your collision code inside, or you can OR them together to one equation like this:
if(((boxA.yPos + boxA.height) < boxB.yPos || boxA.yPos > (boxB.yPos + boxB.height)) || ((boxA.xPos + boxA.length ) < boxB.xPos || boxA.xPos > (boxB.xPos + boxB.length)))
That is a lot to read for one line, and if you just starting out, I would suggest nesting them so you can better see the flow of logic through the equations. But, keep in mind for the future, if you ever need to squeeze those few extra bits of performance, OR them together to one if statement is alright place to start.
One way would be to make a grid and instead of a random location on the screen use a random point on the grid. That way you can check if the current grid location has a button on it already.
If you want them to be more scattered you could add each button to an array and check that the new doesn't touch the other buttons. Loop infinitely creating random locations and another loop to check they don't hit the other buttons in the array. Once a new location is found add the button and break out of the infinite loop.
You should take in account the width of the button , and before setting the location of the button make sure no button intersect with a simple if, if they do just randomize the intersecting buttons, should be easy to programm
Edit :
Lets make it a bit simpler an assume you have 3 buttons an assuming they are located on a 2d axis with these coordinates
A : 1,0
B : 2,0
C : 5,0
button width : X=2 Y=2
As you can see in this example at first glance it seems as though no button intersects with each other yet if you add the width to B you understand that is real location is B [1,3] ,[-1,1] intersects with the real location of C [4,6],[-1,1] assuming the coordinates are the center of the button
first [,] represents X axis second [,] represents Y axis
therefore your check will be something like so:
For each Button x
For each button x
calculate real coordinates of button x and y check intersection
if exists recalculate the coordinates and start the loop over
this solution is a bit expensive when talking about running time but once you get the idea you will be able to find something easier.

Checking depth/z when rendering triangular faces in 3d space

My question can be simplified to the following: If a 3d triangle is being projected and rendered to a 2d viewing plane, how can the z value of each pixel being rendered be calculated in order to be stored to a buffer?
I currently have a working Java program that is capable of rendering 3d triangles to the 2d view as a solid color, and the camera can be moved, rotated, etc. with no problem, working exactly how one would expect it to, but if I try to render two triangles over each other, the one closer to the camera being expected to obscure the farther one, this isn't always the case. A Z buffer seems like the best idea as to how to remedy this issue, storing the z value of each pixel I render to the screen, and then if there's another pixel trying to be rendered to the same coordinate, I compare it to the z value of the current pixel when deciding which one to render. The issue I'm now facing is as follows:
How do I determine the z value of each pixel I render? I've thought about it, and there seem to be a few possibilities. One option involves finding the equation of the plane(ax + by + cz + d = 0) on which the face lies, then some sort of interpolation of each pixel in the triangle being rendered(e.g. halfway x-wise on the 2d rendered triangle -> halfway x-wise through the 3d triangle, same for the y, then solve for z using the plane's equation), though I'm not certain this would work. The other option I thought of is iterating through each point, with a given quantum, of the 3d triangle, then render each point individually, using the z of that point(which I'd also probably have to find through the plane's equation).
Again, I'm currently mainly considering using interpolation, so the pseudo-code would look like(if I have the plane's equation as "ax + by + cz + d = 0"):
xrange = (pixel.x - 2dtriangle.minX)/(2dtriangle.maxX - 2dtriangle.minX)
yrange = (pixel.y - 2dtriangle.minY)/(2dtriangle.maxY - 2dtriangle.minY)
x3d = (3dtriangle.maxX - 3dtriangle.minX) * xrange + 3dtriangle.minX
y3d = (3dtriangle.maxY - 3dtriangle.minY) * yrange + 3dtriangel.minY
z = (-d - a*x3d - b*y3d)/c
Where pixel.x is the x value of the pixel being rendered, 2dtraingle.minX and 2dtriangle.maxX are the minimum and maximum x values of the triangle being rendered(i.e. of its bounding box) after having been projected onto the 2d view, and it's min/max Y variables are the same, but for its Y. 3dtriangle.minX and 3dtriangle.maxX are the minimum and maximum x values of the 3d triangle before having been projected onto the 2d view, a, b, c, and d are the coefficients of the equation of the plane on which the 3d triangle lies, and z is the corresponding z value of the pixel being rendered.
Will that method work? If there's any ambiguity please let me know in the comments before closing the question! Thank you.
The best solution would be calculating the depth for each vertex of the triangle. Then we are able to get the depth of each pixel the same way we do for the colors when rendering a triangle with Gouraud shading. Doing that simultaneously with rendering allows to check the depth easily.
If we have a situation like this:
And we start to draw lines from the top to the bottom. We calculate the slopes from the point one to the others, and add the correct amount of depth every time we move to the next line... And so on.
You did't provide your rendering method, so can't say anything specific to it, but you should take a look at some tutorials related to Gouraud shading. Do some simple modifications to them and you should be able to use it with depth values.
Well, hopefully this helps!

Use loops to create a pyramid in Java

I am trying to create a hollow pyramid of sorts using a loop. The way I would like to approach this is to start at a certain Y, and decrease it by 1, while expanding the X and the Z out by one while covering the perimeter.
*
* *
* *
* *
* *
Granted this would be 3D, using XYZ.
So my main question is, if I have 3 points, X=50 Y=50 Z=50, how would I go down each level of Y while getting the points around the center?
So far
for (int y = 1; y<15; y++) {
l.setY(l.getY() - 1);
l.setX(l.getX() + 1);
l.setZ(l.getZ() + 1);
l.getBlock().setType(Material.GLASS);
}
will only generate a staircase of sorts going 15 blocks down from the starting position
Please imagine the graph of the 3 axis, if you are not practice with it just take a look at this graph.
We will use z as height, by rotating the axis in order to have a clear picture of what is happening. You may as well use z as the depth parameter but it will be harder for you to understand what is going on.
You obtain a wrong plot because you are not moving towards the space in the right way..
What you are looking for is starting by a point, say S=(x,y,z) = (5,5,5) and you want to go down each level by printing your edges for the piramid.
the starting point is plotted as shown in the following figure
By moving down decrementing z you want to draw 4 points (you may want to draw some more, I just draw the edges in this case).
so in the next cycle you have z = z-1;
thus you have to move in the 4 directions allowed by the graph.
The point in the middle keeps the center of the pyramid, while the others are respectively
(5,4,4) (5,6,4) --> moving along y axis
(4,5,4) (6,5,4) --> moving along x axis
while you cycle you keep moving this, by using as metrics the difference between the center, the level(height) and the axis while drawing the pyramid..
HOW? see the last following picture, I added some color to help you keeping track of what is happening. Further I added axis and main points coordinates.
Red points keep the center of the pyramid, by starting at S = (5,5,5) (which is the top) you go down to S1 =(5,5,4) and S2 = (5,5,3).. so imagine this are 2 cicles of your while loop.
Green points keep track of the first cycle, when z = 4,
the center of the pyramid is S1 this time. You want to expand in the space by moving on the y and x axis.
By the center you move -1 and -+1 on y.. so obtaining (5,4,4) and (5,6,4). So far you obtain 2 edges. Let's move on the x axis keeping the center as is, the same this time you move by 1 unit toward such plane so that you have (6,5,4) and (4,5,4)..
The same happens with the second cycle. The distance you move is obtained by
starting height - actual level height
in the case of z = 3 you have to from the center by 5 - 3 = 2 unit (by previous statement)
so on and so forth for the rest of the cycle up to the point you end up.
You may want to stop at 0 unit of shift from center (when starting height == actual level height) by obtaining a nice and well drawn pyramid, other wise you can keep cycling but you have to find another way to stop, the previous subtraction in fact works also with negative height, you can notice that if you reach z = -1 the previous will tell you to shift of 6 units, in this case you have to find another way to stop and break your cycle.
This said you have to adjust your cycle to draw the 4 points, instead of those that you actually draw =)
You go the staircase at only one side down. On the other side, x and z grow in the other direction.

Java OpenGL screen to world transformation using gluUnProject + design discussion

I've got 2 questions. One's a specific question about why my code isn't working as intended and the other is a design question.
1 (Specific Question): I'm trying to map screen coordinates to world coordinates in a 2D tile-based engine (uses the x/y axis, z = 0). I've used a Nehe's tutorial port on how to achieve this but the results I get aren't as expected.
I have a class called MouseController. Whenever a mouse event is trigger (via swing's MouseListener), I pass the MouseEvent into my MouseController.
In my GLCanvas's draw function, I call the MouseController.processClick(GL) function to be able to pass the current gl context into the processClick function and grab the modelview, projection matrices and viewport.
When I click on a block rendered on the screen, the world coordinates that are given back to me make little to no sense. For one, I would expect the z value to be 0, but its 9 (which is how high my camera is set to), and my x and y values are always really close to 0 (occasionally jumping up to 1-9 with very slight movements, then back to a number very close to 0).
Anyone have any idea why this might be the case? The processClick function is below:
public void processClick(GL gl) {
int x = e.getX();
int y = e.getY();
if(e.getButton() == MouseEvent.BUTTON1) {
gl.glGetIntegerv(GL.GL_VIEWPORT, viewPort, 0);
gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, mvMatrix, 0);
gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, prMatrix, 0);
int realy = viewPort[3] - y;
glu.gluUnProject((double)x, (double)realy, 0, mvMatrix, 0, prMatrix, 0, viewPort, 0, wCoord, 0);
System.out.println(x + " " + y);
System.out.println(x + " " + realy);
System.out.println(wCoord[0] + " " + wCoord[1] + " " + wCoord[2]);
}
e = null;
}
Sample output I get from the above function when I click on the screen where I rendered a square at world coordinates (4,5,0):
878 56
878 636
0.0445182388817236 0.055475957454737095 8.900000001489369
Thanks!
EDIT: Reading in the depth buffer using glReadPixels and using that as the z (which returns 1) gets me results that are kind of right, but are too big by a factor of 20.
EDIT2: If I set the far clipping plane to the same value as the height of the camera, it seems to work (but this isn't really a fit).
2 (Design Question): I feel as if it doesn't make sense to process clicks in the OpenGL canvas' draw function. I seem to require the GL from that function to be able to retrieve the matrices necessary for gluUnProject to run. How would you guys design this? Ideally I feel as if I should be able to have this run completely separate of the draw function. Store a reference to the gl object into my MouseController and process the click when the MouseListener picks up on it.
Input about how you guys would/do handle it would be much appreciated too!
I decided just to use gluOrtho2D to setup my projection to simplify solving this problem.
The only "tricky" thing was passing in the actual screen resolution to gluOrtho2D, which could be retrieved (and stored) with:
getContentPane().getSize()
From the JFrame I used.
Setting the preferred size on the panel then packing the frame achieved close results, but the panel itself was still slightly off.

Use Java to identify lines in a graph

I am working on an idea wherein I have to identify lines in a JPG or PNG file. The PNG file contains one graph of a single value - one x,y combination. For example, the graph looks like Y = mx+c.
I would like to identify the line in the graph - if I can indentify the position of the pixel in the frame, I believe I can get back the values (x,y) which were used to plot the graph. The assumptions here is - I know the scale i.e 1 pixel = what unit of Y ?
Can somebody please help me to write a code which will identify the pixels of a specific color in one PNG file?
EDIT
Lets take an example to make it clear. Lets say I have a set of data values X and Y like this -
X = 1, Y = 10
X = 2, Y = 20
X = 3, Y = 30
X = 4, Y = 40
X = 5, Y = 50
X = 6, Y = 60
In this case, if I use jfreechart type of charting tool and make a chart, it tools like a straight line.
So the input is the dataset and output is the .PNG file (using jchart or jfreechart) containing this line graph for Y values.
Question is - if we reverse the flow, can we develop one program which will take the PNG file (that contains the graph) and give me back the dataset.
The context of the problem is -- I want to store the PNG files in my application and not the raw dataset. But given a PNG file, I should be able to get back my dataset.
I'm a bit confused as to whether your problem is simply determining the colour of pixels in an image, or if the problem is the mathematics of what you're trying to do.
For the former, do something such as the following:
BufferedImage bimg = ImageIO.read(new File("whatever.png"));
// get the colour of the pixel at position (x, y)
int col = bimg.getRGB(x, y);
// decode red, green and blue components of colour if necessary
int r = (col >> 16) & 0xff;
int g = (col >> 8) & 0xff;
int b = col & 0xff;
If from the graph you just want to get back the dataset (i.e. not derive an equation from that data), then you essentially loop through each X position and find the Y position where there's a pixel of the colour that the graph plotting program uses. If the graph has axes, antialiasing etc, then the task will be more complex.
The task of deriving an equation from the data is potentially much more complex, but you can start by checking for certain suspected formulae such as y = mx + c as you mention. For example, you can loop through checking the difference between each Y position for the last; if that difference is always the same, then you've got a straight line graph (and at that point, deriving the formula should be trivial).
For testing for other equations, it helps to know a bit of calculus. Then, a starting point is to see if the differences in the differences match the derivative for the equation in question. (Just as an example, if the equation is y = ax^2 + c, then for every increase in X, the increase in Y will itself increase by 2a.)
Do I read that correctly: you have an image of a single line on an otherwise blank canvas? If so, you can just look down the leftmost pixel column and find the pixel that is different, then take a column a bit to the right and find the pixel there. Now you have two points, and generating a linear function from that is trivial. As unit, why not use pixels?
Generally, on a computer monitor you don't have a central (0,0) point, as that point is defined to be the top left corner of the screen. So if we are looking at a function f(x)=ax+b then b parameter is defined to be the y value of the function at x=0, meaning the left border of the screen. So it's important to define exactly what you are offsetting from.
To find the slope, just take some central point on the screen you know you have a point of the function there, go x pixels to the left or the right, find the y height delta, and y/x is the function slope, or parameter a in the function aforementioned.
i am not sure where you reached with your project, but i needed to detect lines in an image as well. Here is what helped me.
http://www.music.mcgill.ca/~cmckay/software/musictech/ScoreReader/HorizontalLineDetection.html

Categories