2011-12-12 32 views
0

我得到了我創建的廣告牌代碼(在別人的幫助下,和一個nehe教程),但似乎當我從0,0移動我的精靈時, 0它停止正常工作,例如,我越接近一個精靈,這個精靈在50,0,50就越偏向它。Billboarded sprite停止工作,如果從0,0,0移動

任何想法如何在不使用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(); 

    } 
+0

如果我正確讀取,當你真正吸取你的精靈,你的推薦並非基於截止目前精靈的位置,而只是它的大小+原點。那是對的嗎? – Sheriff

+0

是的,我發現當相機移動時,如果我使用精靈位置繪製精靈,精靈實際上會四處移動。 – CyanPrime

回答

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(); 
    } 
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模型視圖方法,它節省了計算量(和時間,如果你的視頻架構足夠接近你的處理器)。

我希望這會有所幫助。

編輯;我應該提到,但是我在這個項目中使用的佈局是讓實體類與模型類分開,所以每個實體都可以根據需要切換或共享模型;所以這是一個廣告牌模型類,而owner-> x/y/z指的是擁有該模型位置的實體。

+0

謝謝,但這似乎不適用於我。更多的信息在我編輯的第一篇文章中反映了試圖重新創建這些代碼。 – CyanPrime