From 818368d6862e92f4c16ac03e0e9a63f9e44638b5 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 29 Nov 2009 10:25:24 +0000 Subject: [PATCH] Add better cylindrical billboard algorithm --- src/Billboard.cpp | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Billboard.cpp b/src/Billboard.cpp index 91816d9..f001a2b 100644 --- a/src/Billboard.cpp +++ b/src/Billboard.cpp @@ -166,9 +166,9 @@ public: void CylindricalBillboard::realRender() const { // Based on code from - // http://www.lighthouse3d.com/opengl/billboarding/index.php?billCheat1 - - float modelview[16]; + // http://www.lighthouse3d.com/opengl/billboarding/index.php?billCyl + Vector lookAt, objToCamProj, upAux, objToCam; + float angleCosine; glPushAttrib(GL_DEPTH_BUFFER_BIT); glDepthMask(GL_FALSE); @@ -177,17 +177,34 @@ void CylindricalBillboard::realRender() const translate(); - glGetFloatv(GL_MODELVIEW_MATRIX , modelview); + // objToCamProj is the vector in world coordinates from the + // local origin to the camera projected in the XZ plane + objToCamProj = makeVector( + cameraPosition.x - position.x, + 0.0f, + cameraPosition.z - position.z); + + // This is the original lookAt vector for the object + // in world coordinates + lookAt = makeVector(0.0f, 0.0f, 1.0f); - for (int i = 0; i < 3; i += 2) - for (int j = 0; j < 3; j++) { - if (i == j) - modelview[i*4+j] = 1.0; - else - modelview[i*4+j] = 0.0; - } + // normalize both vectors to get the cosine directly afterwards + objToCamProj.normalise(); - glLoadMatrixf(modelview); + // easy fix to determine wether the angle is negative or positive + // for positive angles upAux will be a vector pointing in the + // positive y direction, otherwise upAux will point downwards + // effectively reversing the rotation. + upAux = lookAt * objToCamProj; + + // compute the angle + angleCosine = lookAt.dot(objToCamProj); + + // perform the rotation. The if statement is used for stability reasons + // if the lookAt and objToCamProj vectors are too close together then + // |angleCosine| could be bigger than 1 due to lack of precision + if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) + glRotatef(acos(angleCosine)*180/3.14, upAux.x, upAux.y, upAux.z); drawTextureQuad(); -- 2.39.2