Draw with OPEN GL in RhinoConduit

Hi, I would like to draw some geometries with Open GL inside Rhino conduit.
I wrote this sample of code in my CRhinoDisplayConduit event:

case CSupportChannels::SC_POSTDRAWOBJECTS:
{
        CRhinoDisplayEngine* p_engine = in_pipeline.Engine();

	ON_Xform modelViewMatrix  = p_engine->GetModelViewMatrix();

	glPushAttrib(GL_ALL_ATTRIB_BITS);
	glEnable(GL_LIGHTING_BIT);

	unsigned int i = 0;

	// Projection
	glMatrixMode(GL_PROJECTION);
	
	glLoadIdentity();

	ON_Xform cameraToClip = p_engine->CameraToClip();
	GLfloat cameraToClip16[16];
		
	// Convert 4x4 ON_XForm to m16 matrix
	for (int row = 0; row < 4; ++row){
		for (int col = 0; col < 4; ++col){
			cameraToClip16[i++] = cameraToClip[row][col];
		}
	}
	glLoadMatrixf(cameraToClip16);
		

	// ModelView
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

	GLfloat modelViewMatrix16[16];
	i = 0;

	// Convert 4x4 ON_XForm to m16 matrix
	for (int row = 0; row < 4; ++row){
		for (int col = 0; col < 4; ++col){
			modelViewMatrix16[i++] = modelViewMatrix[row][col];
		}
	}

	glLoadMatrixf(modelViewMatrix16);
	glPushMatrix();


	// draw line
	glDisable(GL_LIGHTING);
	glLineWidth(3.0f);
	glBegin(GL_LINES);	
	glColor3f(1.0f, 0.0, 0.0);
	glVertex3f(0.0f, 0.0f, 0.0f);
	glVertex3f(1.0f, 1.0f, 10.0f);
	glEnd();
	glEnable(GL_LIGHTING);

	glPopMatrix();    
	glPopAttrib();
}
break;

In Rhino I see my line in the correct position but when I move the point of view with mouse the line remain in the same position.
I think the problem is in the projection matrix because the model view values seems correct.
Does anyone know if is possible to use OpenGL in conduit in C++? With C# I have no problem to use it.

@stevebaer - is this something you can help with?

This is what Rhino does when running in legacy OpenGL mode. Typically we don’t set these matrices up anymore because they are instead passed to shaders as uniforms.

void CRhinoDisplayEngine_OGL::SetupGLMatrices(bool model, bool projection)
{
  if(projection)
  {
    ON_Xform  projectionMatrix;
    VP().GetXform(ON::camera_cs, ON::clip_cs, projectionMatrix);

    // GL's default z buffer likes z to increase as depth increases
    // (left handed camera).  Changing the default to a right
    // handed system seems to confuse some cheap accelerator cards.
    projectionMatrix.m_xform[2][0] = -projectionMatrix.m_xform[2][0];
    projectionMatrix.m_xform[2][1] = -projectionMatrix.m_xform[2][1];
    projectionMatrix.m_xform[2][2] = -projectionMatrix.m_xform[2][2];
    projectionMatrix.m_xform[2][3] = -projectionMatrix.m_xform[2][3];
    projectionMatrix.Transpose();


    if(projectionMatrix.IsValid())
    {
      ::glMatrixMode(GL_PROJECTION);
      ::glLoadMatrix(&projectionMatrix.m_xform[0][0]);
    }
  }

  if(model)
  {
    ::glMatrixMode(GL_MODELVIEW);

    ON_Xform model_view_matrix;
    VP().GetXform(ON::world_cs, ON::camera_cs, model_view_matrix);

    SetModelViewMatrix(model_view_matrix);

    model_view_matrix.Transpose();
    if(model_view_matrix.IsValid())
      ::glLoadMatrix(&model_view_matrix.m_xform[0][0]);
  }
}

3 Likes

Hi @stevebaer, thank you very much for your help. With your code everything works fine.
In any case before your answer yesterday I found a not so “elegant” solution like your. I computed by myself the modelView and projection matrix from camera frustum parameters. Like this:

// Every pipeline contains an instance of a display engine. 
// The engine is used to perform the low level drawing operations for the pipeline.
CRhinoDisplayEngine* p_engine = in_pipeline.Engine();

// calculate the frustum values from RhinoApi that will be used to construct the Projection matrix

ON_Viewport camera = in_pipeline.m_Camera;

GLfloat frustumLeft = camera.FrustumLeft();
GLfloat frustumRight = camera.FrustumRight();
GLfloat frustumBottom = camera.FrustumBottom();
GLfloat frustumTop = camera.FrustumTop();
GLfloat frustumNear = camera.FrustumNear();
GLfloat frustumFar = camera.FrustumFar();

GLfloat projection4x4[4][4], projection16[16];

// Perspective projection matrix
if (camera.IsPerspectiveProjection())
{
	GLfloat A = (frustumRight + frustumLeft) / (frustumRight - frustumLeft);
	GLfloat B = (frustumTop + frustumBottom) / (frustumTop - frustumBottom);
	GLfloat C = -(frustumFar + frustumNear) / (frustumFar - frustumNear);
	GLfloat D = -(2 * frustumFar * frustumNear) / (frustumFar - frustumNear);

	projection4x4[0][0] = (2 * frustumNear) / (frustumRight - frustumLeft);
	projection4x4[0][1] = 0.0;
	projection4x4[0][2] = A;
	projection4x4[0][3] = 0.0;

	projection4x4[1][0] = 0.0;
	projection4x4[1][1] = (2 * frustumNear) / (frustumTop - frustumBottom);
	projection4x4[1][2] = B;
	projection4x4[1][3] = 0.0;

	projection4x4[2][0] = 0.0;
	projection4x4[2][1] = 0.0;
	projection4x4[2][2] = C;
	projection4x4[2][3] = D;

	projection4x4[3][0] = 0.0;
	projection4x4[3][1] = 0.0;
	projection4x4[3][2] = -1;
	projection4x4[3][3] = 0.0;
}
// Ortho projection
else
{
	projection4x4[0][0] = 2 / (frustumRight - frustumLeft);
	projection4x4[0][1] = 0.0;
	projection4x4[0][2] = 0.0;
	projection4x4[0][3] = -(frustumRight + frustumLeft) / (frustumRight - frustumLeft);

	projection4x4[1][0] = 0.0;
	projection4x4[1][1] = 2 / (frustumTop - frustumBottom);
	projection4x4[1][2] = 0.0;
	projection4x4[1][3] = -(frustumTop + frustumBottom) / (frustumTop -frustumBottom);

	projection4x4[2][0] = 0.0;
	projection4x4[2][1] = 0.0;
	projection4x4[2][2] = -2 / (frustumFar + frustumNear);
	projection4x4[2][3] = -(frustumFar + frustumNear) / (frustumFar - frustumNear);

	projection4x4[3][0] = 0.0;
	projection4x4[3][1] = 0.0;
	projection4x4[3][2] = 0.0;
	projection4x4[3][3] = 1.0;
}


convM4x4toM16(projection4x4, projection16);

// model view matrix
ON_Xform worldToCamera = p_engine->WorldToCamera();

// Conversion to m16 values for OpenGL
GLfloat modelView4x4[4][4], modelView16[16];

for (int i = 0; i < 4;i++) {
	for (int j = 0; j < 4;j++) {
		modelView4x4[i][j] = worldToCamera[i][j];
	}
}

convM4x4toM16(modelView4x4, modelView16);
	
//  Set projection matrix
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(projection16);

// Set model view matrix
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(modelView16);
	

But of course I will use your version that is more readable.
thank you so much