OpenGl\JOML: Preventing unwanted translation when scaling a matrix - java

I am attempting to put 3D objects on the HUD using LWJGL 3 and JOML. I just have a small problem where when I scale the object, it moves. I want to prevent that from happening.
In this image my object is set to a position of (0,0) (Z is always set to 0), and a scale of 100 (All scales are divided by 100 so the actual value of the scale is 1 when applied to the matrix. The code that does this can be seen below).
https://i.imgur.com/f8wH7cm.png
Then when I change the scale to 50 (0.5 when applied to the matrix) this is what is shown:
https://i.imgur.com/SXWM8nE.png
I want the object to still be at the top left corner of the screen.
Here is my code that comes up with the true scale and position (The screen size is 1080 x 720)
public Vector3f getTruePos(){
return new Vector3f(((position.x/1080) - 0.5), ((position.y/720) + (0.5)), 0);
}
public float getTrueScale(){
return scale/100;
}
Here is my code that does the rendering of the object.
public void renderHUD(List<UIObject> objects){
hudShaderProgram.bind();
for(UIObject object : objects){
Mesh mesh = object.getMesh();
hudShaderProgram.setUniform("projection", transformation.getOrthoProjectionMatrix());
hudShaderProgram.setUniform("model", transformation.buildModelViewMatrixUI(object));
mesh.render();
}
hudShaderProgram.unbind();
}
Then here is the code that handles the transformations of the object:
public Matrix4f buildModelViewMatrixUI(UIObject gameItem) {
Quaternionf rotation = gameItem.getRotation();
Matrix4f modelMatrix = new Matrix4f();
modelMatrix.translationRotateScale(gameItem.getTruePos().x, gameItem.getTruePos().y, 0, rotation.x, rotation.y, rotation.z, rotation.w, gameItem.getTrueScale(),
gameItem.getTrueScale(), gameItem.getTrueScale());
return modelMatrix;
}
Then getOrthoProjectionMatrix() returns the value that is set by this:
transformation.updateProjectionMatrix(FOV, window.getWidth(), window.getHeight(), Z_NEAR, Z_FAR);
public Matrix4f updateOrthoProjectionMatrix(float left, float right, float bottom, float top, float zNear, float zFar) {
orthoProjMatrix.identity();
orthoProjMatrix.setOrtho(left, right, bottom, top, zNear, zFar);
return orthoProjMatrix;
}
I am not sure what I need to do to achieve what I desire. Any help would be appreciated.
The full code for the snippets above can be found here:
The UIObject class
The Rendering Class
The Transformation class
If this is not enough information please let me know, I will be happy to supply more.

I managed to solve this issue. I only really needed to update my ortho projectin matrix.
public Matrix4f buildOrtho(float left, float right, float bottom, float top){
Matrix4f orthoProjMatrix = new Matrix4f();
orthoProjMatrix.setOrtho(left, right, bottom, top, -100, 1000);
return orthoProjMatrix;
}
I then just changed my render method to this:
public void renderHUD(Window window, List<UIObject> objects){
hudShaderProgram.bind();
Matrix4f orthoProjection = transformation.buildOrtho(0, window.getWidth(), window.getHeight(), 0);
for(UIObject object : objects){
Mesh mesh = object.getMesh();
hudShaderProgram.setUniform("ortho", orthoProjection);
hudShaderProgram.setUniform("model", transformation.buildModelViewMatrixUI(object));
mesh.render();
}
hudShaderProgram.unbind();
}
Also since I am now using the correct ortho projection I no longer need the getTrueScale() and getTruePositon() methods.

Related

How to prevent texture bleeding in a tilemap in LibGDX

I know there are quite some questions (and answers) on this topic, but they all have different solutions, and none of them seems to be working in my case.
I'm developing a small test project with libGDX, in which I tried to add a simple tilemap. I created the tilemap using Tiled, which seems to be working quite good, except for the texture bleeding, that causes black lines (the background color) to appear between the tiles sometimes.
What I've tried so far:
I read several SO-questions, tutorials and forum posts, and tried almost all of the solutions, but I just don't seem to get this working. Most of the answers said that I would need a padding between the tiles, but this doesn't seem to fix it. I also tried loading the tilemap with different parameters (e.g. to use the Nearest filter when loading them) or rounding the camera's position to prevent rounding problems, but this did even make it worse.
My current setup:
You can find the whole project on GitHub. The branch is called 'tile_map_scaling'
At the moment I'm using a tileset that is made of this tile-picture:
It has two pixels of space between every tile, to use as padding and margin.
My Tiled tileset settings look like this:
I use two pixels of margin and spacing, to (try to) prevent the bleeding here.
Most of the time it is rendered just fine, but still sometimes there are these lines between the tiles like in this picture (sometimes they seem to appear only on a part of the map):
I'm currently loading the tile map into the asset manager without any parameters:
public void load() {
AssetManager manager = new AssetManager();
manager.setLoader(TiledMap.class, new TmxMapLoader(new InternalFileHandleResolver()));
manager.setErrorListener(this);
manager.load("map/map.tmx", TiledMap.class, new AssetLoaderParameters());
}
... and use it like this:
public class GameScreen {
public static final float WORLD_TO_SCREEN = 4.0f;
public static final float SCENE_WIDTH = 1280f;
public static final float SCENE_HEIGHT = 720f;
//...
private Viewport viewport;
private OrthographicCamera camera;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
public GameScreen() {
camera = new OrthographicCamera();
viewport = new FitViewport(SCENE_WIDTH, SCENE_HEIGHT, camera);
map = assetManager.get("map/map.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
}
#Override
public void render(float delta) {
//clear the screen (with a black screen)
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
moveCamera(delta);
renderer.setView(camera);
renderer.render();
//... draw the player, some debug graphics, a hud, ...
moveCameraToPlayer();
}
private void moveCamera(float delta) {
if (Gdx.input.isKeyPressed(Keys.LEFT)) {
camera.position.x -= CAMERA_SPEED * delta;
}
else if (Gdx.input.isKeyPressed(Keys.RIGHT)) {
camera.position.x += CAMERA_SPEED * delta;
}
// ...
//update the camera to re-calculate the matrices
camera.update();
}
private void moveCameraToPlayer() {
Vector2 dwarfPosition = dwarf.getPosition();
//movement in positive X and Y direction
float deltaX = camera.position.x - dwarfPosition.x;
float deltaY = camera.position.y - dwarfPosition.y;
float movementXPos = deltaX - MOVEMENT_RANGE_X;
float movementYPos = deltaY - MOVEMENT_RANGE_Y;
//movement in negative X and Y direction
deltaX = dwarfPosition.x - camera.position.x;
deltaY = dwarfPosition.y - camera.position.y;
float movementXNeg = deltaX - MOVEMENT_RANGE_X;
float movementYNeg = deltaY - MOVEMENT_RANGE_Y;
camera.position.x -= Math.max(movementXPos, 0);
camera.position.y -= Math.max(movementYPos, 0);
camera.position.x += Math.max(movementXNeg, 0);
camera.position.y += Math.max(movementYNeg, 0);
camera.update();
}
// ... some other methods ...
}
The question:
I am using padding on the tilemap and also tried different loading parameters and rounding the camera position, but still I have this texture bleeding problem in my tilemap.
What am I missing? Or what am I doing wrong?
Any help on this would be great.
You need to pad the edges of your tiles in you tilesheet.
It looks like you've tried to do this but the padding is transparent, it needs to be of the color of the pixel it is padding.
So if you have an image like this (where each letter is a pixel and the tile size is one):
AB
CB
then padding it should look something like this
A B
AAABBB
A B
C C
CCCCCC
C C
The pixel being padded must be padded with a pixel of the same color.
(I'll try try create a pull request with a fix for your git-repo as well.)
As a little addition to bornander's answer, I created some python scripts, that do all the work to generate a tileset texture, that has the correct edge padding (that bornander explained in his answer) from a texture, that has no padding yet.
Just in case anyone can make use of it, it can be found on GitHub:
https://github.com/tfassbender/libGdxImageTools
There is also a npm package that can extrude the tiles. It was built for the Phaser JS game library, but you could still use it. https://github.com/sporadic-labs/tile-extruder

How to make LibGDX Actions moveTo() animate from one point to another in a curved line?

I am working on a project in LibGDX, and I am using Scene2D actors for some of my sprites. In this regard, I have a sprite, which is spawning somewhere on the screen and needs to move to another position on the screen. To do this I am using the moveTo(xPos, yPos, duration, interpolation) method in the Actions, to make the move animation.
However, when I use this approach, the actor moves like I told it to, but it only moves in a straight line, from point A to B. I have tried several Interpolation options, like Circle interpolation and such, but it seems only to impact the speed of the animation line.
So now my question: How do I make my animation make a smooth curved line (See picture), from A to B?
I am currently using this code to make the Actions animation:
adultCustomerPointActor.addAction(Actions.sequence(
Actions.moveTo(300, 200, 2f, Interpolation.circle)
));
Thanks in advance for your help :)
It's a geometry problem. Using vectors, find the point halfway between the two points:
vec1.set(bx, by).sub(ax, ay).scl(0.5f).add(ax, ay);
Get another vector that is 90 or 270 to from the vector between the points:
vec2.set(bx, by).sub(ax, ay).rotate90().add(vec1);
This vec2 can be scaled to adjust how extreme curvature of the arc is. If you leave it alone, you'll have a quarter circle. You can also scale it negative to reverse the curvature.
Then add the second vector to the first to find the center point of your arc, which we can call point C.
vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
float angle = vec1.angle(vec3);
Now you need a vector that points from point C to point A. You will rotate this vector until it reaches point B. So you need the angle between CA and CB.
So here's a very simplistic class that implements this. It doesn't account yet for deciding if you want the arc to go up or down and if you want to scale how extreme it looks. You could add those as additional parameters with getters/setters. I haven't tested it, so it may need some debugging.
public class ArcToAction extends MoveToAction {
private float angle;
private final Vector2 vec1 = new Vector2(), vec2 = new Vector2(), vec3 = new Vector2();
#Override
protected void begin () {
super.begin();
float ax = target.getX(getAlignment()); // have to recalculate these because private in parent
float ay = target.getY(getAlignment());
vec1.set(getX(), getY()).sub(ax, ay);
vec2.set(vec1).rotate90();
vec1.scl(0.5f).add(ax, ay);
vec2.add(vec1);
vec1.set(bx, by).sub(vec2); // CB
vec3.set(ax, ay).sub(vec2); // CA
angle = vec1.angle(vec3);
}
protected void update (float percent) {
if (percent >= 1){
target.setPosition(getX(), getY(), getAlignment());
return;
}
vec1.set(vec3).rotate(percent * angle);
target.setPosition(vec1.x, vec1.y, getAlignment());
}
}
If you want to support automatic pooling, you can add a method like this:
static public ArcToAction arcTo (float x, float y, float duration, Interpolation interpolation) {
ArcToAction action = Actions.action(ArcToAction .class);
action.setPosition(x, y);
action.setDuration(duration);
action.setInterpolation(interpolation);
return action;
}

Box rotation around multiple axises using Matrix4f

The question change a bit, I figured out how to rotate around a single axis
I want to rotate a box around the Y axis using an angle.
The box has a size, and a Vector3f to signal the rotation.
To rotate the box correctly what I do is rotate the origin position then rotate the origin position plus the size, and use those two references to render the box.
However this rotation does not work correctly and causes rendering artifacts.
This is my code to rotate the positions:
Matrix4f matrix = new Matrix4f();
// Rotate the origin position
Vector3f pos = new Vector3f(new Vector3f(blockX, blockY, blockZ));
matrix.m03 = pos.x;
matrix.m13 = pos.y;
matrix.m23 = pos.z;
Vector3f rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMin = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Rotate the position with the size
// Top left back is the position of the block
Vector3f sizeRot = new Vector3f(new Vector3f(blockX + size, blockY + size, blockZ + size));
matrix = new Matrix4f();
matrix.m03 = sizeRot.x;
matrix.m13 = sizeRot.y;
matrix.m23 = sizeRot.z;
rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMax = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Then here I use the locationMax and the locationMin to render the cube
What could be wrong with this code? Is the logic I am using to rotate the box correct? as in rotate the origin position then rotate the origin position plus the size..
EDIT: I released that rotating after translating is stupid so instead I just rotated the locationMax which is not translated (it is only the size) then I translated and I still get the same result (Graphical Artifacts).
New Code:
float rx = blockX, ry = blockY, rz = blockZ;
Matrix4f matrix = new Matrix4f();
Vector3f rot = new Vector3f(0, 1f, 0f);
matrix = new Matrix4f();
matrix.m03 = size;
matrix.m13 = size;
matrix.m23 = size;
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
matrix.translate(new Vector3f(rx, ry, rz), matrix);
float mx = matrix.m03;
float my = matrix.m13;
float mz = matrix.m23;
// Here is use rx, ry, rz and mx, my, mz to render the box
============ * I figured it out (See below)* =============
EDIT:
This is what I ended up doing:
// Origin point
Vector4f a = new Vector4f(blockX, blockY, blockZ, 1);
// Rotate a matrix 45 degrees
Matrix4f mat = new Matrix4f();
mat.rotate((float) Math.toRandians(45f), new Vector3f(
0, 1f, 0), mat);
/* Transform the matrix to each point */
Vector4f c = new Vector4f(size.x, 0, size.z, 1);
Matrix4f.transform(mat, c, c);
Vector4f.add(c, a, c);
Vector4f b = new Vector4f(size.x, 0, 0, 1);
Matrix4f.transform(mat, b, b);
Vector4f.add(b, a, b);
Vector4f d = new Vector4f(0, 0, size.z, 1);
Matrix4f.transform(mat, d, d);
Vector4f.add(d, a, d);
// Here is use a, b, c, and d to render the box.
The problem with this is that I want to rotate around all axises and not only around the Y axis. This makes the code very long and unreadable and There are a lot of bugs when I try to rotate around all axises.
Update Question:
How do I take the above code and make it so I can rotate around all 3 axises. I want to do this so I can have a billboard that will always face the camera.
This is how I calculate the angle between the camera and the object:
Vector3f angle = new Vector3f();
// Calculate the distance between camera and object
Vector3f.sub(game.getCamera().getLocation(),
new Vector3f(blockX, blockY, blockZ), angle);
// Calculate the angle around the Y axis.
float vectorAngle = (float) ((float) Math.atan2(angle.z, angle.x) * -1 + (Math.PI / 2.0f));
Billboards are a very common application of computer graphics (as I'm sure you've noticed, since you're asking the question!)
Ultimately I think you are over complicating the problem, based on:
as in rotate the origin position then rotate the origin position plus the size..
For computer graphics, the most common transformations are Scaling, Translating, and Rotating, and you do these in an order to achieve a desired effect (traditionally you scale, then rotate about the origin, then translate the vertex's position).
Additionally, you will have three main matrices to render a model in 3d: World Matrix, View Matrix, and Projection Matrix. I believe you are having misunderstandings of transforming from Model Space to World Space.
Graphics TRS and Matrix info. If you are having conceptual problems, or this answer is insufficient, I highly recommend looking at this link. I have yet to find a better resource explaining the fundamentals of computer graphics.
So right at the moment, you have your three angles (in degrees, in a Vector3) corresponding to the angle difference in the X,Y, and Z coordinate spaces from your billboard and your camera. With this information, we generate the View matrix by first gathering all of our matrix transformations in one place.
I'm going to assume that you already have your Translation and Scaling matrices, and that they both work. This means that we only need to generate our Rotation matrix, and then transform that matrix with the scaling matrix, and then transforming that matrix by our translation matrix.
X Rotation Matrix
Y Rotation Matrix
Z Rotation Matrix
(Images taken from CodingLabs link above)
So you will generate these three matrices, using the X,Y, and Z angles you calculated earlier, and then transform them to consolidate them into a single matrix, transform that matrix by the scaling matrix, and then transform that matrix by the translation matrix. Now you have your awesome matrix that, when you multiply a a vertex by it, will transform that vertex into the desired size, rotation, and position.
So you transform every single vertex point by this generated matrix.
And then after that, you should be done! Using these techniques will hopefully simplify your code greatly, and set you on the right path :)
So now how about some code?
//I do not guarantee that this code compiles! I did not write it in an IDE nor did I compile it
float angleToRotX = 180f;
float angleToRotY = 90f;
float angleToRotZ = 0f;
// example vertex
Vector4f vertex = new Vector4f(0, 1, 0, 1);
// Rotate vertex's X coordinates by the desired degrees
Matrix4f rotationXMatrix = new Matrix4f();
rotationXMatrix.rotX(angleToRotX);
Matrix4f rotationYMatrix = new Matrix4f();
rotationYMatrix.rotY(angleToRotY);
Matrix4f rotationZMatrix = new Matrix4f();
rotationZMatrix.rotZ(angleToRotZ);
//now let's translate it by 1.5, 1, 1.5 in the X,Y,Z directions
Matrix4f translationMatrix = new Matrix4f();
translationMatrix.setTranslate(new Vector3f(1.5, 1, 1.5));
/*
Now we have our three rotational matrices. So we multiply them (transform them) to get a single matrix to transform all of the points in this model to the desired world coordinates
*/
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.mul(rotationXMatrix);
rotationMatrix.mul(rotationYMatrix);
rotationMatrix.mul(rotationZMatrix);
Matrix4f worldMatrix = translationMatrix;
worldMatrix.mul(rotationMatrix);
//now worldMatrix, when applied to a vertex, will rotate it by X,Y,Z degrees about the origin of it's model space, and then translate it by the amount given in translationMatrix
worldMatrix.transform(vertex);
//now vertex should be (1.5, 0, 1.5, 1) with (x,y,z,1)
Now this code could really be simplified, and it is excessively verbose. Try it out! I don't have java downloaded on my machine, but I grabbed the methods from the java documentation Here
Here is an image of what is happening (again, taking from coding labs):
(Advanced Info: Quaternions. These are really cool way of orienting a model in 3d space, however I don't quite understand them to the degree I need to in order to explain it to someone else, and I also believe that your problem is more fundamental)
You could generate the matrix without much hassle. The OpenGL matrix looks like the following:
|lx,ux,vx,px| - lx,ly,lz = the left vector
|ly,uy,vy,py| - ux,uy,uz = the up vector
|lz,uz,vz,pz| - vx,vy,vz = the view vector
|0 ,0 ,0 ,1 | - px,py,pz = the translation
All you need to do, is set px,py,pz to the position of your box in the world,
your view vector to the normalized(camera position - box position), your up comes straight from your camera, and the left is calculated via normalized cross product. It's also good practice to reconstruct the up vector, after left one is derived (by another cross product). That's all there's to it.
My solution aims to save you some time coding, rather than explain everything in detail. Hope that is useful to someone.

libgdx create texture from overlay using pixmap

I am trying to create a method which returns a texture modified by an overlay using libgdx and PixMap.
Assuming I have 2 images:
A Base Image in FileHandle textureInput
And an overlay image in FileHandle overLay
It should produce this texture:
So it should use the RGB values from the textureInput and the alpha values from the overLay and create the final image. I believe I can do this using the Pixmap class but I just can't seem to find exactly how.
Here is what I gather should be the structure of the method:
public Texture getOverlayTexture(FileHandle overLay, FileHandle textureInput){
Pixmap inputPix = new Pixmap(textureInput);
Pixmap overlayPix = new Pixmap(overLay);
Pixmap outputPix = new Pixmap(inputPix.getWidth(), inputPix.getHeight(), Format.RGBA8888);
// go over the inputPix and add each byte to the outputPix
// but only where the same byte is not alpha in the overlayPix
Texture outputTexture = new Texture(outputPix, Format.RGBA8888, false);
inputPix.dispose();
outputPix.dispose();
overlayPix.dispose();
return outputTexture;
}
I am just looking for a bit of direction as to where to go from here. Any help is really appreciated. I apologize if this question is too vague or if my approach is entirely off.
Thanks!
I finally found the way to do this.
How my game is setup is that each item draws itself. They are handed a spritebatch and can do stuff with it. I did it that way various reasons. There is an item manager containing a list of items. Each item has various attributes. Each item has it's own render method along with other independent methods. Here is what finally worked:
A normal item's render method which does not use any alpha masking:
public void render(SpriteBatch batch, int renderLayer) {
if(renderLayer == Integer.parseInt(render_layer)){ // be in the correct render layer
batch.draw(item.region,
item.position.x, // position.x
item.position.y, // position.y
0, //origin x
0, //origin y
item.region.getRegionWidth() , //w
item.region.getRegionHeight(), //h
item.t_scale, //scale x
item.t_scale, //scale y
item.manager.radiansToDegrees(item.rotation)); //angle
}
}
So it is handed a spritebatch that it draws to with the correct image, location, scale, and rotation, and that is that.
After playing around with what I found here: https://gist.github.com/mattdesl/6076846 for a while, this finally worked for an item who needs to use alpha masking:
public void render(SpriteBatch batch, int renderLayer) {
if(renderLayer == Integer.parseInt(render_layer)){
batch.enableBlending();
//draw the alpha mask
drawAlphaMask(batch, item.position.x, item.position.y, item.region.getRegionWidth(), item.region.getRegionHeight());
//draw our foreground elements
drawForeground(batch, item.position.x, item.position.y, item.region.getRegionWidth(), item.region.getRegionHeight());
batch.disableBlending();
}
}
There is a TextureRegion named alphaMask which contains a black shape.
It can be any image, but let's say in this instance its this shape / image:
Here is the function called above that uses that image:
private void drawAlphaMask(SpriteBatch batch, float x, float y, float width, float height) {
//disable RGB color, only enable ALPHA to the frame buffer
Gdx.gl.glColorMask(false, false, false, true);
// Get these values so I can be sure I set them back to how it was
dst = batch.getBlendDstFunc();
src = batch.getBlendSrcFunc();
//change the blending function for our alpha map
batch.setBlendFunction(GL10.GL_SRC_ALPHA, GL10.GL_ZERO);
//draw alpha mask sprite
batch.draw(alphaRegion,
x, // position.x
y, // position.y
0, // origin x
0, // origin y
alphaRegion.getRegionWidth(), // w
alphaRegion.getRegionHeight(), // h
item.t_scale, // scale x
item.t_scale, // scale y
item.manager.radiansToDegrees(item.rotation)); // angle
//flush the batch to the GPU
batch.flush();
}
There are a variety of "materials" to apply to any shape. In any instance one of them is assigned to the spriteRegion variable. Let's say right now it is this:
So the drawForeground method called above uses that image like this:
private void drawForeground(SpriteBatch batch, float clipX, float clipY, float clipWidth, float clipHeight) {
//now that the buffer has our alpha, we simply draw the sprite with the mask applied
Gdx.gl.glColorMask(true, true, true, true);
batch.setBlendFunction(GL10.GL_DST_ALPHA, GL10.GL_ONE_MINUS_DST_ALPHA);
batch.draw(spriteRegion,
clipX, // corrected center position.x
clipY, // corrected center position.y
0, //origin x
0, //origin y
spriteRegion.getRegionWidth() , //w
spriteRegion.getRegionHeight(), //h
item.t_scale, //scale x
item.t_scale, //scale y
item.manager.radiansToDegrees(item.rotation)); //angle
//remember to flush before changing GL states again
batch.flush();
// set it back to however it was before
batch.setBlendFunction(src, dst);
}
That all worked right away in the desktop build, and can produce "Brick Beams" (or whatever) in the game nicely:
However in Android and GWT builds (because after all, I am using libgdx) it did not incorporate the alpha mask, and instead rendered the full brick square.
After a lot of looking around I found this: https://github.com/libgdx/libgdx/wiki/Integrating-libgdx-and-the-device-camera
And so to fix this in Android I modified the MainActivity.java onCreate method like this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
cfg.useGL20 = false;
cfg.r = 8;
cfg.g = 8;
cfg.b = 8;
cfg.a = 8;
initialize(new SuperContraption("android"), cfg);
if (graphics.getView() instanceof SurfaceView) {
SurfaceView glView = (SurfaceView) graphics.getView();
// force alpha channel - I'm not sure we need this as the GL surface
// is already using alpha channel
glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
}
And that fixes it for Android.
I still cannot figure out how to make it work properly in gwt, as I cannot figure out how to tell libgdx to tell GWT to tell webGl to go ahead and pay attention to the alpha channel. I'm interested in how to do something like this in an easier or less expensive way (though this seems to work fine).
If anyone knows how to make this work with GWT, please post as another answer.
Here is the non-working GWT build if you want to see the texture issue:
https://supercontraption.com/assets/play/index.html

3D Picking OpenGL ES 2.0 after model matrix translation

Hey all I'm trying to implement 3D picking into my program, and it works perfectly if I don't move from the origin. It is perfectly accurate. But if I move the model matrix away from the origin (the viewmatrix eye is still at 0,0,0) the picking vectors are still drawn from the original location. It should still be drawing from the view matrix eye (0,0,0) but it isn't. Here's some of my code to see if you can find out why..
Vector3d near = unProject(x, y, 0, mMVPMatrix, this.width, this.height);
Vector3d far = unProject(x, y, 1, mMVPMatrix, this.width, this.height);
Vector3d pickingRay = far.subtract(near);
//pickingRay.z *= -1;
Vector3d normal = new Vector3d(0,0,1);
if (normal.dot(pickingRay) != 0 && pickingRay.z < 0)
{
float t = (-5f-normal.dot(mCamera.eye))/(normal.dot(pickingRay));
pickingRay = mCamera.eye.add(pickingRay.scale(t));
addObject(pickingRay.x, pickingRay.y, pickingRay.z+.5f, Shape.BOX);
//a line for the picking vector for debugging
PrimProperties a = new PrimProperties(); //new prim properties for size and center
Prim result = null;
result = new Line(a, mCamera.eye, far);//new line object for seeing look at vector
result.createVertices();
objects.add(result);
}
public static Vector3d unProject(
float winx, float winy, float winz,
float[] resultantMatrix,
float width, float height)
{
winy = height-winy;
float[] m = new float[16],
in = new float[4],
out = new float[4];
Matrix.invertM(m, 0, resultantMatrix, 0);
in[0] = (winx / width) * 2 - 1;
in[1] = (winy / height) * 2 - 1;
in[2] = 2 * winz - 1;
in[3] = 1;
Matrix.multiplyMV(out, 0, m, 0, in, 0);
if (out[3]==0)
return null;
out[3] = 1/out[3];
return new Vector3d(out[0] * out[3], out[1] * out[3], out[2] * out[3]);
}
Matrix.translateM(mModelMatrix, 0, this.diffX, this.diffY, 0); //i use this to move the model matrix based on pinch zooming stuff.
Any help would be greatly appreciated! Thanks.
I wonder which algorithm you have implemented. Is it a ray casting approach to the problem?
I didn't focus much on the code itself but this looks a way too simple implementation to be a fully operational ray casting solution.
In my humble experience, i would like to suggest you, depending on the complexity of your final project (which I don't know), to adopt a color picking solution.
This solution is usually the most flexible and the easiest to be implemented.
It consist in the rendering of the objects in your scene with unique flat colors (usually you disable lighting as well in your shaders) to a backbuffer...a texture, then you acquire the coordinates of the click (touch) and you read the color of the pixel in that specific coordinates.
Having the color of the pixel and the tables of the colors of the different objects you rendered, makes possible for you to understand what the user clicked from a logical perspective.
There are other approaches to the object picking problem, this is probably universally recognized as the fastest one.
Cheers
Maurizio

Categories