User:Regina/ODF 3D Problems

This is a scratch-pad about the implementation of 3D.

General
The sections have following structure:

How it works for the user. This is mostly about what the user sees and what happens, where the items are located in the "3D Effects" dialog, and about the help texts.

Internal Properties. Found with search for words that start with "D3D", and mapping in /core/include/svx/unoshprp.hxx and in /core/include/editeng/unoprnms.hxx.

File Format. I have used the file /core/xmloff/source/draw/sdpropls.cxx and have examined example files.

ODF. How ODF describes it. All citations are from http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html

Problems. Which problems I see.

Feel free to add your ideas and annotations to any part.

Backface Culling
How it works for the user. Button "Double-Sided" in Tab Geometry of the "3D Effects" dialog.

Short tip Double-Sided, extended tip Closes the shape of a 3D object that was created by extruding a freeform line (Convert - To 3D).

If the button is not pressed, then "backface-culling" is enabled. Then the filling is not drawn, fat strokes are drawn. So the user sees the backface as 100% transparent, but still sees the edges.

Internal Properties. D3DDoubleSided, UNO_NAME_3D_DOUBLE_SIDED, SDRATTR_3DOBJ_DOUBLE_SIDED

File Format. dr3d:backface-culling with values enabled and disabled

It is used as attribute in  of the automatic-style of the object.

Button "Double-Sided" pressed writes value disabled.

Button "Double-Sided" not pressed writes value enabled</tt>.

ODF. 20.69

The dr3d:backface-culling</tt> attribute specifies whether backface culling is enabled. The defined values for the dr3d:backface-culling</tt> attribute are: disabled</tt>: backface culling is not enabled. enabled</tt>: backface culling is enabled. The dr3d:backface-culling</tt> attribute is usable with the element: <style:graphic-properties> </tt>

Problems


 * The term "backface" is not defined in ODF 20.69. You find a definition for "front side" in section 20.83, "The front side of the plane is the one the normal points away from."
 * The term "culling" is not defined in ODF. I have not found any other standard, which describes it. Other application work like this: If "backface culling" is enabled, then even in cases a beholder looks at a backface it is not drawn. "Backface culling" is used to avoid calculations for faces, which are inside a closed solid.
 * It is not specified, whether strokes are treated separate and drawn, or are considered a part of the plane and not drawn.
 * The extended tip in LibreOffice does not fit to the common meaning of "backface culling".
 * In ODF it is not specified, how backface culling reacts on inverse normals.

Invert Normals
How it works for the user. Button "Invert Normals" in Tab "Geometry" of "3D Effects" dialog. Short tip Invert Normals, extended tip Inverts the light source.

Toggling button between "pressed" and "not pressed" does not change, which faces are drawn. It toggles, from which light it is lit. If the button is "not pressed" the faces is lit from the light source, if it is "pressed" it is lit from "Ambient light". This corresponds to the help text for "Double-sided Illumination",

''Lights the object from the outside and the inside. To use an ambient light source, click this button, and then click the Invert Normals button.''

Internal Properties. D3DNormalsInvert, UNO_NAME_3D_NORMALS_INVERT, SDRATTR_3DOBJ_NORMALS_INVERT

File Format. dr3d:normal-direction</tt> with values normal</tt> and inverse</tt>

Button "Invert Normals" pressed writes the value normal</tt>.

Button "Invert Normals" not pressed writes the value inverse</tt>.

The calculation of a normal is done in method :getNormal</tt> of class CoordinateDataArray3D</tt> in /core/basegfx/source/polygon/b3dpolygon.cxx</tt>. First the point S with smallest x-value is searched; if equal in x, smallest y-value and then smallest z-value is used. Then the next point N and the previous point P is taken, where the order for 'next' and 'previous' is given by the order in which the points are noted in the array. The normal is the cross-product of first vector SP, second vector SN, and then length normalizes to 1.

Example. A polyline is drawn with points (0cm|0cm), (0cm|2cm) and (3cm|2cm), in this order. After converting to a 3D extrusion object, you get svg:viewBox="0 -2000 3000 2000"</tt> and svg:d="M0 0v-2000h3000"</tt>. LibreOffice uses viewBox and path values as if they have the unit 1/100mm. LibreOffice considers the path to be on the XY-plane and so it has the 3D-Points (0|0|0), (0|-2000|0) and (3000|-2000|0). These points results in a normal vector of (-1|0|0). With the default view of x-axis right and y-axis up this would mean, that the user looks on to the backface of the shape, in case the normal is not inverted. There are some places in the code, where the normal is inverted intentionally, I yet need to investigate why.

ODF 20.80

The <tt>dr3d:normals-direction</tt> attribute specifies which sides of a 3D object's planes are displayed if the <tt>dr3d:lighting-mode</tt> attribute has the value 'standard'.

The defined values for the <tt>dr3d:normals-direction</tt> attribute are:

<tt>inverse</tt>: only the back sides of planes are displayed.

<tt>normal</tt>: only the front sides of planes are displayed.

The front side of the plane is the one the normal points away from.

The <tt>dr3d:normals-direction</tt> attribute has no effect if the <tt>dr3d:lighting-mode</tt> attribute has the value <tt>double-sided</tt>.

The <tt>dr3d:normals-direction</tt> attribute is usable with the element <tt><style:graphic-properties></tt>.

Problems


 * The value in file format is opposite to the UI.
 * The implementation does not consider inverse normals for backface culling
 * ODF does not specify the relation between inverse normals and backface culling.
 * The extended tip is nonsense. How can you invert a light _source_? And 'inverse normals' is a property of the single object and may not effect a light, because that is part of the whole scene.
 * The specification refers to an attribute <tt>dr3d:lighting-mode</tt> with values <tt>standard</tt> and <tt>double-sided</tt>. I find no implementation for it.

Doubles Sided Illumination
How it works for the user. It is the button "Double-Sided Illumination" in section "Normals" on the "Geometry"-tab of the "3D-Effects" dialog. This setting has only an effect, if backface culling is disabled, so that front and back face are drawn in any case.

If backface culling is disabled, I expect the following behavior, which was the behavior in StarOffice 5.2


 * If the button "Double-Sided Illumination" is pressed, a back face is handled the same as a front face. The material is considered solid in addition, that means, that a side is only lit, if the ray light falls onto the side from the direction of the beholder. In this case specularity is used. If the ray light comes from the opposite side and hits the beholder, then the object side on which the beholder looks is in the shadow and only lit by the ambient light.


 * If the button "Double-Sided Illumination" is not pressed, a back face is not lit by a direct ray light. But the material is not really solid. If the ray light hits the beholder and the beholder look onto a back face of the object, then the ray light hits the front face of the object. In this case the beholder sees some light coming through the material. It has no specularity, it looks more like light through a opal glass.


 * If the button "Invert Normals" is pressed, then back face and front face change their role in regard to lighting.

If these hypotheses are correct, then the case, the button "Double-Sided Illumination" is pressed and button "Inverse Normals" is pressed, is handled wrongly. Because a pressed button "Double-Sided Illumination" means, that back face and front face are handled the same, the lighting should be independent of the button "Invert Normals", but currently it looks as if the source of the ray light has moved to the opposite side of the 3D space.

Internal Properties. D3DSceneTwoSidedLighting, UNO_NAME_3D_SCENE_TWO_SIDED_LIGHTING, SDRATTR_3DSCENE_TWO_SIDED_LIGHTING

File format. <tt>dr3d:lighting-mode</tt> with values <tt>true</tt> and <tt>false</tt>.

It is an attribute of the 3D-scene, not of the single object. It is a true attribute not a graphic-property.

Button "Double-Sided Illumination" pressed writes value <tt>true</tt>.

Button "Double-Sided Illumination" not pressed writes value <tt>false</tt>.

ODF 19.99.1 General

The dr3d:lighting-mode attribute specifies the use of lighting in three-dimensional scenes

ODF 9.99.3 <dr3d:scene>

The dr3d:lighting-mode attribute specifies whether lighting is used in a three-dimensional scene.

The defined values for the dr3d:lighting-mode attribute are:

<tt>false</tt>: lighting is not used.

<tt>true</tt>: lighting is used.

Problems
 * The button "Double-Sided Illumination" is arranged together with buttons, which effect only a single object. But the button "Double-Sided Illumination" effects the whole scene and should therefore be separated.
 * It is not clear in ODF, what "lighting is used" means. One understanding might be, that in case lighting-mode is false, each 3D-object in the scene is rendered in its own color, without any part to be more or less shadowed or lighted. Such rendering might be used in charts, if you only want a third dimension, without realistic 3D-objects. But that would be very different from what LibreOffice does actually. My suggestion would be, to deprecate this attribute for 3D-scene and keep it only for chart:plot-area. Then a new attribute would be needed, that describes the actual rendering in LibreOffice.
 * There exists a graphic-property for single objects with the same name but different value type.