LWJGL Camera stretches and shrinks shapes - java

I've been looking around and i couldn't find an answer to this but what I have done is create a cube / box and the camera will squash and stretch depending on where I am looking at. This all seems to resolve it self when the screen is perfectly square but when I'm using 16:9 it stretches and squashes the shapes. Is it possible to change this?
16:9
and this is 500px X 500px
As a side question would it be possible to change the color of background "sky"?

OpenGL uses a cube [-1,1]^3 to represent the frustum in normalized device coordinates. The Viewport transform strechtes this in x and y direction to [0,width] and [0,height]. So to get the correct output aspect ratio, you have to take the viewport dimensions into account when transfroming the vertices into clip space. Usually, this is part of the projection matrix. The old fixed-function gluPerspective() function has a parameter to directly create a frustum for a given aspect ratio. As you do not show any code, it is hard to suggest what you actually should change, but it should be quite easy, as it boils down to a simple scale operation along x and y.
To the side question: That color is defined by the values the color buffer is set to when clearing the it. You can set the color via glClearColor().

Related

Libgdx Spritebatch bug

however, i have a weird issue, when drawing, it seems the outside 1px of an image is stretched to fit a rectangle, but the inside is only stetched to an extend, i was drawing to 48x48 tiles, but drew a 500x500 tile to show the issue. [ 500x500 draws fine ]
the worst part seems to be, it chooses when to stretch and not to stretch. and also what to strech. im sorry this is hard to explain but i have attached a image that i hope does a better job.
it could just be misunderstanding how to use a draw with spritebatch
edit: Tile is 48x48 not 64x64, ive just been working all day.
This is because you are not rendering "pixel perfect" which means your image does not line up with the pixel grid of your monitor. A quick fix might be to set a linear filter for your textures, since by default it uses nearest and thus a pixel on the screen will inherit the closest color it can get. A linear filter will interpolate colors and make that line "look" thinner.
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
If you are using texturepacker you can do this in one go by altering it's settings.
texturePackerSetting.filterMin = Texture.TextureFilter.Linear;
texturePackerSetting.filterMag = Texture.TextureFilter.Linear;
Or you could edit the atlas file itself by by changing the filter parameter to:
filter: Linear,Linear
This obviously costs more power since it needs to do more calculations for each pixel you drawn to the screen but I would not worry about this until your drawing is starting to get a bottleneck.
Another solutions is to draw pixel perfect which means you need to set your viewport to the size of the device gdx.graphics.getWidth, gdx.graphics.getHeight, in other words a ScreenViewport and draw your textures at exact sizes you want them. Of course this means a screen with more pixels sees more of your game world then a screen with less pixels and the more pixels a device has the smaller your textures will look. Another drawback of this is that you have to forget about any zooming or draw sprites for each level of zoom so they line up with the pixel grid of the device again.

How to start an Activity in specific coordinates

My Activity has a Canvas with both width and height equal to 6000. When I start the Activity the upper left coordinate of my screen is (0,0) so screen' center is about (30,60). What I want is start the Activity with coordinates (3000,3000) in the center of screen
any solution?
Update 1:
I used this Kotlin code:
var fondo = Lienzo(this) //fondo is the Canvas View (6000,6000)
val scrollV = ScrollView(this)
val hscrollV = HorizontalScrollView(this)
scrollV.addView(fondo)
hscrollV.addView(scrollV)
layaout1.addView(hscrollV) //layaout1 is a RelativeLayout
More code would be nice since I cannot see where you are declaring the position but if you are hard-coding the coordinates, I would suggest instead of using the same variables for width and height and just putting them in the coordinates /2 so if your variables are width and height, it should be kind of like this depending on what you are using:
.setPosition(width/2, height/2);
If this isn't useful then please provide more info or more code to see where your mistake is :)
That's not how Canvases work in Android. You don't declare how big you want it to be and it magically scales to the screen. If you're in the View's onDraw function, the Canvas passed in is the size of the View, in physical pixels. You need to scale your drawing to it. If you're drawing to an offscreen bitmap first and then blitting that to the screen, its your job to scale the bitmap via a matrix when you blit it. Also, in Android the coordinate system is 0,0 as the upper left hand corner. Unless it greatly eases your drawing I suggest you not fight it.
However you could use a matrix transformation on the Canvas to change that. First you'd want to scale the matrix by 6000/view.getHeight() in the y and 6000/view.getWidth() in the x. Then you'd want to translate it by -3000 in the x and -3000 in the y. That should scale it to the view and move origin to center.

Pixelated texture filtering distorted

I've created a isometric tile based game in Libgdx. The textures I'm using are 64x64 and packed using TexturePacker into a TextureAtlas. They are then drawn onto the screen. However, while moving around the pixelated edges of the 64x64 texture flicker and they are distorted, which can be seen in the images below. I have used all filters available in texturepacker, below you can see the results of the Linear and Nearest filters. Apart from flickering, the linear filter adds a black outline to the textures. I would be fine with this if it wasn't for the flickering when the camera moves around.
How the tile should appear:
Linear filtering (You can clearly see the black lines distorting):
Nearest filtering (Harder to see, but the pixelated lines are not straight):
The easiest place to spot it is on the top and bottom of the brown cube. The distortion happens on different places depending on camera movement (this causes flickering).
Anyone know what causes this, or has a possible solution? I'm not sure if any code snippets are needed.
It is also worth mentioning that the camera is set to windowHeight/ppm (ppm = 64) and windowWidth/ppm, then the textures are drawn onto a batch that has its projection matrix set to camera.combined.
Edit: Somehow it's better when reducing the window height from 800 to 710 (nearest):
Turn on the premultiplyAlpha option in TexturePacker and set setBlendFunction.(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA) on the SpriteBatch. This should get rid of the flickering black fringing. Basically, when using linear filtering, when the sprite's edges don't exactly line up with the pixels on the screen, the color of the pixel is linearly sampled from an image pixel on the edge of your sprite and an image pixel in the invisible black space (RGBA = 0000) next to it, so the edges can appear darker and more transparent than intended. Pre-multiplying the alpha cures this problem by changing the order of operations of the interpolation. Detailed explanation here and here.
Also, use filterMin of MipMapLinearNearest or MipMapLinearLinear to make sure you aren't getting minifying artifacts. (The first one performs better and the second one looks better at certain zoom levels and should be used if your camera zooms in and out.)
And finally, filterMax should be Linear.
Nearest filtering will always produce uneven artifacts if the sprites are not drawn at exactly 1X, 2X, 3X, etc. of their original size, because there will be certain rows and columns of the screen where a pixel in the image is drawn twice.

Get portion of an image using rotated Shape

From the above image if I want a portion behind the RED Rectangle I can easily get it,
but the issue I cannot get the portion behind the Yellow Rectangle because it is rotated.
So how can I get a portion of an image from a rotated shape on it?
For example my goal is to get a portion of an Image where the rectangle is located on the image. if someone rotates this rectangle by an x degree [in whatever direction] then it is getting difficult to extract the exact portion of an image after applying rotation.
Any suggestions?
Here a more lengthy description of a possible approach. I do not know the Java2D drawing API very well but if I remember correctly it has the capabilities to do what is required.
First you have to figure out the translation and rotation of the subregion you want compared to an equally size rectangle located straight in the upper left corner in the image. Then invert this transformation.
Make a graphics context which is backed by a bitmap in memory. This one should have the size of the subimage you want. Setup the inverse transformation you calculated earlier on the context and draw your image at position 0,0. As Java2D will take the transformation into account you should now get the sub image you want in the memory bitmap.
Mihir, I think you might be getting distracted by the rotation/AffineTransform aspects of this challenge and it is leading you down the wrong road. Also keep in mind that I don't totally know what you mean by "get" here -- do you want to save out the highlighted region to an image? Do you want to render it as a watermark on another image? etc... I'll just try and answer in the general case to get you down the right track.
What you want is the content from the image defined by the polygon in yellow in your image above; ignoring the fact that it looks like a rotated rectangle.
It is late and I am missing a step in here, but I think this will get you 90% of the way there and clarify the last piece (Graphics2D.setClip) that you need.
Create a java.awt.Polygon that defines the region around the area you want.
Use getBounds() or getBounds2D() to get the width/height of the bounding box required to hold this Polygon when rendered out into a rectangle. (e.g. boundingBox)
Create a new BufferedImage with these width/height values.
Get the Graphics2D from the new BufferedImage (e.g. newG2)
newG2.drawImage(originalImage, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height)
NOTE This is where my memory is failing me; at some point you need to set the clip on newG2 (newG2.setClip(someShape)) so when the bounding box is rendered into it, you don't get the full bounding box of graphics rendered in, but instead some subset as defined by the yellow outline.
One easy way to do this is to create two Polygon's:
poly1 = a java.awt.Polygon that defines the yellow selection in the ORIGINAL image.
poly2 = a java.awt.Polygon that defines the exact same shape of Polygon, but shifted to a 0,0 origin point.
poly1 is used to get the bounding box to copy out the full bounding box that encompasses the content selected in yellow (and extra content around it)
poly2 is used to set the clip on the target Graphics2D (newG2) so when the bounding box is rendered into it, we clip back out everything outside of that Yellow shape so we just get the content in Yellow. You'll likely want to use an ARGB image type and set the background of the target image as transparent otherwise you'll get a black fill color.
I think this is the right direction for the clips; I was up to my eyeballs in Java2D for years and years but have been out of it for a while and forget if this will give you exactly what you want or not; you might need to tweak it around, but these are all the tools you need.

Java - Keeping scaling relative to image's rotation

For an assignment, I need to make a "doll" in Java where you can move it around and rotate the arms and legs to make funny/cool poses. In addition, the legs should be able to stretch (but not get wider, this is important).
The way I wanted to handle the leg stretching was invert the rotation done to the leg to get it back in the neutral straight position, scale it in the y direction, and then re-perform the rotation. However, it appears the scaling is always going to be in the y direction, so once it's rotated, the leg will become wider. It will only look as it should if it's brought back straight and standing.
The code I have right now looks something like this:
leg.transform(AffineTransform.getRotateInstance(legAngle,pivot.getX(),pivot.getY()).createInverse());
leg.transform(AffineTransform.getScaleInstance(1,scaleFactor);
leg.transform(AffineTransform.getRotateInstance(legAngle,pivot.getX(),pivot.getY()));
How can I make sure the scaling stays relative to the image after rotation?
There are a couple of ways that come to mind. The first (simplest, but slowest) method is to render the stretched leg image to an image, then rotate and render that image. Another way is to use Math.cos and Math.sin to apply the proper scaling in each dimension for the desired effect in the image.

Categories

Resources