Horde3D
http://horde3d.org/forums/

custom projection of text
http://horde3d.org/forums/viewtopic.php?f=2&t=1083
Page 1 of 1

Author:  jimbo [ 24.01.2010, 10:31 ]
Post subject:  custom projection of text

I would like to render the node names in the scene like billboards, so I've written a function to convert the object transformations to the screen. It seems to work but I'm not sure if this is correct:

Code:
void Application::renderNodeNames() {

// get view transformation
   const float* camTrans = 0;
   h3dGetNodeTransMats(_cam, 0, &camTrans);   
   Matrix4f camViewMat(Matrix4f(camTrans).inverted());

// get projection
   float projection[16];
   h3dGetCameraProjMat( _cam, projection );       
   Matrix4f projMat(projection);

   int cnt = h3dFindNodes(H3DRootNode, "", H3DNodeTypes::Undefined);
   for(int i = 0; i < cnt; i++) {
      int node = h3dGetNodeFindResult(i);

// get node name
      const char *name = h3dGetNodeParamStr(node, H3DNodeParams::NameStr);

// get node transform
      const float* nodeTrans = 0;
      h3dGetNodeTransMats(node, 0, &nodeTrans);   
      Matrix4f nodeMat( nodeTrans );

// project
      Matrix4f screenMat = projMat * camViewMat * nodeMat;
      //   why not?: Matrix4f screenMat = nodeMat * camViewMat * projMat;

// to 2D
      float w = screenMat.x[15];
      float x = screenMat.x[12] / w;
      float y = -screenMat.x[13] / w; // why negative?
      float z = screenMat.x[14];

// to screen (overlay coordinates)
      x= (x*0.5f) + 0.5f;
      y = (y*0.5f) + 0.5f;

      if(z > 0)
         h3dutShowText(name, x, y, 0.02f, 1.0f, 1.0f, 1.0f, _fontMatRes, 0);

      //      printf("pos: %f %f %f\n",x,y,z);
   }
}

Author:  marciano [ 24.01.2010, 17:40 ]
Post subject:  Re: custom projection of text

jimbo, your code looks ok to me.

jimbo wrote:
// project
Matrix4f screenMat = projMat * camViewMat * nodeMat;
// why not?: Matrix4f screenMat = nodeMat * camViewMat * projMat;

Vectors are multiplied from the right side, so the order projMat * camViewMat * nodeMat [* vector] is correct (nodeMat is applied to vector first, then viewMat and finally the projection).

jimbo wrote:
float y = -screenMat.x[13] / w; // why negative?

The origin of the overlay coordinate system is the upper left corner and the positive y axis points to the bottom of the screen. Usually, in maths you would have the positive y axis pointing to the top of the screen. However, I find the other convention more intuitive to work with when creating screen elements (since you read from top to bottom).

Here is a IMHO slightly clearer version of your code that I would propose to add to the wiki snippets later:

Code:
// Get camera view matrix
const float *camTrans;
h3dGetNodeTransMats( _cam, 0x0, &camTrans );
Matrix4f viewMat( Matrix4f( camTrans ).inverted() );

// Get camera projection matrix
float camProj[16];
h3dGetCameraProjMat( _cam, camProj );
Matrix4f projMat( camProj );

// Loop over all model nodes
int cnt = h3dFindNodes( H3DRootNode, "", H3DNodeTypes::Model );
for( int i = 0; i < cnt; ++i )
{
   // Get node name
   H3DNode node = h3dGetNodeFindResult( i );
   const char *name = h3dGetNodeParamStr( node, H3DNodeParams::NameStr );

   // Get node position
   const float *nodeTrans;
   h3dGetNodeTransMats( node, 0, &nodeTrans );
   Vec4f pos( nodeTrans[12], nodeTrans[13], nodeTrans[14], 1 );

   // Project
   pos = projMat * viewMat * pos;
   float x = pos.x / pos.w;
   float y = pos.y / pos.w;

   // Transform to overlay coordinates
   x = x * 0.5f + 0.5f;
   y = -y * 0.5f + 0.5f;

   // Show text (avoid back-projection)
   if( pos.w > 0 ) h3dutShowText( name, x, y, 0.02f, 1.0f, 1.0f, 1.0f, _fontMatRes, 0 );
}

Author:  jimbo [ 24.01.2010, 19:50 ]
Post subject:  Re: custom projection of text

Thanks for your help, looks nice and clean. For larger scenes I've added a bit of depth to the texts:
Code:

...

 y = -y * 0.5f + 0.5f;

float maxFontSize = 0.02f;
float minFontSize = 0.005f;

// Scale font a bit with z pos
 float fontSize = 0.2f / pos.z;

// Show text (avoid back-projection)
if( pos.w > 0 && fontSize >= minFontSize ) {
     if( fontSize >= maxFontSize ) fontSize = maxFontSize;
     h3dutShowText( name, x, y, fontSize, 1.0f, 1.0f, 1.0f, _fontMatRes, 0 );
}

Author:  marciano [ 27.01.2010, 22:35 ]
Post subject:  Re: custom projection of text

jimbo wrote:
For larger scenes I've added a bit of depth to the texts

Good idea :)

Page 1 of 1 All times are UTC + 1 hour
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/