سؤال

أحاول تطبيق نسيج على رباعي ، لكنني أحصل فقط على صندوق أسود بدلاً من الملمس. أنا أستخدم Devil لتحميل الصور من الملفات و OpenGL يقوم بالباقي.

هذا ما أفعله حتى الآن:

الفئة التالية تجريد تمثيل الشيطان لصورة ما.

#include "Image.h"

Image::Image()
{
    ilGenImages(1, &this->imageId);
}

Image::~Image()
{
    ilDeleteImages(1, &this->imageId);
}

ILint Image::getWidth()
{
    return this->width;
}

ILint Image::getHeight()
{
    return this->height;
}

ILint Image::getDepth()
{
    return this->depth;
}

ILint Image::getBpp()
{
    return this->bpp;
}

ILint Image::getFormat()
{
    return this->format;
}

ILubyte* Image::getData()
{
    return ilGetData();
}

bool Image::loadFromFile(wchar_t *filename)
{
    // Load the image from file.
    ILboolean retval = ilLoadImage(filename);
    if (!retval) {
        ILenum error;
        while ((error = ilGetError()) != IL_NO_ERROR) {
            wcout << error << L" " << iluErrorString(error);
        }
        return false;
    }

    this->width = ilGetInteger(IL_IMAGE_WIDTH);
    this->height = ilGetInteger(IL_IMAGE_HEIGHT);
    this->depth = ilGetInteger(IL_IMAGE_DEPTH);
    this->bpp = ilGetInteger(IL_IMAGE_BPP);
    this->format = ilGetInteger(IL_IMAGE_FORMAT);

    return true;
}

bool Image::convert()
{
    ILboolean retval = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
    if (!retval) {
        ILenum error;
        while ((error = ilGetError()) != IL_NO_ERROR) {
            wcout << error << L" " << iluErrorString(error);
        }
        return false;
    }
    return true;
}

bool Image::scale(ILint width, ILint height, ILint depth)
{
    ILboolean retval = iluScale(width, height, depth);
    if (!retval) {
        ILenum error;
        while ((error = ilGetError()) != IL_NO_ERROR) {
            wcout << error << L" " << iluErrorString(error);
        }
        return false;
    }
    return true;
}

void Image::bind()
{
    ilBindImage(this->imageId);
}

هذه الفئة تجريد تمثيل الملمس لـ OpenGL.

#include "Texture.h"

Texture::Texture(int width, int height)
{
    glGenTextures(1, &this->textureId);

    this->width = width;
    this->height = height;
}

int Texture::getWidth()
{
    return this->width;
}

int Texture::getHeight()
{
    return this->height;
}

void Texture::initFilter()
{
    // We will use linear interpolation for magnification filter.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // We will use linear interpolation for minifying filter.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

}

void Texture::unpack()
{
    glPixelStoref(GL_UNPACK_ALIGNMENT, 1);
}

void Texture::bind()
{
    glBindTexture(GL_TEXTURE_2D, this->textureId);
}

Texture::~Texture()
{
    glDeleteTextures(1, &this->textureId);
}

تحتوي الفئة التالية على عملية تحميل الملمس.

#include "TextureLoader.h"

void TextureLoader::initialize()
{
    if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION) {
        debug("Wrong DevIL version detected.");
        return;
    }

    ilInit();
    ilutRenderer(ILUT_OPENGL);
}

Texture* TextureLoader::createTexture(wchar_t *filename, Color *color)
{
    // Generate some space for an image and bind it.
    Image *image = new Image();
    image->bind();

    bool retval = image->loadFromFile(filename);
    if (!retval) {
        debug("Could not load image from file.");
        return 0;
    }

    retval = image->convert();
    if (!retval) {
        debug("Could not convert image from RGBA to unsigned byte");
    }

    int pWidth = getNextPowerOfTwo(image->getWidth());
    int pHeight = getNextPowerOfTwo(image->getHeight());
    int size = pWidth * pHeight;

    retval = image->scale(pWidth, pHeight, image->getDepth());
    if (!retval) {
        debug("Could not scale image from (w: %i, h: %i) to (w: %i, h: %i) with depth %i.", image->getWidth(), image->getHeight(), pWidth, pHeight, image->getDepth());
        return 0;
    }

    // Generate some space for a texture and bind it.
    Texture *texture = new Texture(image->getWidth(), image->getHeight());
    texture->bind();

    // Set the interpolation filters.
    texture->initFilter();

    // Unpack pixels.
    texture->unpack();

    ILubyte *imageData = image->getData();

    TextureLoader::setColorKey(imageData, size, new Color(0, 0, 0));
    TextureLoader::colorize(imageData, size, new Color(255, 0, 0));

    debug("bpp: %i", image->getBpp());
    debug("width: %i", image->getWidth());
    debug("height: %i", image->getHeight());
    debug("format: %i", image->getFormat());

    // Map image data to texture data.
    glTexImage2D(GL_TEXTURE_2D, 0, image->getBpp(), image->getWidth(), image->getHeight(), 0, image->getFormat(), GL_UNSIGNED_BYTE, imageData);

    delete image;

    return texture;
}

void TextureLoader::setColorKey(ILubyte *imageData, int size, Color *color)
{
    for (int i = 0; i < size * 4; i += 4)
    {
        if (imageData[i] == color->r && imageData[i + 1] == color->g && imageData[i + 2] == color->b)
        {
            imageData[i + 3] = 0;
        }
    }
}

void TextureLoader::colorize(ILubyte *imageData, int size, Color *color)
{
    for (int i = 0; i < size * 4; i += 4)
    {
        int rr = (int(imageData[i]) * int(color->r)) >> 8;
        int rg = (int(imageData[i + 1]) * int(color->g)) >> 8;
        int rb = (int(imageData[i + 2]) * int(color->b)) >> 8;
        int fak = int(imageData[i]) * 5 - 4 * 256 - 138;

        if (fak > 0)
        {
            rr += fak;
            rg += fak;
            rb += fak;
        }

        rr = rr < 255 ? rr : 255;
        rg = rg < 255 ? rg : 255;
        rb = rb < 255 ? rb : 255;

        imageData[i] = rr > 0 ? (GLubyte) rr : 1;
        imageData[i + 1] = rg > 0 ? (GLubyte) rg : 1;
        imageData[i + 2] = rb > 0 ? (GLubyte) rb : 1;
    }
}

الفئة الأخيرة تفعل الرسم.

#include "Texturizer.h"

void Texturizer::draw(Texture *texture, float x, float y, float angle)
{
    // Enable texturing.
    glEnable(GL_TEXTURE_2D);

    // Bind the texture for drawing.
    texture->bind();

    // Enable alpha blending.
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    int width = texture->getWidth();
    int height = texture->getHeight();

    // Create centered dimension vectors.
    b2Vec2 vertices[4];
    vertices[0] = 0.5f * b2Vec2(- width, - height);
    vertices[1] = 0.5f * b2Vec2(+ width, - height);
    vertices[2] = 0.5f * b2Vec2(+ width, + height);
    vertices[3] = 0.5f * b2Vec2(- width, + height);

    b2Mat22 matrix = b2Mat22();
    matrix.Set(angle);

    glBegin(GL_QUADS);
    for (int i = 0; i < 4; i++) {
        float texCoordX = i == 0 || i == 3 ? 0.0f : 1.0f;
        float texCoordY = i < 2 ? 0.0f : 1.0f;
        glTexCoord2f(texCoordX, texCoordY);

        // Rotate and move vectors.
        b2Vec2 vector = b2Mul(matrix, vertices[i]) + meter2pixel(b2Vec2(x, y));
        glVertex2f(vector.x, vector.y);
    }
    glEnd();

    glDisable(GL_BLEND);
    glDisable(GL_TEXTURE_2D);
}

أخيرًا وليس آخرًا ، تهيئة الطريقة التالية OpenGL (وتؤدي إلى تهيئة الشيطان):

void GraphicsEngine::initialize(int argc, char **argv)
{
    // Initialize the window.
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
    glutInitWindowSize(WIDTH, HEIGHT);

    // Set shading model.
    glShadeModel(GL_SMOOTH);

    // Create the window.
    this->mainWindow = glutCreateWindow(TITLE);

    // Set keyboard methods.
    glutKeyboardFunc(&onKeyDownCallback);
    glutKeyboardUpFunc(&onKeyUpCallback);
    glutSpecialFunc(&onSpecialKeyDownCallback);
    glutSpecialUpFunc(&onSpecialKeyUpCallback);

    // Set mouse callbacks.
    glutMouseFunc(&onMouseButtonCallback);
#ifdef FREEGLUT
    glutMouseWheelFunc(&onMouseWheelCallback);
#endif
    glutMotionFunc(&onMouseMotionCallback);
    glutPassiveMotionFunc(&onMousePassiveMotionCallback);

    // Set display callbacks.
    glutDisplayFunc(&onDrawCallback);
    glutReshapeFunc(&onReshapeCallback);

    // Set a timer to control the frame rate.
    glutTimerFunc(FRAME_PERIOD, onTimerTickCallback, 0);

    // Set clear color.
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

    Camera::getInstance()->subscribe(this);

    // Initialize texture loader.
    TextureLoader::initialize();
}

الصورة التي أستخدمها بالفعل في مشروع OpenGL/Devil آخر ، لذلك لا يمكن أن تكون مصدر المشكلة.

يتم إنشاء الملمس داخل كل فصل يمثل كائنًا عالميًا (إنها لعبة ...). وتسمى الشخصية blobby وهنا أهم أجزاء تنفيذها:

#include "Blobby.h"

Blobby::Blobby()
{
    this->isJumping = false;
    this->isRotating = false;
    this->isWalking = false;
    this->isDucking = false;
    this->isStandingUp = false;
    this->isOnGround = false;
    this->isTouchingWall = false;
    this->angle = 0;
    this->direction = DIRECTION_UNKNOWN;
    this->wallDirection = DIRECTION_UNKNOWN;

    // Create a red blobby texture.
    this->texture = TextureLoader::createTexture(L"D:/01.bmp", new Color(255, 0, 0));

    ContactListener::getInstance()->subscribe(this);
}

void Blobby::draw()
{
    GraphicsEngine::drawString(35, 40, "isOnGround     = %s", this->isOnGround ? "true" : "false");
    GraphicsEngine::drawString(35, 55, "inJumping      = %s", this->isJumping ? "true" : "false");
    GraphicsEngine::drawString(35, 70, "isRotating     = %s", this->isRotating ? "true" : "false");
    GraphicsEngine::drawString(35, 85, "isTouchingWall = %s (%i)", this->isTouchingWall ? "true" : "false", this->wallDirection);

    Texturizer::draw(this->texture, this->getBody(0)->GetPosition().x, this->getBody(0)->GetPosition().y, this->getBody(0)->GetAngle());

    AbstractEntity::draw(); // draws debug information... not important
}

يستدعي رد اتصال مؤقت OpenGL طريقة خطوة تنتهي هنا:

void Simulator::step()
{
    // Update physics.
    this->gameWorld->step();

    b2Vec2 p = Camera::convertWorldToScreen(meter2pixel(this->cameraBlobby->getBody(0)->GetPosition().x), 300.0f);
    if (p.x < 300) {
        Camera::getInstance()->setViewCenter(Camera::convertScreenToWorld(400 - (300 - int(p.x)), 300));
    } else if (p.x > 500) {
        Camera::getInstance()->setViewCenter(Camera::convertScreenToWorld(400 + (int(p.x) - 500), 300));
    }


    for (unsigned int i = 0; i < this->gameWorld->getEntityCount(); i++) {
        IEntity *entity = this->gameWorld->getEntity(i);
        entity->draw();
    }
}

Ientity هي فئة افتراضية خالصة (IE واجهة) ، يستجيب هذه الواجهة ويضيف الطرق العالمية. ويرث Blobby من الاستجواب ويضيف إجراءات خاصة لهذا الكائن العالمي.

تعديل:لقد قمت بتحميل إصدار أحدث من الكود (تبعيات المشروع بأكمله) هنا:http://upload.visusnet.de/uploads/blobbywarriors-rev19.zip (~ 9.5 ميغابايت)

هل كانت مفيدة؟

المحلول

لست على دراية بالشيطان ، لكن ... هل تقدم اللون المنتشر المناسب لعملياتك؟ إذا تم تمكين الإضاءة ، هل هناك بعض الأضواء التي تشير إلى الربع؟ هل تنظر الكاميرا إلى أمامي جانب الربع؟

تعديل:

لقد حصلت على خطأ في الكود ، ولكن ليس الشخص الذي نشرته هنا ، ولكن في الإصدار في الأرشيف الذي ربطته.

أنت أتصل glColor3i(255, 255, 255), ، ويضع اللون المنتشر إلى (تقريبًا) أسود كما هو متوقع. glColor3i يفعل ليس اقبل قيم الألوان في نطاق الهدف (الحساب أو الإطار). يتم تحجيم القيم المحتملة إلى نطاق كامل من int يكتب. هذا يعني أن القيمة القصوى (1.0 في العوام) ممثلة بـ MAX_INT (2،147،483،647) ، 0 هي 0 ، و -1.0 IS MIN_INT (-2،147،483،648). ال 255 تمثل القيمة التي قدمتها حوالي 0.000000118 ، وهو ما يقرب من الصفر.

أعتقد أنك قصدت واحدة من أشكال (مكافئة تمامًا):

glColor3f(1.0, 1.0, 1.0), glColor3ub(255, 255, 255),

glColor3i(2147483647, 2147483647, 2147483647).

نصائح أخرى

ماذا يوجد في مصفوفة B2MAT22؟ هل يمكن أن يكون الضرب من خلال هذه المصفوفة يتسبب في رسم رؤوسك بترتيب في اتجاه عقارب الساعة ، لأنني أعتقد في هذه الحالة أن ظهر مربعك سيواجهك ، وقد يكون الملمس على الجانب الآخر (غير المرئي).

لقد واجهت مشكلة كهذه منذ وقت طويل ، أعتقد أنها كانت مشكلة في أبعاد الملمس التي لا تكون أساسية من 2 (128x128 ، 512x512 ، إلخ). أنا متأكد من أنهم قد أصلحوا ذلك الآن ، لكن قد يكون ذلك شيئًا يجب تجربته.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top