android - set starting point to top left on libgdx - android
i want to use libgdx as a solution to scaling of apps based on screens aspect ratio.
i've found this link , and i find it really useful:
http://blog.acamara.es/2012/02/05/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/
i'm quite rusty with opengl (haven't written for it in years) and i wish to use the example on this link so that it would be easy to put images and shapes .
sadly , the starting point is in the middle . i want to use it like on many other platforms - top left corner should be (0,0) , and bottom right corner should be (targetWidth-1,targetHeight-1) ,
from what i remember, i need to move(translate) and rotate the camera in order to achieve it , but i'm not sure .
here's my modified code of the link's example for the onCreate method:
#Override
public void create()
{
camera=new OrthographicCamera(VIRTUAL_WIDTH,VIRTUAL_HEIGHT);
// camera.translate(VIRTUAL_WIDTH/2,VIRTUAL_HEIGHT/2,0);
// camera.rotate(90,0,0,1);
camera.update();
//
font=new BitmapFont(Gdx.files.internal("data/fonts.fnt"),false);
font.setColor(Color.RED);
//
screenQuad=new Mesh(true,4,4,new VertexAttribute(Usage.Position,3,"attr_position"),new VertexAttribute(Usage.ColorPacked,4,"attr_color"));
Point bottomLeft=new Point(0,0);
Point topRight=new Point(VIRTUAL_WIDTH,VIRTUAL_HEIGHT);
screenQuad.setVertices(new float[] {//
bottomLeft.x,bottomLeft.y,0f,Color.toFloatBits(255,0,0,255),//
topRight.x,bottomLeft.y,0f,Color.toFloatBits(255,255,0,255),//
bottomLeft.x,topRight.y,0f,Color.toFloatBits(0,255,0,255),//
topRight.x,topRight.y,0f,Color.toFloatBits(0,0,255,255)});
screenQuad.setIndices(new short[] {0,1,2,3});
//
bottomLeft=new Point(VIRTUAL_WIDTH/2-50,VIRTUAL_HEIGHT/2-50);
topRight=new Point(VIRTUAL_WIDTH/2+50,VIRTUAL_HEIGHT/2+50);
quad=new Mesh(true,4,4,new VertexAttribute(Usage.Position,3,"attr_position"),new VertexAttribute(Usage.ColorPacked,4,"attr_color"));
quad.setVertices(new float[] {//
bottomLeft.x,bottomLeft.y,0f,Color.toFloatBits(255,0,0,255),//
topRight.x,bottomLeft.y,0f,Color.toFloatBits(255,255,0,255),//
bottomLeft.x,topRight.y,0f,Color.toFloatBits(0,255,0,255),//
topRight.x,topRight.y,0f,Color.toFloatBits(0,0,255,255)});
quad.setIndices(new short[] {0,1,2,3});
//
texture=new Texture(Gdx.files.internal(IMAGE_FILE));
spriteBatch=new SpriteBatch();
spriteBatch.getProjectionMatrix().setToOrtho2D(0,0,VIRTUAL_WIDTH,VIRTUAL_HEIGHT);
}
so far , i've succeeded to use this code in order to use scaled coordinates , and still keep aspect ratio (which is great) , but i didn't succeed in moving the starting point (0,0) to the top left corner .
please help me .
EDIT: ok , after some testing , i've found out that the reason for it not working is that i use the spriteBatch . i think it ignores the camera . this code occurs in the render part. no matter what i do to the camera , it will still show the same results.
#Override
public void render()
{
if(Gdx.input.isKeyPressed(Keys.ESCAPE)||Gdx.input.justTouched())
Gdx.app.exit();
// update camera
// camera.update();
// camera.apply(Gdx.gl10);
// set viewport
Gdx.gl.glViewport((int)viewport.x,(int)viewport.y,(int)viewport.width,(int)viewport.height);
// clear previous frame
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
//
final String msg="test";
final TextBounds textBounds=font.getBounds(msg);
spriteBatch.begin();
screenQuad.render(GL10.GL_TRIANGLE_STRIP,0,4);
quad.render(GL10.GL_TRIANGLE_STRIP,0,4);
Gdx.graphics.getGL10().glEnable(GL10.GL_TEXTURE_2D);
spriteBatch.draw(texture,0,0,texture.getWidth(),texture.getHeight(),0,0,texture.getWidth(),texture.getHeight(),false,false);
spriteBatch.draw(texture,0,VIRTUAL_HEIGHT-texture.getHeight(),texture.getWidth(),texture.getHeight(),0,0,texture.getWidth(),texture.getHeight(),false,false);
font.draw(spriteBatch,msg,VIRTUAL_WIDTH-textBounds.width,VIRTUAL_HEIGHT);
spriteBatch.end();
}
These lines:
camera.translate(VIRTUAL_WIDTH/2,VIRTUAL_HEIGHT/2,0);
camera.rotate(90,0,0,1);
should move the camera such that it does what you want. However, my code has an additional:
camera.update()
call after it calls translate, and it looks like you're missing that. The doc for Camera.update says:
update
public abstract void update()
Recalculates the projection and view matrix of this camera and the Frustum planes. Use this after you've manipulated any of the attributes of the camera.
Related
LibGdx: calculating view matrix from projection
I'm currently working on Google VR Sdk integration with LibGDX. As a starting point, I used this one: https://github.com/yangweigbh/Libgdx-CardBoard-Extension However I was not really satisfied with it as it does not follow the the general project structure of LibGDX projects, so I started to refactor and move things around. So far so good, I have a demo running showing a rotating cube. Now I wanted to add a Skybox, starting from here: LibGDX 0.9.9 - Apply cubemap in environment The image is drawn, but does not move with head rotation like the other objects, so I looked deeper into the CardboardCamera class, especially the part about setting the projection matrix. The Skybox class from above gets a quaternion from the camera's view matrix. However this matrix is not set within the CardboardCamera class; instead it sets the projection matrix directly leaving the view matrix unchanged. So my question now is. If I have the projection matrix, how can I either get the correct quaterion for it to be used for the Skybox or how can I calculate the view matrix so that its getRotation() method returns the correct values ? If both does not make sense, where could I get the correct getRotation() data from ? Relevant code of the CardboardCamera class: public void setEyeProjection(Matrix4 projection) { this.projection.set(projection); } final Matrix4 tmpMatrix = new Matrix4(); final Vector3 tmpVec = new Vector3(); #Override public void update(boolean updateFrustum) { // below line does not make much sense as position, direction and up are never set... view.setToLookAt(position, tmpVec.set(position).add(direction), up); tmpMatrix.set(eyeViewAdjustMatrix); Matrix4.mul(tmpMatrix.val, view.val); combined.set(projection); Matrix4.mul(combined.val, tmpMatrix.val); if (updateFrustum) { invProjectionView.set(combined); Matrix4.inv(invProjectionView.val); frustum.update(invProjectionView); } }
Panning the view of a gameObject instead of the camera in Unity3d?
I'm having a hard time to pan a view of a gameObject in Unity3d. I'm new to scripting and I'm trying to develop an AR (Augmented Reality) application for Android. I need to have a gameObject (e.g. a model of a floor), from the normal top down view, rendered to a "pseudo" iso view, inclined to 45 degrees. As the gameObject is inclined, I need to have a panning function on its view, utilizing four (4) buttons (for left, right, forward(or up), backward(or down)). The problem is that, I cannot use any of the known panning script snippets around the forum, as the AR camera has to be static in the scene. Need to mention that, I need the panning function to be active only at the isometric view, (which I already compute with another script), not on top down view. So there must be no problem with the inclination of the axes of the gameObject, right? Following, are two mockup images of the states, the gameObject (model floor) is rendered and the script code (from Unity reference), that I'm currently using, which is not very much functional for my needs. Here is the code snippet, for left movement of the gameObject. I use the same with a change in -, +speed values, for the other movements, but I get it only move up, down, not forth, backwards: #pragma strict // The target gameObject. var target: Transform; // Speed in units per sec. var speedLeft: float = -10; private static var isPanLeft = false; function FixedUpdate() { if(isPanLeft == true) { // The step size is equal to speed times frame time. var step = speedLeft * Time.deltaTime; // Move model position a step closer to the target. transform.position = Vector3.MoveTowards(transform.position, target.position, step); } } static function doPanLeft() { isPanLeft = !isPanLeft; } It would be great, if someone be kind enough to take a look at this post, and make a suggestion on how this functionality can be coded the easiest way, as I'm a newbie? Furthermore, if a sample code or a tutorial can be provided, it will be appreciated, as I can learn from this, a lot. Thank you all in advance for your time and answers.
If i understand correctly you have a camera with some fixed rotation and position and you have a object you want to move up/down/left/right from the cameras perspective To rotated an object to a set of angles you simply do transform.rotation = Quaternion.Euler(45, 45, 45); Then to move it you use the cameras up/right/forward in worldspace like this to move it up and left transform.position += camera.transform.up; transform.position -= camera.transform.right; If you only have one camera in your scene you can access its transform by Camera.main.transform An example of how to move it when someone presses the left arrow if(Input.GetKeyDown(KeyCode.LeftArrow)) { transform.position -= camera.transform.right; }
LibGDX. Android. Black background on transparent DecalSprites
In my App I use several DecalSprites as a part of my scene. They all have transparency (PNG-textures). When I have them overlapping, some of those show black background instead of transparency. Those DecalSprites have different Z-coordinates. So they should look like one behind another. Please note also the line on the border of a texture. This is also something that I'm struggling to remove. Update 1: I use PerspectiveCamera in the scene. But all the decals are positioned to face the camera as in 2d mode. So this "black" background appears only in certain cases e.g. when camera goes right (and all those decals appear in the left of the scene). Also I use the CameraGroupStrategy
Solved! The reason was that CameraGroupStrategy when ordering Decals (from farthest to closest to camera) takes the "combined" vector distance between camera and the Decal. When my camera panned to left or to right the distance to the Z-farthest Decal became LESS than the Z-closer Decal. This produced the artifact. Fix: GroupStrategy strategy = new CameraGroupStrategy(cam , new ZStrategyComparator()); And the Comparator: private class ZStrategyComparator implements Comparator<Decal> { #Override public int compare (Decal o1, Decal o2) { float dist1 = cam.position.dst(0, 0, o1.getPosition().z); float dist2 = cam.position.dst(0, 0, o2.getPosition().z); return (int)Math.signum(dist2 - dist1); } } Thanks to all guys who tried to help. Especially Xoppa. He sent me into the right direction in libGDX IRC.
Android AndEngine two circles collision perfectly
Android AndEngine two circles collision perfectly. I have two circle and a collision method for them, I want when they touch each other the collision happens, currently when they near each other the collision happens. I think that it is because of the transparent free space in the .png file of each circle. In the picture you can see that now they collide from a distance, I want when both touch each other. My collision method: if (circle1.collidesWith(circle)){ Score += 1; }
I am almost sure you are right that transparent places in png causes it. You probably creating BoxBody. In your case you should use circle body like this: Body circleBody = PhysicsFactory.createCircleBody(pWorld, pSprite, BodyType.StaticBody, FixtureDef); If it doesn't help there is method overload where you can provide position and size of the body. I can recommend you using DebugRender which you only have to attach to scene: new DebugRenderer(physicsWorld, vbom) When u use this you will see how helpful it can be:) Just remember that it may slowdown your phone when you have a lot of bodies on the scene. PS. You didn't give us a lot of information but you should use contactListener to check colisions. There are plenty of tutorials in the internet for it PS2. If you don't use Box2D extension - do it. This is great feature of AndEngine and it's pointless to implement that for yourself. It will be hard to detect circle shape collision of 2 objects without Box2D.
If you are not in Box2d , You must use Pixel-Perfect Collision library. Well default AndEngine Library, Does not support pixel perfect collision. To get this support, you need to import this library in eclipse and add this to your project uses library. Here, I Demonstrate how to use this library. When you define Texture and Atlas for your sprite write as below. private BitmapTextureAtlas lifeAtlas; public PixelPerfectTiledTextureRegion life_Texture; PixelPerfectTextureRegionFactory.setAssetBasePath("gfx/game/"); lifeAtlas = new BitmapTextureAtlas(textureManager, 1280, 128, TextureOptions.BILINEAR); life_Texture = PixelPerfectTextureRegionFactory.createTiledFromAsset( lifeAtlas, activity, "heart_tiled.png", 0, 0, 10, 1, 0); lifeAtlas.load(); For your custom sprite class, public class Plane extends PixelPerfectAnimatedSprite { public Plane(float pX, float pY, PixelPerfectTiledTextureRegion pTiledTextureRegion, VertexBufferObjectManager pVertexBufferObjectManager) { super(pX, pY, pTiledTextureRegion, pVertexBufferObjectManager); setColor(Color.GREEN); } } You also need some adjustment with your AndEngine library to use it. Follow this thread to go.
First Person Camera rotation in 3D
I have written a first person camera class for android. The class is really simple , the camera object has its three axes X,y and Z and there are functions to create the ModelView matrix ( i.e. calculateModelViewMatrix() ), rotate the camera along its X and Y axis and Translate the camera along its Z-axis. I think that my ModelViewMatrix calulation is correct and i can also translate the camera along the Z-axis. Rotation along x-axis seems to work but along Y-axis it gives strange results. Also another problem with the rotation seems to be that instead of the camera being rotated, my 3d model starts to rotate instead along its axis. I have written another implementation based on the look at point and using the openGL ES's GLU.gluLookAt( ) function to obtain the ModelView matrix but that too seems to suffer from the exactly the same problems. EDIT First of all thanks for your reply. I have actually made a second implementation of the Camera class, this time using the rotation functions provided in android.opengl.Matrix class as you said. I have provided the code below, which is much simpler. To my surprise, the results are "Exactly" the same. This means that my rotation functions and Android's rotation functions are producing the same results. I did a simple test and looked at my data. I just rotated the LookAt point 1-dgree at a time around Y-axis and looked at the coordinates. It seems that my LookAt point is lagging behind the exact rotation angle e.g. at 20-deg it has only roatated 10 to 12 degree. And after 45-degrees it starts reversing back
There is a class android.opengl.Matrix which is a collection of static methods which do everything you need on a float[16] you pass in. I highly recommend you use those functions instead of rolling your own. You'd probably want either setLookAtM with the lookat point calculated from your camera angles (using sin, cos as you are doing in your code - I assume you know how to do this.) -- edit in response to new answer -- (you should probably have edited your original question, by the way - your answer as another question confused me for a bit) Ok, so here's one way of doing it. This is uncompiled and untested. I decided to build the matrix manually instead; perhaps that'll give a bit more information about what's going on... class TomCamera { // These are our inputs - eye position, and the orientation of the camera. public float mEyeX, mEyeY, mEyeZ; // position public float mYaw, mPitch, mRoll; // euler angles. // this is the outputted matrix to pass to OpenGL. public float mCameraMatrix[] = new float [16]; // convert inputs to outputs. public void createMatrix() { // create a camera matrix (YXZ order is pretty standard) // you may want to negate some of these constant 1s to match expectations. Matrix.setRotateM(mCameraMatrix, 0, mYaw, 0, 1, 0); Matrix.rotateM(mCameraMatrix, 0, mPitch, 1, 0, 0); Matrix.rotateM(mCameraMatrix, 0, mRoll, 0, 0, 1); Matrix.translateM(mCameraMatrix, 0, -mEyeX, -mEyeY, -mEyeZ); } }