Java-Gaming.org    
Featured games (91)
games approved by the League of Dukes
Games in Showcase (577)
games submitted by our members
Games in WIP (498)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [SOLVED] Shear transformation in libgdx  (Read 817 times)
0 Members and 1 Guest are viewing this topic.
Offline whatever

Senior Newbie





« Posted 2013-09-22 15:42:03 »

I recently started experimenting with libgdx. Creating a SpriteBatch drawing sprites on it. Work like a sharm. It is possible to resize and rotate an sprite but I can't find a method to performe a shear transformation on a sprite, like it is possible in Java2D: http://docs.oracle.com/javase/7/docs/api/java/awt/geom/AffineTransform.html

Can somebody help me out on how to perform a shear operation on a sprite in libgdx?
Offline davedes
« Reply #1 - Posted 2013-09-22 16:56:23 »

One option is to apply a shear transformation matrix to the sprite. Another option is to transform the vertices yourself and submit them with the float[] parameter.

Here is an implementation of the first option:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
   private Matrix4 idt = new Matrix4();
   private Matrix4 shear = new Matrix4();
   private OrthographicCamera cam;
   
   public static Matrix4 toShear(Matrix4 m, float shx, float shy) {
      m.idt();
      m.val[Matrix4.M01] = shx;
      m.val[Matrix4.M10] = shy;
      return m;
   }
   
   @Override
   public void render () {
      Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
     
      cam.setToOrtho(false);
      spriteBatch.setProjectionMatrix( cam.combined );
      spriteBatch.begin();
     
      //draw your regular sprites with identity transform...
     spriteBatch.setTransformMatrix( idt );
      spriteBatch.draw(texture, 0, 0, 25, 25);
     
      //now draw your sheared sprites
     toShear(shear, 0.80f, 0.0f);
      spriteBatch.setTransformMatrix( shear );
     
      spriteBatch.draw(texture, 50, 50);
      spriteBatch.end();
   }


More info on the shear matrix here:
http://cs.fit.edu/~wds/classes/cse5255/thesis/shear/shear.html

Keep in mind that changing the transform/projection matrices will flush your batch. You should order your calls to minimize batch flushing, see here:
https://github.com/mattdesl/lwjgl-basics/wiki/Sprite-Batching

Offline whatever

Senior Newbie





« Reply #2 - Posted 2013-09-22 18:35:56 »

Setting a shear transformation on the SpriteBatch is not an option for me. I have many sprites that are sheared different ways. This will (like you say) kill the SpriteBatch. I'am going to try manipulation the vertices. I will keep you posted.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline davedes
« Reply #3 - Posted 2013-09-22 18:55:38 »

I talk a little about setting individual vertices using Sprite or SpriteBatch in this post:
http://www.badlogicgames.com/forum/viewtopic.php?p=42550#p42550

It is for a gradient (individual vertex colors), but the same concept should apply for individual vertex positions. The downside is that you won't get the nice rotation/scale/etc of SpriteBatch.draw() utilities.

Offline whatever

Senior Newbie





« Reply #4 - Posted 2013-09-23 22:26:54 »

Fixed. I now use the standard Java AfineTransform to change the vertices. This makes converting my existing code (Java2D) much easier because AfineTransform is used there quite frequently. See the example code below.

And of course. Thanks for the help  Smiley

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
public class GdxPerf implements ApplicationListener {
   private OrthographicCamera camera;
   private SpriteBatch batch;
   private Texture texture;
   private Sprite sprite;
   private AffineTransform transform = new AffineTransform();
   
   private float[] verticesSrc = null;
   private float[] verticesDst = null;
   private float[] src = new float[8];
   private float[] dst = new float[8];
   
   @Override
   public void create() {      
      camera = new OrthographicCamera();
     
      batch = new SpriteBatch();
     
      texture = new Texture(Gdx.files.internal("data/Alice.png"));
      texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
     
      TextureRegion region = new TextureRegion(texture, 0, 0, 512, 512);
     
      sprite = new Sprite(region);
      sprite.setPosition(0, 0);
     
      verticesSrc = sprite.getVertices();
      verticesDst = Arrays.copyOf(sprite.getVertices(), sprite.getVertices().length);
     
      transform = new AffineTransform();
   }

   @Override
   public void dispose() {
      batch.dispose();
      texture.dispose();
   }

   @Override
   public void render() {      
      Gdx.gl.glClearColor(0, 0, 0, 0);
      Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
     
      transform.setToIdentity();
     
      transform.translate(50.0d, 50.0d);
      transform.scale(1.5d, 1.5d);
      transform.shear(0.25d, 0.10d);
      transform.rotate(-Math.PI / 8.0d);
     
      src[0] = verticesSrc[SpriteBatch.X1];
      src[1] = verticesSrc[SpriteBatch.Y1];
      src[2] = verticesSrc[SpriteBatch.X2];
      src[3] = verticesSrc[SpriteBatch.Y2];
      src[4] = verticesSrc[SpriteBatch.X3];
      src[5] = verticesSrc[SpriteBatch.Y3];
      src[6] = verticesSrc[SpriteBatch.X4];
      src[7] = verticesSrc[SpriteBatch.Y4];

      transform.transform(src, 0, dst, 0, 4);
     
      verticesDst[SpriteBatch.X1] = dst[0];
      verticesDst[SpriteBatch.Y1] = dst[1];
      verticesDst[SpriteBatch.X2] = dst[2];
      verticesDst[SpriteBatch.Y2] = dst[3];
      verticesDst[SpriteBatch.X3] = dst[4];
      verticesDst[SpriteBatch.Y3] = dst[5];
      verticesDst[SpriteBatch.X4] = dst[6];
      verticesDst[SpriteBatch.Y4] = dst[7];

      camera.setToOrtho(false);
      batch.setProjectionMatrix(camera.combined);
      batch.begin();
     
      batch.draw(texture, verticesDst, 0, verticesDst.length);
           
      batch.end();
   }

   @Override
   public void resize(int width, int height) {
   }

   @Override
   public void pause() {
   }

   @Override
   public void resume() {
   }
}
Offline davedes
« Reply #5 - Posted 2013-09-24 03:40:13 »

Keep in mind that the java2D package won't work on WebGL, iOS, or Android. Nor will it work if you use a desktop backend like JGLFW.

Offline whatever

Senior Newbie





« Reply #6 - Posted 2013-09-27 22:11:04 »

Indeed. Looks like I have to make my own AffineTransform implementation that behaves like the Java2D one.
Offline davedes
« Reply #7 - Posted 2013-09-27 22:55:10 »

Why not just use the shear matrix transform I posted earlier, along with standard LibGDX camera / matrix? Tongue

Offline whatever

Senior Newbie





« Reply #8 - Posted 2013-09-28 15:47:13 »

My original Java2D application that I want to convert to libGdx uses a different shear transformation for every drawed image. Using the SpriteBatch.setTransformMatrix is not an option because it will render the SpriteBatch useless (flushes each draw to the GPU).

I tought about extending the Sprite class or build a wrapper around it. Problem with this solution is that it can become implemetation dependent on the Sprite class real fast.

I noticed that the transformations of the Sprite class are a bit different from the Java2D implementation. For example: rotate in Java2D rotates default around the bottom left point of an image. Sprite rotates around the center of the image. Of course this can all be solved.

Making my own AffineTransform implementation has the benefit that the original code doesn't have to be rewritten much.

In the end it is a decision with both pro's and con's. Rewrite more parts of the original code or create an easy way to use libGdx for this application. In this case I choose not to rewrite big parts of the original code.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

xsi3rr4x (22 views)
2014-04-15 18:08:23

BurntPizza (17 views)
2014-04-15 03:46:01

UprightPath (31 views)
2014-04-14 17:39:50

UprightPath (15 views)
2014-04-14 17:35:47

Porlus (31 views)
2014-04-14 15:48:38

tom_mai78101 (57 views)
2014-04-10 04:04:31

BurntPizza (115 views)
2014-04-08 23:06:04

tom_mai78101 (214 views)
2014-04-05 13:34:39

trollwarrior1 (182 views)
2014-04-04 12:06:45

CJLetsGame (189 views)
2014-04-01 02:16:10
List of Learning Resources
by Longarmx
2014-04-08 03:14:44

Good Examples
by matheus23
2014-04-05 13:51:37

Good Examples
by Grunnt
2014-04-03 15:48:46

Good Examples
by Grunnt
2014-04-03 15:48:37

Good Examples
by matheus23
2014-04-01 18:40:51

Good Examples
by matheus23
2014-04-01 18:40:34

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:22:30

Anonymous/Local/Inner class gotchas
by Roquen
2014-03-11 15:05:20
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!