Текстура из текстурпакера в LibGDX

Пытаюсь понять обертку текстуры в (потрясающей) среде LibGDX, и мне нужна помощь.

Я хотел бы привязать текстуру (согласно Mesh, Color & Texture), который извлекается из TextureAtlas, упакованного с помощью TexturePacker. Текстура привязывается к прямоугольной сетке.

Я хочу, чтобы текстура (экземпляр текстуры) в основном извлекалась из упакованного файла.

Можно ли использовать методы createsprite или findregion и как-то пропустить шаг дескриптора файла?

Дополнительно: что-то особенное следует иметь в виду при объединении вышеуказанного метода с AssetManager?

Спасибо, что разобрались со мной!


person user1450458    schedule 12.06.2012    source источник


Ответы (2)


Создайте область текстуры

Сначала вы создаете объект TextureAtlas, указывая на текстовый файл, описывающий ваш атлас (инструмент, создающий атлас, создаст два файла: изображение и текстовый файл с описанием его содержимого):

TextureAtlas myTextures = new TextureAtlas("images/packed.txt");

Затем вы можете найти TextureRegion в этом атласе (то есть конкретную подтекстуру атласа). Регион должен иметь базовое имя исходного файла, который использовался (есть больше деталей и параметров, если вы следуете некоторым специальным соглашениям об именах для создания массивов элементов текстуры, но пока оставьте это):

TextureRegion region = myTextures.findRegion(fname);

Настроить текстурированную сетку

Чтобы нарисовать эту область текстуры на сетке, вам нужно инициализировать Mesh с поддержкой координат текстуры:

Mesh myMesh = new Mesh(...,
                       new VertexAttribute(Usage.TextureCoordinates, 2, "y"));

new VertexAttribute(Usage.TextureCoordinates, 2, ...) сообщает libGDX, что этот меш будет иметь две текстурные координаты для каждой вершины (традиционно две текстурные координаты называются u и v). У вас может быть множество различных атрибутов для каждой вершины, но я предполагаю, что единственным другим атрибутом является Usage.Position с тремя значениями для пространственных координат x, y, z.

Теперь в массиве с плавающей запятой, который определяет вашу сетку (массив, который вы передаете в setVertices), вам нужно установить пространственные координаты x, y и z плюс координаты текстуры u и v для каждой вершины:

final int floatsPerVertex = 5; // 3 spatial +  2 texture
float[] meshData = new float[numVerticies * floatsPerVertex];
for (int i = 0; i < numVerticies; i++) {
   meshData[(i * floatsPerVertex) + 0] = ... ; // x coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 1] = ... ; // y coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 2] = ... ; // z coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 3] = ... ; // u texture coordinate of i'th vertex
   meshData[(i * floatsPerVertex) + 4] = ... ; // v texture coordinate of i'th vertex
}
myMesh.setVertices(meshData);

Вы можете вычислить правильные u и v для конкретного TextureRegion с помощью методов getU, getV, getU2 и getV2. Обратите внимание, что координаты текстуры имеют начало координат (u1, v1) в левом верхнем углу, а ось Y указывает «вниз» (экранные и пространственные координаты в OpenGL обычно имеют начало в левом нижнем углу, а точки оси Y — «внизу»). вверх"). Это немного сложно, но очень гибко, так как вы можете переворачивать, растягивать или искажать текстуру, когда она отображается на вашей сетке.

Поскольку текстура большая (скажем, 512x512), а конкретная область является небольшим ее подмножеством (скажем, 20x20 при разрешении 128x128), в конечном итоге вы получите координаты текстуры сетки, которые используют только подмножество 20x20 всего изображения 512x512.

Визуализировать текстурированную сетку

Наконец, при рендеринге вам нужно привязать изображение и включить текстурирование перед рендерингом:

region.getTexture().bind();
Gdx.graphics.getGL10().glEnable(GL10.GL_TEXTURE_2D);
myMesh.render();
Gdx.graphics.getGL10().glDisable(GL10.GL_TEXTURE_2D);

Обратите внимание, что это гораздо менее эффективно, чем должно быть. Частично преимущество текстурного атласа заключается в том, что он должен содержать множество областей, которые можно визуализировать вместе, поэтому вам нужно только связать одну текстуру, а затем визуализировать множество различных текстурированных сеток из этой одной связанной текстуры.

SpriteBatch поддерживает спрайты, определенные с помощью TextureRegion, и AssetManager поддерживают загрузку и поиск TextureAtlas в качестве элемента первого класса.

person P.T.    schedule 12.06.2012
comment
Ценю твою помощь. Спасибо! - person user1450458; 21.06.2012
comment
@ user1450458 Рад, что ответ оказался полезным. Если это удовлетворительно отвечает на ваш вопрос, пожалуйста, примите ответ (нажмите на очертание галочки слева, чтобы она стала зеленой). См. раздел ответов: stackoverflow.com/faq#howtoask. - person P.T.; 21.06.2012
comment
Я не понял тег принятия-ответа, но спасибо. Последующие действия: я не могу найти метод setTexureCoordinates для класса Mesh или любой другой метод, обрабатывающий TextureRegion или AtlasRegion. - person user1450458; 25.06.2012
comment
@user1450458 user1450458 К сожалению, я напортачил с setTextureCoordinates .. это мой собственный метод. Я обновлю ответ, чтобы включить правильные детали. - person P.T.; 25.06.2012
comment
Наконец-то у меня снова есть время, чтобы просмотреть это, и я не могу заставить работать одну вещь: регион. Метод getImage() не существует. и, кроме того, если я буду использовать метод getTexture(), я получу взамен всю упакованную страницу с текстурами. Любые решения? - person user1450458; 10.09.2012
comment
Ой, извините за это! Вы должны использовать метод getTexture для региона и привязать его. (Так что теперь region.getTexture().bind()). Привязка всей текстуры правильная. Идея состоит в том, что вы вызываете bind один раз (что затратно — думайте об этом как о загрузке текстуры на вашу видеокарту) с очень большой текстурой, а затем вы «рисуете» множество (u, v) субрегионов из этого одна текстура. - person P.T.; 10.09.2012

Получил это, чтобы работать, используя приведенное выше объяснение.

Я не могу поверить, что так мало людей задают этот вопрос, потому что это похоже на то, что другие хотели бы сделать.

Из принятого решения я создал функцию, которая также вычисляет новую позицию UV.

Протестировано, и это работает для меня, но, пожалуйста, просмотрите, поскольку я не разработчик Java.

public Mesh RebuildMeshUVtoTextureRegion(Mesh ObjectMesh, TextureRegion UVMapPos)
{
    int numFloats = ObjectMesh.getNumVertices() * ObjectMesh.getVertexSize() / 4;
    float[] vertices = new float[numFloats];
    ObjectMesh.getVertices(vertices);

    int numIndices = ObjectMesh.getNumIndices();
    short SourceIndices[] = new short[numIndices];
    ObjectMesh.getIndices(SourceIndices);

    final int floatsPerVertex = 5;
    int TimesToLoop = ((vertices.length) /floatsPerVertex); 

    float previousU;
    float previousV;

    float FullMapHeight = UVMapPos.getTexture().getHeight();
    float FullMapWidth  = UVMapPos.getTexture().getWidth();
    float NewMapWidth = UVMapPos.getRegionWidth();
    float NewMapHeight = UVMapPos.getRegionHeight();

    float FullMapUPercent;
    float FullMapVPercent;

    for (int i = 0; i < TimesToLoop; i++) 
    {   
        previousU = (vertices[(i * floatsPerVertex) + 3]);
        previousV = (vertices[(i * floatsPerVertex) + 4]);
        FullMapUPercent = previousU / FullMapWidth;
        FullMapVPercent = previousV / FullMapHeight;
        vertices[(i * floatsPerVertex) + 3] = (NewMapWidth * FullMapUPercent) + UVMapPos.getU(); //New U
        vertices[(i * floatsPerVertex) + 4] = (NewMapHeight * FullMapVPercent) + UVMapPos.getV();//New V
    }

    ObjectMesh.setVertices(vertices);
    ObjectMesh.setIndices(SourceIndices);

    return ObjectMesh;
}
person Paradox    schedule 30.06.2013