-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
basis universal texture atlas loading #1
Comments
Hi, and thanks for the question. Seems like a simple guide on how to load generated atlases is missing for the GDX Texture Packer. Will fix it in the next release. Overall, manually loading a basis-based atlas should not be any more complicated than loading a regular texture atlas. You just need to do everything that the standard Before you use the code below, you should have the // First off, load the basis texture.
FileHandle textureFile = Gdx.files.internal("path/to/atlas/texture.basis");
TextureData textureData = new BasisuTextureData(textureFile);
Texture texture = new Texture(textureData);
// Load the atlas data.
FileHandle atlasFile = Gdx.files.internal("path/to/atlas/data.atlas");
TextureAtlas.TextureAtlasData atlasData = new TextureAtlas.TextureAtlasData(atlasFile, atlasFile.parent(), false);
// The most important part - manually assign the texture
// to all the pages before initiating the atlas object.
// BEWARE: In case your atlas has multiple pages,
// you should assign the appropriate textures for each page.
// This example works for single-page atlases only.
for (TextureAtlas.TextureAtlasData.Page page : atlasData.getPages()) {
page.texture = texture;
}
// Then simply instantiate the atlas object.
TextureAtlas atlas = new TextureAtlas(atlasData); That's it. I didn't test the code, but you should get the idea. PS: You don't need to manually dispose every atlas texture. The textures will be disposed of along with the atlas, when you call |
I can't get this working, I keep getting classCastExceptions. I have the following in my assetManager private static void setLoaders() {
assetManager.setLoader(TextureAtlas.class, ".basis", basisUniversalTextureAtlasLoader);
assetManager.setLoader(Texture.class, ".basis", new BasisuTextureLoader(assetManager.getFileHandleResolver()));
assetManager.setLoader(Texture.class, textureLoader);
assetManager.setLoader(TextureAtlas.class, textureAtlasLoader);
} my assetLoader has to extend a SynchronousAssetLoader (I think), so it looks like this right now (changed it multiple times) public class BasisUniversalTextureAtlasLoader extends SynchronousAssetLoader<TextureAtlas, TextureAtlasLoader.TextureAtlasParameter> {
public BasisUniversalTextureAtlasLoader(FileHandleResolver resolver) {
super(resolver);
}
TextureAtlasData data;
@Override
public TextureAtlas load(AssetManager assetManager, String fileName, FileHandle file, TextureAtlasParameter parameter) {
// First off, load the basis texture.
FileHandle textureFile = file.parent().child(fileName + ".basis");
TextureData textureData = new BasisuTextureData(textureFile);
Texture texture = new Texture(textureData);
// Load the atlas data.
TextureAtlas.TextureAtlasData atlasData = new TextureAtlas.TextureAtlasData(file, file.parent(), false);
// The most important part - manually assign the texture
// to all the pages before initiating the atlas object.
// BEWARE: In case your atlas has multiple pages,
// you should assign the appropriate textures for each page.
// This example works for single-page atlases only.
for (TextureAtlas.TextureAtlasData.Page page : atlasData.getPages()) {
page.texture = texture;
}
// Then simply instantiate the atlas object.
TextureAtlas atlas = new TextureAtlas(atlasData);
return atlas;
}
@Override
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle atlasFile, TextureAtlasParameter parameter) {
Array<AssetDescriptor> dependencies = new Array();
return dependencies;
}
static public class BasisuTextureAtlasParameter extends AssetLoaderParameters<TextureAtlas> {
/** whether to flip the texture atlas vertically **/
public boolean flip = false;
public BasisuTextureAtlasParameter() {
}
public BasisuTextureAtlasParameter(boolean flip) {
this.flip = flip;
}
}
} And I get the following errors
|
If you're using This is the only line you need: // Register the texture loader for the ".basis" file extension.
assetManager.setLoader(Texture.class, ".basis", new BasisuTextureLoader(assetManager.getFileHandleResolver())); Once the asset manager knows how to load |
@jeltedeproft sorry, I made a mistake in the example code link. Please see the updated answer ⬆️ |
Sorry that I come back to this after several weeks, I put this issue aside for a while, but the solution you proposed doesn't seem to work for me. After adding the loader class like you mentioned private static void setLoaders() {
assetManager.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(filePathResolver));
assetManager.setLoader(BitmapFont.class, ".ttf", new FreetypeFontLoader(filePathResolver));
assetManager.setLoader(TiledMap.class, tmxMapLoader);
assetManager.setLoader(Texture.class, textureLoader);
assetManager.setLoader(Texture.class, ".basis", new BasisuTextureLoader(assetManager.getFileHandleResolver()));
assetManager.setLoader(TextureAtlas.class, textureAtlasLoader);
assetManager.setLoader(Skin.class, new FreeTypeSkinLoader(assetManager.getFileHandleResolver()));
assetManager.setLoader(ParticleEffect.class, particleEffectLoader);
assetManager.setLoader(Sound.class, soundLoader);
assetManager.setLoader(Music.class, musicLoader);
assetManager.setLoader(SoundBuffer.class, soundBufferLoader);
loadersSet = true;
} i get the following error
Any ideas? |
Looking at the error, I don't think it's related to the atlas loader. There might be something wrong with the specific file, whose name appears to be in weird coding:
Just find the problematic file, and it should be obvious from there that it might be broken or something similar. On a side note, unless you use your own custom asset loaders, you don't need to add them manually. Just have a look at the AssetManager`s constructor to get an idea of what is supported out of the box. For Basis textures/atlases to work, you only need this one line: assetManager.setLoader(Texture.class, ".basis", new BasisuTextureLoader(assetManager.getFileHandleResolver())); |
Thanks for the tip! i cleaned up my code a bit with the loaders. After some debugging I finally understand the issue. First when the textureAtloas tries to get loaded it uses the TextureAtlasLoader to load the sprites.basis texture atlas. Nothing wrong here. Then when it starts looking for dependencies (aka the sprites in the atlas) it got the wrong loader for me. It got the TextureLoader. This was because in the stored loaders it had the following for the Texture key
It then took the TextureLoader because the filename it finds in the textureAtlas was
all the sprites in the basis texture atlas have a filename like this, I assume because of the way they are stored? Do you have any better solutions? |
hmm when I remove the extension it gives me the following error
|
it happens here in the TextureAtlasLoader @Override
public Array<AssetDescriptor> getDependencies (String fileName, FileHandle atlasFile, TextureAtlasParameter parameter) {
FileHandle imgDir = atlasFile.parent();
if (parameter != null)
data = new TextureAtlasData(atlasFile, imgDir, parameter.flip);
else {
data = new TextureAtlasData(atlasFile, imgDir, false);
}
Array<AssetDescriptor> dependencies = new Array();
for (Page page : data.getPages()) {
TextureParameter params = new TextureParameter();
params.format = page.format;
params.genMipMaps = page.useMipMaps;
params.minFilter = page.minFilter;
params.magFilter = page.magFilter;
dependencies.add(new AssetDescriptor(page.textureFile, Texture.class, params));
}
return dependencies;
} It creates a Textureparameter class, this is why i originally thought i had to make my own TextureAtlasLoader |
Oh, my bad. Seems like Basis texture loader for atlases was broken for a while... Thanks for the digging! Meanwhile, just use this simplified version of the loader, that is based on the standard package com.crashinvadrs.basisu.gdx;
import com.badlogic.gdx.assets.AssetDescriptor;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.assets.loaders.AsynchronousAssetLoader;
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
import com.badlogic.gdx.assets.loaders.TextureLoader;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
import com.crashinvaders.basisu.gdx.BasisuGdxUtils;
import com.crashinvaders.basisu.gdx.BasisuTextureData;
public class CustomBasisTextureLoader extends AsynchronousAssetLoader<Texture, TextureLoader.TextureParameter> {
BasisuTextureData textureData;
public CustomBasisTextureLoader(FileHandleResolver resolver) {
super(resolver);
// We need to make sure this one is first time called
// on the main thread and not during async texture loading.
BasisuGdxUtils.initSupportedGlTextureFormats();
}
public void loadAsync(AssetManager manager, String fileName, FileHandle fileHandle, TextureLoader.TextureParameter parameter) {
BasisuTextureData data;
data = new BasisuTextureData(fileHandle);
data.prepare();
textureData = data;
}
public Texture loadSync(AssetManager manager, String fileName, FileHandle fileHandle, TextureLoader.TextureParameter parameter) {
Texture texture = new Texture(this.textureData);
this.textureData = null;
if (parameter != null) {
texture.setFilter(parameter.minFilter, parameter.magFilter);
texture.setWrap(parameter.wrapU, parameter.wrapV);
}
return texture;
}
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle fileHandle, TextureLoader.TextureParameter parameter) {
return null;
}
} |
No problem, thanks for sticking with the issue |
sorry for coming back to this agai, but I can't get it working with your modified class. Here is the error I am getting
|
Hm, so the atlas page files on the file system have proper names after the texture packer export, right? |
yeah the .atlas file has normal names |
Ok, what about the actual files, do they have the same names as in the atlas file, or are they gibberish straight out of gdx-texture-packer? Or do the names get read wrong at runtime, when the atlas tries to load them? I want to understand at what point the names get broken. If the gdx-texture-packer outputs them that way, I would ask you about the minimalistic gdx-texture-packer project so I can reproduce the issue on my end. Like get a random image or two, create an atlas for them and save the |
ok, so the output of the gdx-texture-packer is an atlas file with normal names, all my files have the same normal name. |
The gdx-texture-packer project seems totally fine and the output files are fully valid. I tested the files in a blank project using this code: AssetManager assetManager = new AssetManager();
assetManager.setLoader(Texture.class, ".basis", new BasisuTextureLoader(assetManager.getFileHandleResolver()));
assetManager.load("test.atlas", TextureAtlas.class);
assetManager.finishLoading();
TextureRegion region = assetManager.get("test.atlas", TextureAtlas.class).findRegion("alchemist-CLIMBING1-left", 1) It loads atlas and yields an absolutely normal texture region that I can render on the screen. At this point, I'd assume that the naming issue you're having is OS/system configuration related. Looks more like something is broken with text encoding. And it doesn't seems like it has anything to do with gdx-texture-packer or basis textures directly. But I wonder if you have similar issues when you change the atlas texture format to PNG? What OS are you on? Also, it'd help a lot to understand at what stage the names get broken at runtime. If you could jump into debugging and see how the loaded |
I've used PNG for quite a while and it always worked normally, it was only once i switched to basis that i had this problem. Edition Windows 11 Pro I'll try the debugging next |
Gotcha, thanks. I will try to reproduce it on my Win10 machine. Just to clarify, do you have the same issue with the test atlas you've sent (cannot load on runtime)? |
omg I am a complete idiot, I'm so sorry. Working now! thanks for all the help |
Haha, it's good it wasn't another rare system-related bug that takes an eternity to locate... Anyway, I hope it's gonna work fine for you from here. One note, something I found myself soon after implementing the texture compression lib, Basis doesn't suit pixel art and low-res images well. There are a lot of noticeable artifacts on the compressed textures, it totally destroys the pixel art page images and produces different kinds of unexpected image distortion on different platforms (based on the transcoded format). At least when ETC1S (low-quality compression) is used. You might try UASTC (high-quality compression) which is less size-efficient but should give a more predictable and clean output. |
ok, thanks for the tip, I'll use the UASTC compression and I'll do a check to see if the quality is still good. |
how do I load a basis universal sprite sheet created gdx-texture-packer into libgdx?
The text was updated successfully, but these errors were encountered: