'Avoid Z-fighting on 2D objects
I do display some 2D items (text + lines + arrows) in 3D scene. All items are selectable, after selection color is changed from white to blue. For some of items, I am struggling with Z-fighting. See pictures: selected item (blue) is covered by white arrow. At the second picture is white arrow hidden.
How and where in code should I move item closer to camera if item.isSelected()
? I can not use GL_POLYGON_OFFSET_LINE
, see glPolygonOffset() bugs with lines.
@Override
/**
* Render the MyObject
*/
public void render(GL gl, RenderParameters params, boolean selection)
{
//code, some checks
// Load the Transformation matrix of this TreeDataItem
Matrix4f trafo = item.getGlobalTrafo( );
if( trafo == null )
{
trafo = new Matrix4f();
Matrix4f.setIdentity(trafo);
}
// Get the PMI type if not done so yet
int nonTextDLSize = getNonTextDL().size();
int textDLSize = getTextDL().size();
if(pmiType == PmiType.PT_UNKNOWN)
{
// Check if it is a PMI with visu available
if(nonTextDLSize > 0 || textDLSize > 0)
pmiType = PmiType.PT_VISUAL;
else
{
Vector3f ptO = item.getTextOrigin();
if( ptO != null )
ptO = Matrix4f.transformPoint(trafo, ptO, null);
Vector3f vecX = item.getTextXAxis();
Vector3f vecY = item.getTextYAxis();
// Check if it is a Coordinate System PMI
pmiData = createCoordSystemPmiData(ptO, vecX, vecY);
if(pmiData != null)
pmiType = PmiType.PT_COORDSYSTEM;
else
// Nothing to be done for an unknown PMI
return;
}
}
// Set camera frustum
GL2 gl2 = (GL2)gl;
if(params == null)
return;
Camera camera = params.getCamera();
if(camera == null)
return;
if(!camera.hasFrustum())
{
BBox bbox = (pmiData != null) ? pmiData.getBBox(gl2, params) : item.getBBox();
if(bbox != null && trafo != null)
camera.addBBoxToBounding( bbox, trafo );
return;
}
//code, set preferences, e.g. color, line thickness
// Now draw the PMI visu
if (usePMIBeforeGeom) //Preference option settings if PMIs should be in front of geometry
gl2.glDisable(GL2.GL_DEPTH_TEST);
switch(pmiType)
{
case PT_COORDSYSTEM: // a Coordinate System PMI
//code
break;
case PT_VISUAL: // a PMI with visual representation stored
if(nonTextDLSize > 0) //those items should be fixed!!!!
{
FloatBuffer bf = ByteBuffer.allocateDirect( 4 * 16 ).order( ByteOrder.nativeOrder( ) ).asFloatBuffer( );
trafo.store( bf );
bf.rewind( );
gl2.glPushMatrix( );
gl2.glMultMatrixf( bf );
if (!selection && !(item.isHighlight()) && usePMIColorFromFile)
{
if (pmiGeomColor != null)
gl2.glColor4fv(pmiGeomColor);
}
gl2.glLineWidth( selection ? 4 : item.isHighlight() ? lineThickness * 2 : lineThickness );
for( Integer nonTextDL : getNonTextDL( ) )
{
gl2.glCallList( nonTextDL );
}
gl2.glPopMatrix( );
bf.clear( );
bf = null;
}
if(textDLSize > 0 )
{
//code
}
}
}
Solution 1:[1]
For drawing PMIs in front of geometry is used:
gl2.glDepthRange(k, k);
instead of gl2.glDisable(GL2.GL_DEPTH_TEST)
.
Then I can draw selected items in closer range:
if (item.isSelected() && usePMIBeforeGeom)
gl2.glDepthRange(SELECTION_DEPTH_RANGE, SELECTION_DEPTH_RANGE);
Finally I set range back.
gl2.glDepthRange(OpenGLRenderer.NEAR_DEPTH_RANGE, OpenGLRenderer.FAR_DEPTH_RANGE);
Code:
case PT_VISUAL: // a PMI with visual representation stored
if(nonTextDLSize > 0)
{
FloatBuffer bf = ByteBuffer.allocateDirect( 4 * 16 ).order( ByteOrder.nativeOrder( ) ).asFloatBuffer( );
trafo.store( bf );
bf.rewind( );
gl2.glPushMatrix( );
gl2.glMultMatrixf( bf );
if (!selection && !(item.isHighlight()) && usePMIColorFromFile)
{
if (pmiGeomColor != null)
gl2.glColor4fv(pmiGeomColor);
}
//gl2.glLineWidth( selection ? 4 : lineThickness );
if (item.isSelected() && usePMIBeforeGeom)
gl2.glDepthRange(SELECTION_DEPTH_RANGE, SELECTION_DEPTH_RANGE);
gl2.glLineWidth( selection ? 4 : item.isHighlight() ? lineThickness * 2 : lineThickness );
for( Integer nonTextDL : getNonTextDL( ) )
{
gl2.glCallList( nonTextDL );
}
if (item.isSelected())
gl2.glDepthRange(OpenGLRenderer.NEAR_DEPTH_RANGE, OpenGLRenderer.FAR_DEPTH_RANGE);
gl2.glPopMatrix( );
bf.clear( );
bf = null;
}
if(textDLSize > 0 )
{
//code
}
Constants:
private static final double SELECTION_DEPTH_RANGE = 0.000003;
public static final double NEAR_DEPTH_RANGE = 0.000004;
public static final double FAR_DEPTH_RANGE = 1.0;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |