Methods of NCollection_Vec3 and NCollection_Vec3 that returned reference to internal buffer as vector of lower dimension (non-const xy(), xyz() etc.) are eliminated.
Use of these methods could led to generation of incorrect binary code by GCC.
Instead added new method SetValues() accepting vector of lower dimension and additional value.
DRAW test command QANColTestVec4 reproducing one situation where the bug occurs is added, along with a test case.
v[2] = theZ;
}
- //! Constructor from 2-components vector.
- explicit NCollection_Vec3 (const NCollection_Vec2<Element_t>& theVec2)
+ //! Constructor from 2-components vector + optional 3rd value.
+ explicit NCollection_Vec3 (const NCollection_Vec2<Element_t>& theVec2, Element_t theZ = Element_t(0))
{
v[0] = theVec2[0];
v[1] = theVec2[1];
- v[2] = Element_t(0);
+ v[2] = theZ;
}
//! Assign new values to the vector.
v[2] = theZ;
}
+ //! Assign new values to the vector.
+ void SetValues (const NCollection_Vec2<Element_t>& theVec2, Element_t theZ)
+ {
+ v[0] = theVec2.x();
+ v[1] = theVec2.y();
+ v[2] = theZ;
+ }
+
//! Alias to 1st component as X coordinate in XYZ.
Element_t x() const { return v[0]; }
//! Alias to 3rd component as BLUE channel in RGB.
Element_t& b() { return v[2]; }
- //! @return XY-components modifiable vector
- NCollection_Vec2<Element_t>& xy()
- {
- return *((NCollection_Vec2<Element_t>* )&v[0]);
- }
-
- //! @return YZ-components modifiable vector
- NCollection_Vec2<Element_t>& yz()
- {
- return *((NCollection_Vec2<Element_t>* )&v[1]);
- }
-
//! Check this vector with another vector for equality (without tolerance!).
bool IsEqual (const NCollection_Vec3& theOther) const
{
}
//! Compute per-component division by scale factor.
- NCollection_Vec3 operator/ (const Element_t theInvFactor)
+ NCollection_Vec3 operator/ (const Element_t theInvFactor) const
{
NCollection_Vec3 aResult (*this);
return aResult /= theInvFactor;
v[2] = v[3] = Element_t (0);
}
- //! Constructor from 3-components vector.
- explicit NCollection_Vec4(const NCollection_Vec3<Element_t>& theVec3)
+ //! Constructor from 3-components vector + optional 4th value.
+ explicit NCollection_Vec4(const NCollection_Vec3<Element_t>& theVec3, const Element_t theW = Element_t(0))
{
std::memcpy (this, &theVec3, sizeof(NCollection_Vec3<Element_t>));
- v[3] = Element_t (0);
- }
-
- //! Constructor from 3-components vector + alpha value.
- explicit NCollection_Vec4(const NCollection_Vec3<Element_t>& theVec3,
- const Element_t theAlpha) {
- std::memcpy (this, &theVec3, sizeof(NCollection_Vec3<Element_t>));
- v[3] = theAlpha;
+ v[3] = theW;
}
//! Assign new values to the vector.
v[3] = theW;
}
+ //! Assign new values as 3-component vector and a 4-th value.
+ void SetValues (const NCollection_Vec3<Element_t>& theVec3, const Element_t theW)
+ {
+ v[0] = theVec3.x();
+ v[1] = theVec3.y();
+ v[2] = theVec3.z();
+ v[3] = theW;
+ }
+
//! Alias to 1st component as X coordinate in XYZW.
Element_t x() const { return v[0]; }
//! Alias to 4th component as ALPHA channel in RGBA.
Element_t& a() { return v[3]; }
- //! @return XY-components modifiable vector
- NCollection_Vec2<Element_t>& xy()
- {
- return *((NCollection_Vec2<Element_t>* )&v[0]);
- }
-
- //! @return YZ-components modifiable vector
- NCollection_Vec2<Element_t>& yz()
- {
- return *((NCollection_Vec2<Element_t>* )&v[1]);
- }
-
- //! @return YZ-components modifiable vector
- NCollection_Vec2<Element_t>& zw()
- {
- return *((NCollection_Vec2<Element_t>* )&v[2]);
- }
-
- //! @return XYZ-components modifiable vector
- NCollection_Vec3<Element_t>& xyz()
- {
- return *((NCollection_Vec3<Element_t>* )&v[0]);
- }
-
- //! @return YZW-components modifiable vector
- NCollection_Vec3<Element_t>& yzw()
- {
- return *((NCollection_Vec3<Element_t>* )&v[1]);
- }
-
//! Check this vector with another vector for equality (without tolerance!).
bool IsEqual (const NCollection_Vec4& theOther) const
{
{
case Aspect_GFM_HOR:
{
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[1] = myGradientParams.color2.xyz().ChangeData();
- aCorners[2] = myGradientParams.color1.xyz().ChangeData();
- aCorners[3] = myGradientParams.color1.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[1] = myGradientParams.color2.ChangeData();
+ aCorners[2] = myGradientParams.color1.ChangeData();
+ aCorners[3] = myGradientParams.color1.ChangeData();
break;
}
case Aspect_GFM_VER:
{
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[1] = myGradientParams.color1.xyz().ChangeData();
- aCorners[2] = myGradientParams.color2.xyz().ChangeData();
- aCorners[3] = myGradientParams.color1.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[1] = myGradientParams.color1.ChangeData();
+ aCorners[2] = myGradientParams.color2.ChangeData();
+ aCorners[3] = myGradientParams.color1.ChangeData();
break;
}
case Aspect_GFM_DIAG1:
{
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[3] = myGradientParams.color1.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[3] = myGradientParams.color1.ChangeData();
aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[0][0] + aCorners[3][0]);
aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[0][1] + aCorners[3][1]);
aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[0][2] + aCorners[3][2]);
}
case Aspect_GFM_DIAG2:
{
- aCorners[1] = myGradientParams.color1.xyz().ChangeData();
- aCorners[2] = myGradientParams.color2.xyz().ChangeData();
+ aCorners[1] = myGradientParams.color1.ChangeData();
+ aCorners[2] = myGradientParams.color2.ChangeData();
aDiagCorner1[0] = aDiagCorner2[0] = 0.5f * (aCorners[1][0] + aCorners[2][0]);
aDiagCorner1[1] = aDiagCorner2[1] = 0.5f * (aCorners[1][1] + aCorners[2][1]);
aDiagCorner1[2] = aDiagCorner2[2] = 0.5f * (aCorners[1][2] + aCorners[2][2]);
aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f);
aVertices[3] = OpenGl_Vec2(0.0f, 0.0f);
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[1] = myGradientParams.color1.xyz().ChangeData();
- aCorners[2] = myGradientParams.color2.xyz().ChangeData();
- aCorners[3] = myGradientParams.color2.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[1] = myGradientParams.color1.ChangeData();
+ aCorners[2] = myGradientParams.color2.ChangeData();
+ aCorners[3] = myGradientParams.color2.ChangeData();
break;
}
case Aspect_GFM_CORNER2:
{
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[1] = myGradientParams.color1.xyz().ChangeData();
- aCorners[2] = myGradientParams.color2.xyz().ChangeData();
- aCorners[3] = myGradientParams.color2.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[1] = myGradientParams.color1.ChangeData();
+ aCorners[2] = myGradientParams.color2.ChangeData();
+ aCorners[3] = myGradientParams.color2.ChangeData();
break;
}
case Aspect_GFM_CORNER3:
aVertices[2] = OpenGl_Vec2(float(myViewWidth), 0.0f);
aVertices[3] = OpenGl_Vec2(0.0f, 0.0f);
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[1] = myGradientParams.color2.xyz().ChangeData();
- aCorners[2] = myGradientParams.color1.xyz().ChangeData();
- aCorners[3] = myGradientParams.color2.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[1] = myGradientParams.color2.ChangeData();
+ aCorners[2] = myGradientParams.color1.ChangeData();
+ aCorners[3] = myGradientParams.color2.ChangeData();
break;
}
case Aspect_GFM_CORNER4:
{
- aCorners[0] = myGradientParams.color2.xyz().ChangeData();
- aCorners[1] = myGradientParams.color2.xyz().ChangeData();
- aCorners[2] = myGradientParams.color1.xyz().ChangeData();
- aCorners[3] = myGradientParams.color2.xyz().ChangeData();
+ aCorners[0] = myGradientParams.color2.ChangeData();
+ aCorners[1] = myGradientParams.color2.ChangeData();
+ aCorners[2] = myGradientParams.color1.ChangeData();
+ aCorners[3] = myGradientParams.color2.ChangeData();
break;
}
case Aspect_GFM_NONE:
}
// pack transformation parameters
- OpenGl_Vec4 aTrsf[2];
- aTrsf[0].x() = -theParams->Translation().x();
- aTrsf[0].y() = -theParams->Translation().y();
- aTrsf[0].zw() = theParams->Scale();
- aTrsf[1].x() = std::sin (-theParams->Rotation() * static_cast<float> (M_PI / 180.0));
- aTrsf[1].y() = std::cos (-theParams->Rotation() * static_cast<float> (M_PI / 180.0));
+ OpenGl_Vec4 aTrsf[2] =
+ {
+ OpenGl_Vec4 (-theParams->Translation().x(),
+ -theParams->Translation().y(),
+ theParams->Scale().x(),
+ theParams->Scale().y()),
+ OpenGl_Vec4 (static_cast<float> (std::sin (-theParams->Rotation() * M_PI / 180.0)),
+ static_cast<float> (std::cos (-theParams->Rotation() * M_PI / 180.0)),
+ 0.0f, 0.0f)
+ };
myActiveProgram->SetUniform (this, aUniLoc, 2, aTrsf);
return;
}
void SetColor (const OpenGl_Vec4& theColor)
{
// apply the same formula as in Graphic3d_MaterialAspect::SetColor()
- Ambient.xyz() = theColor.rgb() * 0.25f;
- Diffuse.xyz() = theColor.rgb();
+ Ambient.SetValues (theColor.rgb() * 0.25f, Ambient.a());
+ Diffuse.SetValues (theColor.rgb(), Diffuse.a());
}
//! Initialize material
}
myIs2d = true;
myParams = theParams;
- myPoint.xy() = thePoint;
- myPoint.z() = 0.0f;
+ myPoint.SetValues (thePoint, 0.0f);
myString.FromUnicode (theText.ToExtString());
}
return 0;
}
+// Test operations with NCollection_Vec4 that caused generation of invalid code by GCC
+// due to reinterpret_cast conversions of Vec4 internal buffer to Vec3 (see #29825)
+static Standard_Integer QANColTestVec4 (Draw_Interpretor& theDI, Standard_Integer /*theNbArgs*/, const char** /*theArgVec*/)
+{
+ NCollection_Mat4<float> aMatrix;
+ aMatrix.Translate (NCollection_Vec3<float> (4.0f, 3.0f, 1.0f));
+
+ NCollection_Vec4<float> aPoints1[8];
+ for (int aX = 0; aX < 2; ++aX)
+ {
+ for (int aY = 0; aY < 2; ++aY)
+ {
+ for (int aZ = 0; aZ < 2; ++aZ)
+ {
+ aPoints1[aX * 2 * 2 + aY * 2 + aZ] = NCollection_Vec4<float> (-1.0f + 2.0f * float(aX),
+ -1.0f + 2.0f * float(aY),
+ -1.0f + 2.0f * float(aZ),
+ 1.0f);
+ }
+ }
+ }
+
+ NCollection_Vec3<float> aPoints2[8];
+ for (int aPntIdx = 0; aPntIdx < 8; ++aPntIdx)
+ {
+ // NB: the evaluation of line below could be dropped by GCC optimizer
+ // while retrieving xyz() value the line after
+ aPoints1[aPntIdx] = aMatrix * aPoints1[aPntIdx];
+ aPoints2[aPntIdx] = aPoints1[aPntIdx].xyz() / aPoints1[aPntIdx].w();
+ //aPoints2[aPntIdx] = NCollection_Vec3<float> (aPoints1[aPntIdx].x(), aPoints1[aPntIdx].y(), aPoints1[aPntIdx].z()) / aPoints1[aPntIdx].w();
+ }
+
+ for (int aPntIter = 0; aPntIter < 8; ++aPntIter) { theDI << aPoints2[aPntIter].SquareModulus() << " "; }
+ if ((int )(aPoints2[7].SquareModulus() + 0.5f) != 45)
+ {
+ theDI << "Error: method 'NCollection_Vec4::xyz()' failed.";
+ }
+ return 0;
+}
+
void QANCollection::CommandsTest(Draw_Interpretor& theCommands) {
const char *group = "QANCollection";
- // from agvCollTest/src/CollectionEXE/FuncTestEXE.cxx
theCommands.Add("QANColTestArray1", "QANColTestArray1 Lower Upper",
__FILE__, QANColTestArray1, group);
theCommands.Add("QANColTestArray2", "QANColTestArray2 LowerRow UpperRow LowerCol UpperCol",
theCommands.Add("QANColTestSequence", "QANColTestSequence", __FILE__, QANColTestSequence, group);
theCommands.Add("QANColTestVector", "QANColTestVector", __FILE__, QANColTestVector, group);
theCommands.Add("QANColTestArrayMove", "QANColTestArrayMove (is expected to give error)", __FILE__, QANColTestArrayMove, group);
+ theCommands.Add("QANColTestVec4", "QANColTestVec4 test Vec4 implementation", __FILE__, QANColTestVec4, group);
theCommands.Add("QATestAtof", "QATestAtof [nbvalues [nbdigits [min [max]]]]", __FILE__, QATestAtof, group);
}
const Graphic3d_Vec2& aNode1 = getPosVec2 (aTriNodes[0]);
const Graphic3d_Vec2& aNode2 = getPosVec2 (aTriNodes[1]);
const Graphic3d_Vec2& aNode3 = getPosVec2 (aTriNodes[2]);
- aCenter.xy() += (aNode1 + aNode2 + aNode3) / 3.0;
+ aCenter += Graphic3d_Vec3((aNode1 + aNode2 + aNode3) / 3.0);
}
if (myBvhIndices.HasPatches())
{
else
{
aPnt2d = &getPosVec2 (aPointIndex);
- aCenter.xy() += *aPnt2d;
+ aCenter += Graphic3d_Vec3(*aPnt2d);
}
if (myBvhIndices.HasPatches())
--- /dev/null
+puts "Check NCollection_Vec4 functionality"
+
+QANColTestVec4