Спрайты с рекламными щитами перестают работать, если перемещены с 0,0,0 - PullRequest
0 голосов
/ 13 декабря 2011

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

Есть идеи, как правильно сделать рекламный щит для спрайтов, если не на 0,0,0?

Вот код:

public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float r, float g, float b, int sprWidth, int sprHeight){
         // store the current model matrix
        GL11.glPushMatrix();

            // bind to the appropriate texture for this sprite
            texture.bind();
            Vector3f look = new Vector3f(0,0,0);
            Vector3f.sub(player.pos, sprPos, look);
            look.normalise();

            Vector3f right = new Vector3f(0,0,0);
            Vector3f.cross(new Vector3f(0,1,0) /* <-- default up vector */, look, right);
            right.normalise();

            Vector3f up = new Vector3f(0,0,0);
            Vector3f.cross(look, right, up);
            up.normalise();


            Matrix4f m = new Matrix4f();
            m.m00 = right.x;
            m.m01 = right.y;
            m.m02 = right.z;
            m.m03 = 0;

            m.m10 = up.x;
            m.m11 = up.y;
            m.m12 = up.z;
            m.m13 = 0;

            m.m20 = look.x;
            m.m21 = look.y;
            m.m22 = look.z;
            m.m23 = 0;

            m.m30 = sprPos.x;
            m.m31 = sprPos.y;
            m.m32 = sprPos.z;
            m.m33 = 1;

            java.nio.FloatBuffer fb = BufferUtils.createFloatBuffer(32);
            m.store(fb);
            fb.flip();
            GL11.glMultMatrix(fb);

            // draw a quad textured to match the sprite
            GL11.glBegin(GL11.GL_QUADS);
                GL11.glTexCoord2f(0,0);                                     GL11.glVertex3f( - (sprWidth/2), (sprHeight/2), 0);    // Top left Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), 0);                   GL11.glVertex3f( + (sprWidth/2), (sprHeight/2), 0);  // Top right Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f( + (sprWidth/2), -(sprHeight/2), 0);   // Bottom right Of The Quad (Left)
                GL11.glTexCoord2f(0, texture.getHeight());                  GL11.glVertex3f( - (sprWidth/2), -(sprHeight/2), 0);   // Bottom left Of The Quad (Left)
            GL11.glEnd();

        // restore the model view matrix to prevent contamination
        GL11.glPopMatrix();

    }

Редактировать: пробовал этот код на основе ответа Кнетика, но он даже не поворачивал спрайтов к камере. Вот код, который я использовал:

public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float r, float g, float b, int sprWidth, int sprHeight){
         // store the current model matrix
        GL11.glPushMatrix();
            FloatBuffer tempViewBuf = BufferUtils.createFloatBuffer(16);

            GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, tempViewBuf);

            float[] tempView = new float[16];

            for(int i = 0; i < 16; i++){
                tempView[i] = tempViewBuf.get(i);
            }

            float[] modelView = new float[6];

            modelView[0] = tempView[0] - tempView[1];
            modelView[1] = tempView[0] + tempView[1];

            modelView[2] = tempView[4] - tempView[5];
            modelView[3] = tempView[4] + tempView[5];

            modelView[4] = tempView[8] - tempView[9];
            modelView[5] = tempView[8] + tempView[9];

            // bind to the appropriate texture for this sprite
            texture.bind();

            // draw a quad textured to match the sprite
            GL11.glBegin(GL11.GL_QUADS);
                GL11.glTexCoord2f(0,0);                                     GL11.glVertex3f( - (sprWidth/2) + modelView[1], (sprHeight/2) + modelView[3], 0 + modelView[5]);    // Top left Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), 0);                   GL11.glVertex3f( + (sprWidth/2) + modelView[0], (sprHeight/2) + modelView[2], 0 + modelView[4]);  // Top right Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f( + (sprWidth/2) + modelView[1], -(sprHeight/2)+ modelView[3], 0 + modelView[5]);   // Bottom right Of The Quad (Left)
                GL11.glTexCoord2f(0, texture.getHeight());                  GL11.glVertex3f( - (sprWidth/2) + modelView[0], -(sprHeight/2)+ modelView[2], 0 + modelView[4]);   // Bottom left Of The Quad (Left)
            GL11.glEnd();

        // restore the model view matrix to prevent contamination
        GL11.glPopMatrix();

    }

Ответы [ 2 ]

0 голосов
/ 14 декабря 2011

Просто нужно было использовать другой способ билбординга:

public void drawBillBoardSprite(Texture texture, Vector3f sprPos, float r, float g, float b, int sprWidth, int sprHeight){
         // store the current model matrix
        GL11.glPushMatrix();
            GL11.glTranslatef(sprPos.x, 0, sprPos.z);
            // bind to the appropriate texture for this sprite
            texture.bind();

            FloatBuffer modelview = BufferUtils.createFloatBuffer(16);

            // get the current modelview matrix
            GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelview);

            // Note that a row in the C convention is a column 
            // in OpenGL convention (see the red book, pg.106 in version 1.2)
            // right vector is [1,0,0]  (1st column)
            // lookAt vector is [0,0,1] (3d column)
            // leave the up vector unchanged (2nd column)
            // notice the increment in i in the first cycle (i+=2)
            for(int i=0; i<3; i+=2 ) 
                for(int j=0; j<3; j++ ) {
                    if ( i==j )
                        modelview.put(i*4+j, 1.0f);
                    else
                        modelview.put(i*4+j, 0.0f);
                }

            // set the modelview matrix
            GL11.glLoadMatrix(modelview);

            // draw a quad textured to match the sprite
            GL11.glBegin(GL11.GL_QUADS);
                GL11.glTexCoord2f(0,0);                                     GL11.glVertex3f( - (sprWidth/2), (sprHeight/2), 0);    // Top left Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), 0);                   GL11.glVertex3f( + (sprWidth/2), (sprHeight/2), 0);  // Top right Of The Quad (Left)
                GL11.glTexCoord2f(texture.getWidth(), texture.getHeight()); GL11.glVertex3f( + (sprWidth/2), -(sprHeight/2), 0);   // Bottom right Of The Quad (Left)
                GL11.glTexCoord2f(0, texture.getHeight());                  GL11.glVertex3f( - (sprWidth/2), -(sprHeight/2), 0);   // Bottom left Of The Quad (Left)
            GL11.glEnd();

        // restore the model view matrix to prevent contamination
        GL11.glPopMatrix();
    }
0 голосов
/ 13 декабря 2011

Я выкопал мой старый проект, в котором были частицы с биллбордом, и мое решение было таким:

static float[] tempView;

// ...additional render stuff up here

// If there's anything that needs billboarding
if(getParticleTop() > 0)
{
glGetFloatv(GL_MODELVIEW_MATRIX, tempView);

modelView[0] = tempView[0] - tempView[1];
modelView[1] = tempView[0] + tempView[1];

modelView[2] = tempView[4] - tempView[5];
modelView[3] = tempView[4] + tempView[5];

modelView[4] = tempView[8] - tempView[9];
modelView[5] = tempView[8] + tempView[9];

// ... render each particle
}

И в отдельных частицах рендерится

float* modelView = renderer->getModelView();

glBegin(GL_QUADS);
{
glTexCoord2f(0, 1);
glVertex3f(owner->x - (modelView[1] * scale), owner->y - (modelView[3] * scale), owner->z - (modelView[5] * scale));

glTexCoord2f(0, 0);
glVertex3f(owner->x + (modelView[0] * scale), (owner->y + modelView[2] * scale), owner->z + (modelView[4] * scale));

glTexCoord2f(1, 0);
glVertex3f(owner->x + (modelView[1] * scale), owner->y + (modelView[3] * scale), owner->z + (modelView[5] * scale));

glTexCoord2f(1, 1);
glVertex3f(owner->x - (modelView[0] * scale), owner->y + (modelView[2] * scale), owner->z - (modelView[4] * scale));
}
glEnd();

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

Я помню, как изучал учебник NeHe и нашел то же самоепроблема, это решение отказалось от NeHe и погуглило кого-то еще, кто предложил метод GL ModelView, который экономит вычисления (и время, если ваша видео архитектура достаточно близка к вашему процессору).

Надеюсь, это поможет.

РЕДАКТИРОВАТЬ;Я должен был упомянуть, но компоновка, которую я использовал в этом проекте, заключалась в том, чтобы иметь класс сущностей, отдельный от классов моделей, чтобы каждая сущность могла переключаться или совместно использовать модели по мере необходимости;так что это класс модели рекламного щита, а owner-> x / y / z относится к объекту, которому принадлежит позиция этой модели.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...