Shading problem with Mirror in gp_Trsf

Hi
I've a problem with the SetMirror() method.
This method in the version void SetMirror(const gp_Ax1 &A1) works!

But I need to use the version : SetMirror (const gp_Ax2 &A2)

For Example :

BRepPrimAPI_MakeBox mkBox(gp_Pnt(100,100,100), 10, 10, 10);
TopoDS_Shape aShape= mkBox.Shape();
gp_Trsf aTrsf;
aTrsf.SetMirror(gp_Ax2(gp_Pnt(0,0,0), gp_Dir(1,0,0)));
TopLoc_Location newLocation(aTrsf);
aShape.Location(newLocation);

The shape takes the transformation (mirroring), but in the Viewer the Shading representation "change color" it becomes darkest (in shadow). See the screenshot :

http://img504.imageshack.us/img504/6135/mirrorproblem.jpg

Saretto

Saretto's picture

Nobody has this problem?

Fotis Sioutis's picture

Are you using the OCC provided visualization services ?

Saretto's picture

"Are you using the OCC provided visualization services ?"

Yes

Fotis Sioutis's picture

Then really I have no clue ...

but

your issue reminded me a problem i had in past when i was reading the occ provided mesh in order to pass it to my own renderer.The problem then, was that i did not translate the provided normal with the owner TopoDS_Face transformation.This issue created the exact same side-effect like your case.

Fotis

Saretto's picture

UP!

In OCC 6.4 is resolved this issue ????

sergey zaritchny's picture

Hi,
Unfortunately I can't reproduce the problem in Draw (in OCCT6.3.0 too).
Used below set of commands with 'mirror' command and
the next visualization in standard AISViewer in shading mode
gives correct result (as you may see it from the attached picture).

box b 100 100 100 10 10 10
copy b b2
tmirror b2 0 0 0 1 0 0
vinit
vdisplay b
# turn on shading mode for the first box 'b'
vdisplay b2
# turn on shading mode for the second box 'b2'
vfit
The resulting shape is attached.
Regards

Attachments: 
P G's picture

Looks fine with me too.
But 'tmirror' command uses the SetMirror function with gp_Ax1 object.
The author wants to use 'gp_Ax2' object.
regards
- PG

sergey zaritchny's picture

h'm!
Look, please at the BRepTest_BasicCommands.cxx.
Below is the extraction from the code:
...
if (!strcmp(a[0],"tmirror")) {
if (n < 8) return 1;
T.SetMirror(gp_Ax2(gp_Pnt(atof(a[n-6]),atof(a[n-5]),atof(a[n-4])),
gp_Vec(atof(a[n-3]),atof(a[n-2]),atof(a[n-1]))));
...
}
IMHO it is gp_Ax2.
Regards

Timo Roth's picture

The difference is that the Draw command "tmirror" uses BRepBuilderAPI_Transform whereas Saretto in his code just set the location of the shape.

The mirror transformation inverts the normals. Therefore, the shading isn't correct anymore.
Also scaling transformations affect the normals. Therefore, upscaling results in darker lighting, downscaling in lighter Lighting if you just set the shape to a new location.

BRepBuilderAPI_Transform::Perform checks for these cases and uses BRepTools_TrsfModification in these and setting the location of the shape in other cases like e.g. rotations. As far as I understand, BRepTools_TrsfModification creates a transformed copy of the shape and therefore the normals are recalculated.

I don't know where the normals are calculated or if it is possible to force their recalculation.

The same shading problems also occur when you set the transformation of an AIS_InteractiveObject via SetTransformation() to be a scale or mirror transformation after it has been displayed in an AIS_InteractiveContext. This seems to me like a bug. Using BRepBuilderAPI_Transform solves this problem but it is much slower.
A colleague of mine said that you can let OpenGL recalculate the normals automatically by
glEnable(GL_RESCALE_NORMAL);
Would this be a solution for all these problems?
According to http://www.opengl.org/discussion_boards/showthread.php/133406-GL_RESCALE... GL_RESCALE_NORMAL is contained in OpenGL 1.2.

Kind regards,
Timo

Timo Roth's picture

In order to reproduce the mirror problem with AIS_InteractiveObject.SetTransformation you can use the Import Export sample with the following modification:

void CColoredShapes::Display(Handle(AIS_InteractiveContext)& anAIScontext)
{
for ( TopoDS_ListIteratorOfListOfShape iter(m_shapeList); iter.More(); iter.Next() )
{
Handle(AIS_Shape) ais = new AIS_Shape(iter.Value());
anAIScontext->SetColor(ais, (Quantity_NameOfColor)m_colorMap.Find(iter.Value()));
anAIScontext->SetMaterial(ais, Graphic3d_NOM_GOLD, Standard_False);
anAIScontext->Display(ais, Standard_False);

// modification
anAIScontext->SetDisplayMode( ais, 1 );
Handle(Geom_Transformation) t = new Geom_Transformation;
t->SetMirror( gp_Ax2( gp_Pnt( 0, 0, 0 ), gp_Dir( 0, 0 ,1 )));
ais->SetTransformation(t, false, false );
}
}

When clicking on the "Create box" button, the shading of the created box doesn't work correctly.

Timo Roth's picture

I've added

if (myGlContext->core12 != NULL)
{
GLenum err_code;
glGetError();
glEnable(GL_RESCALE_NORMAL);
err_code = glGetError();
if (GL_NO_ERROR != err_code )
{
throw new std::exception("Could not enable GL_RESCALE_NORMAL. " + err_code);
}
}

at the end of the constructor of OpenGL_Window.
Now, the normals are correct when scaling, but the mirroring-problem remained.

Timo Roth's picture

In OCC 6.8.0 this problem was fixed by the following patch:

"25276: Lighting is broken if some kinds of transformation applied to a shape.

The problem caused by the fact that mirror transformation breaks the OpenGL lighting completely, has been solved by inverting the order of triangle vertices in mirrored mesh (triangulation). The mesh is mirrored if its transformation matrix determinant is less than 0.
The flag Mirrored is now stored in OpenGl_Structure to handle AIS object mirror transformations. If this flag is enabled, glFrontFace(GL_CW) is applied before calling draw.
Additionally GL_NORMALIZE mode is used when scale transform is applied in order to get rid of lighting issues."