Author Topic: Texture repeat  (Read 4068 times)

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Texture repeat
« on: September 10, 2011, 11:27:46 am »
Hello,

I am building a 3D world, and in Blender I have set the textures to repeat over my models. I get the following in Blender:



ie the texture does repeat.

In JPCT however, the texture seems to strecth and distort:



I have not explicitely set any repeat attribute in JPCT as I could not find any (thought it would read from the 3DS file). I load the texture and the model with the following codes.

Code: [Select]
final Texture sea = new Texture(Flight.getInstance().getResources().openRawResource(R.raw.seaday));
TextureManager.getInstance().addTexture("seaday.jpg", sea);

Code: [Select]
Object3D[] model = Loader.load3DS(file, scale);
Object3D o3d = new Object3D(0);
Object3D temp = null;
for (int i = 0; i < model.length; i++) {
    temp = model[i];
    temp.setCenter(SimpleVector.ORIGIN);
    temp.rotateX((float)( -.5*Math.PI));
    temp.rotateMesh();
    temp.setRotationMatrix(new Matrix());
    o3d = Object3D.mergeObjects(o3d, temp);
    o3d.build();
}
return o3d;

Is there a way to specify a repeat ratio in JPCT (something like "wrapTextureSpherical" but with repeat?)

Thanks
Nicolas

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Re: Texture repeat
« Reply #1 on: September 11, 2011, 04:40:30 pm »
Anyone has an idea?

I tried to look for texturing tutorials for JPCT and coulnd't find much. Does ayone have a link to share?

Thx
Nicolas

Offline MrM

  • byte
  • *
  • Posts: 36
    • View Profile
Re: Texture repeat
« Reply #2 on: September 11, 2011, 04:56:43 pm »
Try this:
Put your texture in drawable, just for siplicity's sake.

Code: [Select]

import android.graphics.drawable.BitmapDrawable;
import android.graphics.BitmapFactory;
import android.graphics.Shader;

BitmapDrawable tile = new BitmapDrawable(BitmapFactory.decodeResource(Flight.getResources(), R.drawable.seaday));
tile.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);

Texture sea = new Texture(tile);

TextureManager.getInstance().addTexture("seaday.jpg", sea);


Then, take whatever your Object3D is called, for example plane:
Code: [Select]
plane.setTexture("seaday.jpg")

Tell me if ti works out for you. You might need to change the image size, or fiddle with the Shader tiling.

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Re: Texture repeat
« Reply #3 on: September 11, 2011, 06:01:10 pm »
Thank you for your suggestion. I ended up "gridifying" all my large planes, and marking all edges as "seem" in blender. After UVMap, it looks much better:



I will spend a bit more time on it to see if I can fix the few border artifacts, if not, will try your suggestion.

Thanks!
Nicolas

Offline MrM

  • byte
  • *
  • Posts: 36
    • View Profile
Re: Texture repeat
« Reply #4 on: September 11, 2011, 06:13:50 pm »
No problem, I could try and make your texture image seamless if you want (if it's not seamless already), but as you use multiple planes, I doubt that will help you.
Cheers, and good luck  ;D

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Re: Texture repeat
« Reply #5 on: September 11, 2011, 06:46:20 pm »
Wow, your code just produces awesome results. Only problem is that FPS has taken a serious hit. I'm not stretching the planes too much though, ie there's not a crazy amount of repeats. Any idea why this?

Thx
Nicolas

Offline MrM

  • byte
  • *
  • Posts: 36
    • View Profile
Re: Texture repeat
« Reply #6 on: September 11, 2011, 07:04:25 pm »
Hmmm... This could be a problem.

Where are you loading the resources? onSurfaceChanged or onSurfaceCreated?
I think it could be happening if the image was loaded separately for each tile.
How big is your image? Try compressing it if it's too big...

And if you're loading your stuff in onSurfaceChanged try doing it in onSurfaceCreated.

Quote
public abstract void onSurfaceCreated (GL10 gl, EGLConfig config)
Since: API Level 3

Called when the surface is created or recreated.

Called when the rendering thread starts and whenever the EGL context is lost. The EGL context will typically be lost when the Android device awakes after going to sleep.

Since this method is called at the beginning of rendering, as well as every time the EGL context is lost, this method is a convenient place to put code to create resources that need to be created when the rendering starts, and that need to be recreated when the EGL context is lost. Textures are an example of a resource that you might want to create here.

Note that when the EGL context is lost, all OpenGL resources associated with that context will be automatically deleted. You do not need to call the corresponding "glDelete" methods such as glDeleteTextures to manually delete these lost resources.

Please provide feedback if possible, or if there are any improvements.

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Re: Texture repeat
« Reply #7 on: September 11, 2011, 07:39:02 pm »
I tweaked a bit the bitmaps (size, JPEG compression, seamless) and it looks quite good now. I also followed your advice on the "onSurfaceCreated". That didn't make a noticeable performance change but am convinced that it is better to put the code there.

Performance is better now but there is a huge correlation between performance and the amount of time  textures are repeated. I guess this is good in a way, it makes me bear in mind technical limitations rather than just making everything "hi-res" :)



Thx
Nicolas

Offline MrM

  • byte
  • *
  • Posts: 36
    • View Profile
Re: Texture repeat
« Reply #8 on: September 11, 2011, 08:00:11 pm »
I can see what you mean. Maybe it's just how things work in android.graphics.Shader.

I think I'd rather create a bigger texture which would be tiled (512 or 1024) in Photoshop or whatever,  then in a 3d program make the water plane (not the Airplane, but the sea) just one object (eg.: one plane), flatten it's UV's and make sure they're the shape of the sea plane (again, not the Airplane), align them with the texture, and export it all as OBJ (It's my favorite format).  Then load it in JPCT-ae, and assign the texture which was created before, the tiled one. I would also use MemoryHelper.compact() because:
Quote
This can be used to trigger some gc work that might otherwise interrupt the application causing an animation to stutter or similar. However, this method can't avoid that...it just increases the chance that won't happen or at least not that often.

and probably clear the loader cache with Loader.clearCache();...

I think if you use one single bitmap which you would manually tile in an image editor, and slap it on just one flat UVed object, it would look nicer, and improve the fps...

Offline MrM

  • byte
  • *
  • Posts: 36
    • View Profile
Re: Texture repeat
« Reply #9 on: September 11, 2011, 08:05:30 pm »
Oh yeah, and I like how it's done in the example, everything's compiled in a FrameBuffer, and then drawn and rendered in onDrawFrame();...

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Re: Texture repeat
« Reply #10 on: September 11, 2011, 08:07:48 pm »
I am not sure what you mean by

Quote
I think if you use one single bitmap which you would manually tile in an image editor, and slap it on just one flat UVed object, it would look nicer, and improve the fps...

Do you mean you would rather repeat the texture in a photoshop like program to get approximately the size of the plane rather than making the renderer repeat it at runtime?

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11777
    • View Profile
    • http://www.jpct.net
Re: Texture repeat
« Reply #11 on: September 11, 2011, 08:10:52 pm »
jPCT-AE (as well as jPCT) repeats the texture by default if the texture coordinates are <0 or >1, i.e. if the upper left corner is at 0/0 and the lower right at 10/10, the texture will be repeated 10 times on that polygon. I've no idea what Blender does, when you enable this "repeating", but obviously something different or otherwise, it should just work. Or maybe the exporter screws it up somehow?

Offline MrM

  • byte
  • *
  • Posts: 36
    • View Profile
Re: Texture repeat
« Reply #12 on: September 11, 2011, 08:21:34 pm »
I would repeat it in Photoshop. If "X" is my original image and its 64x64 , I would do this:

I would open a new 1024x1024 blank image and copy it again and again (like in a 8x8 matrix) like so:

[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]
[X  X  X  X  X  X  X  X]

Then save that image, and apply it to my object, so it would be tiled at runtime.
I've used a lot of complex models (7000+ polys) with big images before (When I wanted a detailed UV object, with a complex map), and so far I haven't had problems with fps, 4-7 frames at the most. Of course, I used MemoryHelper.compact(); and Loader.clearCache(); too...

Maybe it's just me, but you won't know unless you try :)

Plus, what ErgonOlsen said just now is true, I typed the method above because I've no idea how Blender works, I use something else.

Offline Tishu

  • byte
  • *
  • Posts: 32
    • View Profile
Re: Texture repeat
« Reply #13 on: September 11, 2011, 08:43:39 pm »
From what I have read on some forums, the "repeating" option in blender is not exported, it is a blender only thing so it is of no help here.

I realized than even with removing

Code: [Select]
citydayc.setTileModeXY(TileMode.REPEAT, TileMode.REPEAT);

the textures now repeat correctly. There are still a few artefacts but I reckon this is more to do with my UVmapping than with JPCT.

I get about 28-30 FPS on my Desire HD, but it drops to around 20-24 when I hover some more complex textures, and same values when collision detection is playing.

MrM, I see your point. I think I will continue with the route of smaller images however and let JPCT repeat them. This seems to be the best performance/look ratio. Thanks a lot for your help.

Rgds
Nicolas