I am using the following texture
It is being displayed only partially and it gets repeated when I used the following code:
float scale = (float)( (float)Gdx.graphics.getWidth() / (float)(tex.getWidth()));
w = Gdx.graphics.getWidth();
h = scale * tex.getHeight();
float x = 0.0f;
float y = Gdx.graphics.getWidth() - h * splashTimer;
Sprite s = new Sprite(tex);
//s.setOriginCenter();
// s.setScale(scale);
//s.setOriginCenter();
// s.setOriginCenter();
//s.setSize(s.getWidth() * scale, s.getHeight() * scale);
//s.setOriginCenter();
s.setScale(0.1f);//1.0f + (1.0f - scale));
s.setOrigin(0, 0);
s.setPosition(x, y);
batch.begin();
batch.draw(s,0,0,Gdx.graphics.getWidth(), scale * s.getHeight());
// s.draw(batch);
batch.end();
It gets chopped and repeated in Android and looks like this:
Orange isn't even drawn. Why is this happening?
Apparently this happened because I was using mipmaps. I disabled the use of mipmaps and now it works.
Related
I am trying to move an ImageView after scaling it down, but for some reason, the position does not match the destinated position. First I calculate the scaling factors and the difference between the new and old positions. Then I started the animation, but the ImageView moves to far to the left and to the bottom and I have no clue why.
float scaleX = (destWidth * 1.0f) / imageView.getMeasuredWidth();
float scaleY = (destHeight * 1.0f) / imageView.getMeasuredHeight();
float moveX = -1 * (imageView.getLeft() - destX); // move image to the left
float moveY = destY - imageView.getTop(); // move image to the bottom
oa = ObjectAnimator.ofPropertyValuesHolder(imageView
, PropertyValuesHolder.ofFloat("scaleX", scaleX)
, PropertyValuesHolder.ofFloat("scaleY", scaleY)
, PropertyValuesHolder.ofFloat("translationX", moveX)
, PropertyValuesHolder.ofFloat("translationY", moveY));
oa.setDuration(3000);
oa.setRepeatMode(ValueAnimator.REVERSE);
oa.setRepeatCount(ValueAnimator.INFINITE);
oa.start();
I figured it out myself, but I will leave the corrected code below for others with similar problems.
Basically, the ImageView is first moved according to the translation and then scaled down. The scaling moves the top, bottom, left and right to the center and therefore the ImageView is offset.
To fix this half of the difference between the old ImageView size and the new ImageView size needs to be subtracted from the previous moveX/moveY.
float moveX = -1 * (imageView.getLeft() - destX)
- ((imageView.getMeasuredWidth() - (imageView.getMeasuredWidth() * scaleX)) / 2);
// move image to the bottom
float moveY = destY - imageView.getTop()
- ((imageView.getMeasuredHeight() - (imageView.getMeasuredHeight() * scaleY)) / 2);
Finally, the finished code should look like this.
float scaleX = (destWidth * 1.0f) / imageView.getMeasuredWidth();
float scaleY = (destHeight * 1.0f) / imageView.getMeasuredHeight();
// move image to the left
float moveX = -1 * (imageView.getLeft() - destX)
- ((imageView.getMeasuredWidth() - (imageView.getMeasuredWidth() * scaleX)) / 2);
// move image to the bottom
float moveY = destY - imageView.getTop()
- ((imageView.getMeasuredHeight() - (imageView.getMeasuredHeight() * scaleY)) / 2);
oa = ObjectAnimator.ofPropertyValuesHolder(imageView
, PropertyValuesHolder.ofFloat("scaleX", scaleX)
, PropertyValuesHolder.ofFloat("scaleY", scaleY)
, PropertyValuesHolder.ofFloat("translationX", moveX)
, PropertyValuesHolder.ofFloat("translationY", moveY));
oa.setDuration(3000);
oa.setRepeatMode(ValueAnimator.REVERSE);
oa.setRepeatCount(ValueAnimator.INFINITE);
oa.start();
The task is to crop video by given points(like rectangle) and display the cropped video.
The code works with cropping the first halh of video(0, 0, videoWidth/2, videoHeight). But when i tryed to display the second one(videoWidth/2, 0, videoWidth, videoHeight), that is what was displayed.
The video is displayed on TextureView inside FrameLayout.
The part, that doesn't work:
private void updateTextureViewSize(int ax, int ay, int bx, int by) {
float scaleX;
float scaleY;
//proportions between screen and frame dimensions
scaleX = mVideoWidth / mDisplayWidth;
scaleY = mVideoHeight / mDisplayHeight;
float scaleRegionW = mVideoWidth / Math.abs(ax - bx);
float scaleRegionH = mVideoHeight / Math.abs(ay - by);
float scaleRegion = scaleRegionW < scaleRegionH ? scaleRegionW : scaleRegionH;
Matrix matrix = new Matrix();
if (scaleX > scaleY) {
matrix.setScale(scaleRegion / scaleY, scaleRegion);
matrix.postTranslate(-ax * (int) scaleRegion / scaleY, -ay * scaleRegion / scaleY);
} else {
matrix.setScale(scaleRegion, scaleRegion / scaleX);
matrix.postTranslate(-ax * scaleRegion / scaleX, -ay * scaleRegion / scaleX);
}
mTextureView.setTransform(matrix);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams((int) mDisplayWidth, (int) mDisplayHeight));
}
The answer was found by Dmitry Yacenko.
The full code.
An easy way to crop video by given points (ax, ay, bx, xy) is:
float scaleX = mDisplayWidth / mVideoWidth, scaleY = mDisplayHeight / mVideoHeight;
//proportions between screen and frame dimensions
float scale = mDisplayHeight / Math.abs(by - ay);
Matrix matrix = new Matrix();
matrix.reset();
matrix.setScale(scale / scaleX, scale / scaleY);
//scaling video
matrix.postTranslate(-scale * ax, -scale * ay);
//move video, so the needed part of it will be displayed properly
mTextureView.setLayoutParams(new FrameLayout.LayoutParams((int) mDisplayWidth, (int) mDisplayHeight));
mTextureView.setTransform(matrix);
//updating the Texture view
I currently have a sprite following a path...all is working well from a steering perspective, however I am trying to make it so the center of the sprite tracks along the path, rather than the corner (0,0) tracing along the path. Essentially, I would like the center of the fish to follow the line.
Below is an image of what I have implemented, and what I would like to achieve.
The core implementation of this mechanic lies within my update() method; as follows;
private void update(float deltaTime) {
float angle = (float) Math.atan2(path.get(waypoint).y - getY(), path.get(waypoint).x - getX());
velocity.set((float) Math.cos(angle) * speed, (float) Math.sin(angle) * speed);
velocity_normal = new Vector2(-velocity.y, velocity.x).nor();
setPosition(
getX() + (velocity.x * deltaTime),
getY() + (velocity.y * deltaTime)
);
setRotation(angle * MathUtils.radiansToDegrees);
if(isWayPointReached()){
setPosition(path.get(waypoint).x, path.get(waypoint).y);
if(waypoint + 1 >= path.size){
waypoint = 0;
} else {
waypoint++;
}
}
}
In particular the setPosition call. My initial thoughts were to calculate the normal vector to the velocity vector, normalize, and multiply the x and y components respectively by the fish height... to my mind this would offset the fish by its height (150px). The code attempted is as follows;
velocity_normal = new Vector2(-velocity.y, velocity.x).nor();
setPosition(
getX() + (velocity.x * deltaTime) + velocity_normal.x * getHeight() * deltaTime,
getY() + (velocity.y * deltaTime) + velocity_normal.y * getHeight() * deltaTime
);
The results in some odd behavior, the fish gets progressively further from the line, it seems the vector is getting compounded and added each frame.
I have also tried to update the normal vector once each way-point has been reached, however this does not work either.
I think the above logic is correct, however have I made a fundamental error in my vector maths?
Your assistance would be greatly appreciated.
EDIT:
Added to constructor:
setPosition(
path.get(waypoint).x - 0.5f * getWidth() ,
path.get(waypoint).y - 0.5f * getHeight()
);
Amended update() method;
private void update(float deltaTime) {
float angle = (float) Math.atan2(path.get(waypoint).y - getY(), path.get(waypoint).x - getX());
velocity.set((float) Math.cos(angle) * speed, (float) Math.sin(angle) * speed);
Vector2 velocity_normal = new Vector2();
velocity_normal.set(velocity).nor().scl( speed * deltaTime ); // multiply the speed to scale the unit vector up
translate( velocity_normal.x, velocity_normal.y );
setRotation(angle * MathUtils.radiansToDegrees);
if(isWayPointReached()){
setPosition(path.get(waypoint).x, path.get(waypoint).y);
if(waypoint + 1 >= path.size){
waypoint = 0;
} else {
waypoint++;
}
}
}
Note the omission of the setPosition call, and the replacement with;
Vector2 velocity_normal = new Vector2();
velocity_normal.set(velocity).nor().scl( speed * deltaTime );
translate( velocity_normal.x, velocity_normal.y );
How would I influence the pointA / pointB as mentioned below?
Thanks.
The Sprite position is from the left bottom corner and the origin (where the sprite rotates around) is already set to the center of the sprite. So only the local offset is wrong. You have to substract half the size from the position and then the sprite can move relatively from that offset.
Where you set the sprite:
setPosition(
path.get(waypoint).x - 0.5f * getWidth(),
path.get(waypoint).y - 0.5f * getHeight()
);
In the update method. Because you are adding the velocity every frame you can translate the sprite.
void update(float deltaTime){
// directional global vector
Vector2 velocity = tmp.set(path.get(waypoint)).sub(path.get(waypoint - 1)).nor().scl(speed * deltaTime);
// reference angle is relative to the right vector(1, 0)
float angle = velocity.angle();
setRotation(angle);
translate(velocity.x, velocity.y);
if (isWayPointReached()){
setPosition(
path.get(waypoint).x - 0.5f * getWidth(),
path.get(waypoint).y - 0.5f * getHeight()
);
if(waypoint + 1 >= path.size){
waypoint = 1;
} else {
waypoint++;
}
}
}
There is setCenter() method in Sprite class:
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/Sprite.html#setCenter-float-float-
Try setting center like that instead of calculating it additionally.
I am trying to draw points on face based on land marks i am using google vision api to detect face and landmarks, My question is how i calculate the value of scale variable
for (Landmark landmark : face.getLandmarks()) {
int cx = (int) (landmark.getPosition().x * scale);
int cy = (int) (landmark.getPosition().y * scale);
canvas.drawCircle(cx, cy, 10, paint);
}
I find this solution on this website but this solution not work for me because i trying to use live camera preview (e.g. real time) not try to detect from image
double scale = Math.min( viewWidth / imageWidth, viewHeight / imageHeight );
I am creating a little game in Java and I have an image which gets rotated.
As you can see in the two images below, there is a giant ship which slowly rotates in the game, but when it gets to a certain point it gets cut off (due to its own little BufferedImage).
Heres my rendering code:
public void drawImageRotated(BufferedImage img, double x, double y, double scale, double angle) {
x -= xScroll;
y -= yScroll;
BufferedImage image = new BufferedImage((int)(img.getWidth() * 1.5D), (int)(img.getHeight() * 1.5D), 2);
Graphics2D g = (Graphics2D)image.getGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.rotate(Math.toRadians(angle), image.getWidth() / 2, image.getHeight() / 2);
g.drawImage(img, image.getWidth() / 2 - img.getWidth() / 2, image.getHeight() / 2 - image.getHeight() / 2, null);
g2d.drawImage(image, (int)(x-image.getWidth()*scale/2), (int)(y-image.getHeight()*scale/2), (int)(image.getWidth()*scale), (int)(image.getHeight()*scale), null);
g.dispose();
}
Back to the matter at hand, how can i work out the maximum x and y size of an image during rotation so I can compensate with my buffered images size?
If you have a basically rectangular image which is rotated around its center, the maximum width and height during rotation will be when a diagonal of the image rectangle is horizontal or vertical. This diagonal distance could be computed with the Pythagorean Theorem and used for the width and height of the BufferedImage.
int size = (int) Math.sqrt((img.getWidth() * img.getWidth()) + (img.getHeight() * img.getHeight()));
BufferedImage image = new BufferedImage(size, size, 2);
// The rest of your code as before
how can i work out the maximum x and y size of an image during rotation so I can compensate with my buffered images size?
double sin = Math.abs(Math.sin(angle));
double cos = Math.abs(Math.cos(angle));
int w = image.getWidth();
int h = image.getHeight();
int neww = (int)Math.floor(w*cos+h*sin);
int newh = (int)Math.floor(h*cos+w*sin);
The above code was taken from this example: Java(SWING) working with Rotation
An alternative is to rotate the actual Graphics object, draw the image, and restore the rotation:
AffineTransform old = g2d.getTransform();
g2d.rotate(Math.toRadians(angle), x + image.getWidth() / 2, y + image.getWidth() / 2);
g2d.drawImage(image, x, y, null);
g2d.setTransform(old);
Let's consider width being the width of the original image, height its original height and angle the rotation angle value in radians.
According to my calculations, the size of the rotated image is something like this:
rotatedWidth = Math.cos(angle) * width + Math.sin(angle) * height;
rotatedHeight = Math.sin(angle) * width + Math.cos(angle) * height;
You may also need to take a look at this thread as well, as it may help.