I have a graphics application in JAVA, which is made up of many different shapes (lines, circles, arcs, etc, which are drawn via the Graphics.drawLine(), drawArc()... methods). I would like to create mouse-over events on many, if not all of the drawn objects.
What I was thinking was to store some sort of bitmap with metadata in it, and use that to figure out which object the mouse is over. Is there a way to do this in Java? (looping through all the objects per mouse move doesn't seem viable).
Thanks,
John
Key-color solution
(moved from comment)
Create an off-screen graphics buffer (like BufferedImage), same size as subject image.
Draw all objects into this buffer. Each object with one own color. Depending on object count you can optimize image buffer: For example use 8-bit graphics.
Read resulting image buffer by pixel (example Java - get pixel array from image). Determine pixel color at current mouse position, and map color index (or RGB value) to the source object.
Pros:
The solution is "pixel-accurate": Object boundaries are exact - pixel to pixel.
Easy to solve overlapping objects problem. Just draw them at the desired order.
Object complexity is not limited. Theoretically bitmaps are also possible.
Cons:
To move one object, the complete off-screen buffer must be repainted
Number of objects can be limited when using low-bit image buffer
It depends on your specifications. You do not mention if those shapes are allowed to overlap, to move, how many of them can exist etc.
Solution a) The easiest approach that comes to mind is to implement each shape as a JComponent descedant (e.g. JPanel). So you would have a CirclePanel, an ArcPanel etc that extend JPanel and each one of them paints itself in the same way it is being done now.
Having the shapes as a JComponent allows you to add a MouseListener to each panel that would then handle the mouseEntered(), mouseExited() events.
Solution b) If on the other hand you need to draw all the shapes on a single component's area (as I understand is the case now) then you still do not need to iterate over all the shapes. You just need to introduce an algorithm to categorize the shapes based on their position, to be able to exclude them fast inside your "isMouseOver(Shape s)" test procedure.
For example lets say you divide the area to 2 equal sub-areas left and right (let's call them tiles). When you create each shape you test which tile they intersect to, and you store this information both in the shape and in the corresponding tile.
Now when you need to test if the mouse is over a shape, you decide which tile the mouse is over. This way you only have to check shapes that intersect either the left or the right tile. Assuming that your shapes are distributed uniformly on the screen, you have just rejected 50% of the shapes with one test.
Depending on how many shapes you have, you could use 4 or 8 tiles, or you could even create/delete tiles dynamically (e.g. based on how many objects tend to gather in one area of the screen or not).
I would suggest to try the first solution because it is easier and a cleaner approach. If you decide that it does not fit your needs, you could then go for an approach similar to the second one.
Related
I'm having quite a bit of difficulty wrapping my head around the actual display side of things with libgdx. That is, it just seems fairly jumbled in terms of what needs to be done in order to actually put something up onto the screen. I guess my confusion can sort of be separated into two parts:
What exactly needs to be done in terms of creating an image? There's
Texture, TextureRegion, TextureAtlas, Sprite, Batch, and probably a
few other art related assets that I'm missing. How do these all
relate and tie into each other? What's the "production chain" among
these I guess would be a way of putting it.
In terms of putting
whatever is created from the stuff above onto the monitor or
display, how do the different coordinate and sizing measures relate
and translate to and from each other? Say there's some image X that
I want to put on the screen. IT's got it's own set of dimensions and
coordinates, but then there's also a viewport size (is there a
viewport position?) and a camera position (is there a camera size?).
On top of all that, there's also the overall dispaly size that's
from Gdx.graphics. A few examples of things I might want to do could
be as follow:
X is my "global map" that is bigger than my screen
size. I want to be able to scroll/pan across it. What are the
coordinates/positions I should use when displaying it?
Y is bigger
than my screen size. I want to scale it down and have it always be
in the center of the screen/display. What scaling factor do I use
here, and which coordinates/positions?
Z is smaller than my screen
size. I want to stick it in the upper left corner of my screen and
have it "stick" to the global map I mentioned earlier. Which
positioning system do I use?
Sorry if that was a bunch of stuff... I guess the tl;dr of that second part is just which set of positions/coordinates, sizes, and scales am I supposed to do everything in terms of?
I know this might be a lot to ask at once, and I also know that most of this stuff can be found online, but after sifting through tutorial after tutorial, I can't seem to get a straight answer as to how these things all relate to each other. Any help would be appreciated.
Texture is essentially the raw image data.
TextureRegion allows you to grab smaller areas from a larger texture. For example, it is common practice to pack all of the images for your game/app into a single large texture (the LibGDX “TexturePacker” is a separate program that does this) and then use regions of the larger texture for your individual graphics. This is done because switching textures is a heavy and slow operation and you want to minimize this process.
When you pack your images into a single large image with the TexturePacker it creates a “.atlas” file which stores the names and locations of your individual images. TextureAtlas allows you to load the .atlas file and then extract your original images to use in your program.
Sprite adds position and color capabilities to the texture. Notice that the Texture API has no methods for setting/getting position or color. Sprites will be your characters and other objects that you can actually move around and position on the screen.
Batch/SpriteBatch is an efficient way of drawing multiple sprites to the screen. Instead of making drawing calls for each sprite one at a time the Batch does multiple drawing calls at once.
And hopefully I’m not adding to the confusion, but another I option I really like is using the “Actor” and “Stage” classes over the “Sprite” and “SpriteBatch” classes. Actor is similar to Sprite but adds additional functionality for moving/animating, via the act method. The Stage replaces the SpriteBatch as it uses its own internal SpriteBatch so you do not need to use the SpriteBatch explicitly.
There is also an entire set of UI components (table, button, textfield, slider, progress bar, etc) which are all based off of Actor and work with the Stage.
I can’t really help with question 2. I stick to UI-based apps, so I don’t know the best practices for working with large game worlds. But hopefully someone more knowledgeable in that area can help you with that.
This was to long to reply as a comment so I’m responding as another answer...
I think both Sprite/SpriteBatch and Actor/Stage are equally powerful as you can still animate and move with Sprite/SpriteBatch, but Actor/Stage is easier to work with. The stage has two methods called “act” and “draw” which allows the stage to update and draw every actor it contains very easily. You override the act method for each of your actors to specify what kind of action you want it to do. Look up a few different tutorials for Stage/Actor with sample code and it should become clear how to use it.
Also, I was slightly incorrect before that “Actor” is equivalent to Sprite, because Sprite includes a texture, but Actor by itself does not have any kind of graphical component. There is an extension of Actor called “Image” that includes a Drawable, so the Image class is actually the equivalent to Sprite. Actor is the base class that provides the methods for acting (or “updating”), but it doesn’t have to be graphical. I've used Actors for other purposes such as triggering audio sounds at specific times.
Atlas creates the large Texture containing all of your png files and then allows you to get regions from it for individual png's. So the pipeline for getting a specific png graphic would be Atlas > Region > Sprite/Image. Both Image and Sprite classes have constructors that take a region.
I wish to create a dynamic outline to a Shape (AWT) by adding objects (with draw functions) to appropriate positions on screen along the shape's perimeter. I want a roughly even distance between each object. (An alternative approach to the same affect will be fine.)
How might I acquire the locations for these objects? I know shapes have a path iterator, but I have no idea how to use it.
You might look at a library such as the one described in A Shape Diagram Editor.
If you want to experiment, GraphPanel is a simple object drawing program that features moveable, resizable, colored nodes connected by edges. If the nodes were a little smaller, they'd be moveable points on a Shape that can be iterated as shown here for Polygon.
Addendum: I want a roughly even distance between each object.
The class Node exposes a number of static methods that operate on a List<Node> such as selected. Existing implementations serve, for example, to translate or resize multiple selections as a unit. Functions for Align and Distribute could be implemented similarly. I'd look at LayoutManger as an example for the latter.
Use FlatteningPathIterator to get points for Shape's path.
Also you can use BasicStroke's method
public Shape createStrokedShape(Shape s)
to get Shape's outline with desire width.
I wanted to create Conway's Game of Life. I read the Java 2d API, but the Graphics class only provides methods to drawRect() and fillRect() on the paintComponent of a JPanel. I mean that the rectangles cannot be handled individually as objects i.e. so that i can check which one is on in relation to the ones in the vicinity.
So I wanted to ask how are squares to be made so that they can be handled individually and the grid be created dynamically?
Create a Sqaure class with all properties required.
Create a list of Square objects representing the board.
In the draw method for the JPanel, iterate over your list of Square objects, drawing each one out, based on its properties.
Keep your display code separate from your logic as much as possible - it's nearly always a good idea.
I'd like to propose a completely different solution. Normally have to treat the generated graphics as output-only, meaning, you don't want to read state from the graphics because that'd be too slow.
You'll have to keep the state of the cells elsewhere, like in a two-dimensional array.
boolean[][] or int[][] for example.
Then you'll need a "render" method of sorts, that takes the values of your cells, and draws it out.
But I'd like to propose an even cooler way of doing this. Instead of keeping a two dimensional array, use the (one dimensional) array that a BufferedImage is made up of.
Normally, each "pixel" is an element in that array. Then you use drawImage to draw that image, and scale that image up. This could perform really well. You might be able to have an entire screen draw in real time pretty much.
There are various methods on BufferedImage, it gets a little confusing at first. In the end you'll find a DataBuffer somewhere. You'll want access to the int[].
Then, to set a cell: data[y * width + x] = -1; (white cell)
to clear a cell: data[y * width + x] = 0; (black cell)
(for example - or vice versa - or any other color).
You can get really fancy with this. You could use various offset variables instead of having to calculate the y*width+x all the time, and optimize it really well.
In fact, I go as far as being able to make it so efficient, that you could actually outperform another guy making the exact same program in C++.
I have rendered a 3D scene in OpenGL viewed from the gluOrtho perspective. In my application I am looking at the front face of a cube of volume 100x70x60mm (which I have as 1000x700x600 pixels). Inside this cube I have rendered a simple blue sphere which sits exactly in the middle and 'fills' the cube (radius 300 pixels).
I now want to read the color value of pixels (in 3D) at specific points within the cube; i.e. I wish to know if say point (100,100,-200) is blue or blank (black).
glReadPixels only allows 2D extraction of color and I have tried it with the DEPTH_COMPONENT but am unsure what this should return in byte form? Is there a way to combine the two? Am I missing something?
I am using Eclipse with Java and JOGL.
This can't be done in the context of OpenGL--you'll need some sort of scene graph or other space partitioning scheme working in concert with your application's data structures.
The reason is simple: the frame buffer only stores the color and depth of the fragment nearest to the eye at each pixel location (assuming a normal GL_LESS depth function). The depth value stored in the Z-buffer is used to determine if each subsequent fragment is closer or farther from the eye than the existing fragment, and thus whether the new fragment should replace the old or not. The frame buffer only stores color and depth values from the most recent winner of the depth test, not the entire set of fragments that would have mapped to that pixel location. Indeed, there would be no way to bound the amount of graphics memory required if that were the case.
You're not the first to fall for this misconception, so I say it the most blunt way possible: OpenGL doesn't work that way. OpenGL never(!) deals with objects or any complex scenes. The only thing OpenGL knows about are framebuffers, shaders and single triangles. Whenever you draw an object, usually composed of triangles, OpenGL will only see each triangle at a time. And once something has been drawn to the framebuffer, whatever has been there before is lost.
There are algorithms based on the concepts of rasterizers (like OpenGL is) that decompose a rendered scene into it's parts, depth peeling would be one of them.
I'm writing a simple painting program. To simulate a pencil drawing, I've stored the drawn points in a set, so when the window is resized the points won't be gone, and whenever another point is added I call the repaint method (the paint method draws all paints in the array on screen). But when the number of points increases, the program runs slowly.
Is there a more efficient method to do this?
The fastest way to get constant-speed repainting is to store the entire image that's drawn as a bitmap, and of course update it when the user draws. This way, you can redraw the right thing, and even add scrollbars and the like if you want. You can keep the array of points for an "undo" feature, for example.
If instead you want to make a vector-drawing program, then you have to keep the individual primitive operations (such as line, rectangles, etc). In that case it still pays off to keep an image for fast repainting, and now the trick becomes how to efficiently update that image when the user modifies the drawing (e.g. by resizing a rectangle). One way to do that is to tile the drawing area into lots of smaller ones, so you only need to recompute the underlying image for the parts that intersect with the object being modified by the user.
In both techniques, you'd use double-buffering just so that the user doesn't perceive flicker. But with double-buffering alone, the "redraw the whole set of points" would still be slow.
Since you haven't give any code, I am guessing that you are using primitive drawing methods (like draw a line or point).
A good option would be to use the Double Buffering technique to do the painting.
Look up GeneralPath.
What you can do is create a Shape class, that'll vary according to what you are going to draw (Rectangle, Triangle, Point, Line, etc.). You should do this even though now you're only drawing points.
When you create your Shape have code that checks what Shape to create, something like a switch/case statement:
...
case PENCIL:
if (generalPath == null) {
generalPath = new GeneralPath();
generalPath.moveTo(p1.x, p1.y);
} else {
generalPath.lineTo(p2.x, p2.y);
}
shape = generalPath;
break;
...
In the code that draws, simply call repaint and the Shape will be drawn.