如果从0,0,0移动,广告牌精灵将停止工作

时间:2011-12-12 21:16:20

标签: java math opengl

我得到了我创建的广告牌代码(在其他人的帮助下,以及一个教程),但似乎当我从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();

    }

编辑:根据Knetic的答案尝试了这段代码,但它甚至没有将精灵旋转到相机上。这是我使用的代码:

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 :(得分:0)

我挖了一个我的旧项目,这个项目有广告牌,我的解决方案就是这个。

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模型视图方法的人,这样可以节省计算(如果您的视频架构足够接近您的处理器,那么会节省时间) )。

我希望这会有所帮助。

EDIT;我应该提到,但我在这个项目中使用的布局是将实体类与模型类分开,因此每个实体都可以根据需要切换或共享模型;所以这是一个广告牌模型类,所有者 - &gt; x / y / z指的是拥有该模型位置的实体。

答案 1 :(得分: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();
            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();
    }