1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0033426: Data Exchange, VRML - Impossible to import VRML V1

VrmlData_ShapeNode creating (for vrml v1 case) was added
This commit is contained in:
ichesnok 2023-07-24 09:43:30 +01:00
parent 28b505b27b
commit 06f2625c35
5 changed files with 270 additions and 62 deletions

View File

@ -13,11 +13,16 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <VrmlData_Coordinate.hxx>
#include <VrmlData_Geometry.hxx>
#include <VrmlData_Group.hxx>
#include <VrmlData_IndexedFaceSet.hxx>
#include <VrmlData_IndexedLineSet.hxx>
#include <VrmlData_Scene.hxx>
#include <VrmlData_WorldInfo.hxx>
#include <VrmlData_InBuffer.hxx>
#include <VrmlData_ListOfNode.hxx>
#include <VrmlData_ShapeNode.hxx>
#include <VrmlData_UnknownNode.hxx>
#include <Precision.hxx>
#include <gp_Ax1.hxx>
@ -206,8 +211,8 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
TCollection_AsciiString aDummy;
aStatus = Scene().ReadWord (theBuffer, aDummy);
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Separator") ||
VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch")) {
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "Switch"))
{
Standard_Boolean isBracketed (Standard_False);
// Read the opening bracket for the list of children
if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
@ -238,7 +243,99 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
break;
}
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints")) {
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "TransformSeparator") ||
VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Separator"))
{
Handle(VrmlData_Group) aGroupNode = new VrmlData_Group(Scene(), "");
Standard_Boolean isBracketed(Standard_False);
// Read the opening bracket for the list of children
if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
break;
if (theBuffer.LinePtr[0] == '{') {
theBuffer.LinePtr++;
if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
break;
isBracketed = Standard_True;
}
// Read the child nodes
Handle(VrmlData_Node) aChildNode;
while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
// read the end-of-list bracket
if (isBracketed && theBuffer.LinePtr[0] == '}') {
theBuffer.LinePtr++;
break;
}
// otherwise read a node
if (!OK(aStatus, ReadNode(theBuffer, aChildNode)))
break;
aGroupNode->AddNode(aChildNode);
if (isBracketed == Standard_False)
break;
}
Handle(VrmlData_Coordinate) aCoord;
Handle(VrmlData_IndexedFaceSet) anIndFaceSet;
Handle(VrmlData_IndexedLineSet) anIndLineSet;
Handle(VrmlData_Appearance) anAppearance;
for (VrmlData_ListOfNode::Iterator anIt = aGroupNode->NodeIterator(); anIt.More(); anIt.Next())
{
Handle(VrmlData_Node) aNode = anIt.Value();
if (aNode.IsNull())
continue;
if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_Coordinate)))
{
aCoord = Handle(VrmlData_Coordinate)::DownCast(anIt.Value());
}
else if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_IndexedFaceSet)))
{
anIndFaceSet = Handle(VrmlData_IndexedFaceSet)::DownCast(anIt.Value());
if (!aCoord.IsNull())
{
anIndFaceSet->SetCoordinates(aCoord);
}
}
else if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_IndexedLineSet)))
{
anIndLineSet = Handle(VrmlData_IndexedLineSet)::DownCast(anIt.Value());
if (!aCoord.IsNull())
{
anIndLineSet->SetCoordinates(aCoord);
}
}
else if (anIt.Value()->IsKind(STANDARD_TYPE(VrmlData_Material)))
{
Handle(VrmlData_Material) aMaterial = Handle(VrmlData_Material)::DownCast(anIt.Value());
anAppearance = new VrmlData_Appearance();
anAppearance->SetMaterial(aMaterial);
}
}
if (!aCoord.IsNull())
{
Handle(VrmlData_ShapeNode) aShapeNode = new VrmlData_ShapeNode(Scene(), "");
if (!anIndFaceSet.IsNull())
{
aShapeNode->SetGeometry(anIndFaceSet);
}
else if (!anIndLineSet.IsNull())
{
aShapeNode->SetGeometry(anIndLineSet);
}
if (!anAppearance.IsNull())
{
aShapeNode->SetAppearance(anAppearance);
}
aGroupNode->AddNode(aShapeNode);
}
AddNode(aGroupNode);
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ShapeHints") ||
VRMLDATA_LCOMPARE (theBuffer.LinePtr, "DirectionalLight")) {
// Skip this tag
if (!OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
break;
@ -305,6 +402,14 @@ VrmlData_ErrorStatus VrmlData_Group::Read (VrmlData_InBuffer& theBuffer)
aStatus = VrmlData_VrmlFormatError;
break;
}
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "DEF"))
{
TCollection_AsciiString aWord;
if (OK(aStatus, VrmlData_Scene::ReadWord(theBuffer, aWord)))
{
setName(aWord.ToCString());
}
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "url")) {
NCollection_List<TCollection_AsciiString> lstURL;
if (OK(aStatus, ReadMultiString (theBuffer, lstURL))) {

View File

@ -26,6 +26,109 @@ IMPLEMENT_STANDARD_RTTIEXT(VrmlData_Material,VrmlData_Node)
#pragma warning (disable:4996)
#endif
namespace
{
static const Standard_Real THE_MAT_PREC = 0.001 * Precision::Confusion();
//=======================================================================
//function : isValidValue
//purpose :
//=======================================================================
static bool isValidValue(Standard_Real theVal)
{
return theVal >= -THE_MAT_PREC && theVal <= 1.0 + THE_MAT_PREC;
}
//=======================================================================
//function : isValidColor
//purpose :
//=======================================================================
static bool isValidColor(const gp_XYZ & theVec3)
{
return isValidValue(theVec3.X()) && isValidValue(theVec3.Y()) && isValidValue(theVec3.Z());
}
//=======================================================================
//function : parseColor
//purpose :
//=======================================================================
static bool parseColor(VrmlData_ErrorStatus & theStatus,
VrmlData_InBuffer & theBuffer,
gp_XYZ & theColor,
const VrmlData_Scene & theScene)
{
if (!VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer)))
{
return false;
}
bool isArray = *theBuffer.LinePtr == '[';
if (isArray)
{
++theBuffer.LinePtr;
}
theStatus = theScene.ReadXYZ(theBuffer, theColor, Standard_False, Standard_False);
if (isArray)
{
if (VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer))
&& *theBuffer.LinePtr == ']')
{
++theBuffer.LinePtr;
}
else
{
theStatus = VrmlData_VrmlFormatError;
}
}
if (!isValidColor(theColor))
{
theStatus = VrmlData_IrrelevantNumber;
return false;
}
return true;
}
//=======================================================================
//function : parseScalar
//purpose :
//=======================================================================
static bool parseScalar(VrmlData_ErrorStatus & theStatus,
VrmlData_InBuffer & theBuffer,
Standard_Real & theValue,
const VrmlData_Scene & theScene)
{
if (!VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer)))
{
return false;
}
bool isArray = *theBuffer.LinePtr == '[';
if (isArray)
{
++theBuffer.LinePtr;
}
theStatus = theScene.ReadReal(theBuffer, theValue, Standard_False, Standard_False);
if (isArray)
{
if (VrmlData_Node::OK(theStatus, VrmlData_Scene::ReadLine(theBuffer))
&& *theBuffer.LinePtr == ']')
{
++theBuffer.LinePtr;
}
else
{
theStatus = VrmlData_VrmlFormatError;
}
}
if (!isValidValue(theValue))
{
theStatus = VrmlData_IrrelevantNumber;
return false;
}
return true;
}
}
//=======================================================================
//function : VrmlData_Material()
@ -36,6 +139,7 @@ VrmlData_Material::VrmlData_Material ()
: myAmbientIntensity (0.2),
myShininess (0.2),
myTransparency (0.),
myAmbientColor(0., 0., 0., Quantity_TOC_RGB),
myDiffuseColor (0.8, 0.8, 0.8, Quantity_TOC_sRGB),
myEmissiveColor (Quantity_NOC_BLACK),
mySpecularColor (Quantity_NOC_BLACK)
@ -55,6 +159,7 @@ VrmlData_Material::VrmlData_Material (const VrmlData_Scene& theScene,
myAmbientIntensity (theAmbientIntens < 0. ? 0.2 : theAmbientIntens),
myShininess (theShininess < 0. ? 0.2 : theShininess),
myTransparency (theTransparency < 0 ? 0. : theTransparency),
myAmbientColor (0., 0., 0., Quantity_TOC_RGB),
myDiffuseColor (0.8, 0.8, 0.8, Quantity_TOC_sRGB),
myEmissiveColor (Quantity_NOC_BLACK),
mySpecularColor (Quantity_NOC_BLACK)
@ -79,6 +184,7 @@ Handle(VrmlData_Node) VrmlData_Material::Clone
aResult->SetAmbientIntensity (myAmbientIntensity);
aResult->SetShininess (myShininess);
aResult->SetTransparency (myTransparency);
aResult->SetAmbientColor (myAmbientColor);
aResult->SetDiffuseColor (myDiffuseColor);
aResult->SetEmissiveColor (myEmissiveColor);
aResult->SetSpecularColor (mySpecularColor);
@ -93,66 +199,37 @@ Handle(VrmlData_Node) VrmlData_Material::Clone
VrmlData_ErrorStatus VrmlData_Material::Read (VrmlData_InBuffer& theBuffer)
{
VrmlData_ErrorStatus aStatus;
const Standard_Real aConf = 0.001 * Precision::Confusion();
Standard_Real anIntensity[3] = { 0.2, 0.2, 0. };
gp_XYZ aColor[3] = {
gp_XYZ aColor[4] = {
gp_XYZ (0.0, 0.0, 0.0),
gp_XYZ (0.8, 0.8, 0.8),
gp_XYZ (0.0, 0.0, 0.0),
gp_XYZ (0.0, 0.0, 0.0)
};
while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ambientIntensity")) {
if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[0],
Standard_False, Standard_False)))
if (anIntensity[0] < -aConf || anIntensity[0] > 1.+aConf) {
aStatus = VrmlData_IrrelevantNumber;
break;
}
} else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "shininess")) {
if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[1],
Standard_False, Standard_False)))
if (anIntensity[1] < -aConf || anIntensity[1] > 1.+aConf) {
aStatus = VrmlData_IrrelevantNumber;
break;
}
} else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "transparency")) {
if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[2],
Standard_False, Standard_False)))
if (anIntensity[2] < -aConf || anIntensity[2] > 1.+aConf) {
aStatus = VrmlData_IrrelevantNumber;
break;
}
} else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "diffuseColor")) {
if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[0],
Standard_False, Standard_False)))
if (aColor[0].X() < -aConf || aColor[0].X() > 1.+aConf ||
aColor[0].Y() < -aConf || aColor[0].Y() > 1.+aConf ||
aColor[0].Z() < -aConf || aColor[0].Z() > 1.+aConf)
{
aStatus = VrmlData_IrrelevantNumber;
break;
}
} else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "emissiveColor")) {
if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[1],
Standard_False, Standard_False)))
if (aColor[1].X() < -aConf || aColor[1].X() > 1.+aConf ||
aColor[1].Y() < -aConf || aColor[1].Y() > 1.+aConf ||
aColor[1].Z() < -aConf || aColor[1].Z() > 1.+aConf)
{
aStatus = VrmlData_IrrelevantNumber;
break;
}
} else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "specularColor")) {
if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[2],
Standard_False, Standard_False)))
if (aColor[2].X() < -aConf || aColor[2].X() > 1.+aConf ||
aColor[2].Y() < -aConf || aColor[2].Y() > 1.+aConf ||
aColor[2].Z() < -aConf || aColor[2].Z() > 1.+aConf)
{
aStatus = VrmlData_IrrelevantNumber;
break;
}
} else
if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ambientIntensity"))
{
parseScalar(aStatus, theBuffer, anIntensity[0], Scene());
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "shininess")) {
parseScalar(aStatus, theBuffer, anIntensity[1], Scene());
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "transparency")) {
parseScalar(aStatus, theBuffer, anIntensity[2], Scene());
}
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "ambientColor")) {
parseColor(aStatus, theBuffer, aColor[0], Scene());
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "diffuseColor")) {
parseColor(aStatus, theBuffer, aColor[1], Scene());
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "emissiveColor")) {
parseColor(aStatus, theBuffer, aColor[2], Scene());
}
else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "specularColor")) {
parseColor(aStatus, theBuffer, aColor[3], Scene());
}
else
break;
if (!OK(aStatus))
@ -168,11 +245,13 @@ VrmlData_ErrorStatus VrmlData_Material::Read (VrmlData_InBuffer& theBuffer)
myAmbientIntensity = anIntensity[0];
myShininess = anIntensity[1];
myTransparency = anIntensity[2];
myDiffuseColor.SetValues (aColor[0].X(), aColor[0].Y(), aColor[0].Z(),
myAmbientColor.SetValues (aColor[0].X(), aColor[0].Y(), aColor[0].Z(),
Quantity_TOC_sRGB);
myEmissiveColor.SetValues (aColor[1].X(), aColor[1].Y(), aColor[1].Z(),
myDiffuseColor.SetValues (aColor[1].X(), aColor[1].Y(), aColor[1].Z(),
Quantity_TOC_sRGB);
mySpecularColor.SetValues (aColor[2].X(), aColor[2].Y(), aColor[2].Z(),
myEmissiveColor.SetValues (aColor[2].X(), aColor[2].Y(), aColor[2].Z(),
Quantity_TOC_sRGB);
mySpecularColor.SetValues (aColor[3].X(), aColor[3].Y(), aColor[3].Z(),
Quantity_TOC_sRGB);
}
return aStatus;

View File

@ -60,6 +60,12 @@ class VrmlData_Material : public VrmlData_Node
inline Standard_Real
Transparency () const { return myTransparency; }
/**
* Query the Ambient color
*/
inline const Quantity_Color&
AmbientColor () const { return myAmbientColor; }
/**
* Query the Diffuse color
*/
@ -97,6 +103,14 @@ class VrmlData_Material : public VrmlData_Node
inline void SetTransparency (const Standard_Real theTransparency)
{ myTransparency = theTransparency; }
/**
* Query the Ambient color
*/
inline void SetAmbientColor (const Quantity_Color& theColor)
{
myAmbientColor = theColor;
}
/**
* Query the Diffuse color
*/
@ -150,6 +164,7 @@ class VrmlData_Material : public VrmlData_Node
Standard_Real myAmbientIntensity;
Standard_Real myShininess;
Standard_Real myTransparency;
Quantity_Color myAmbientColor;
Quantity_Color myDiffuseColor;
Quantity_Color myEmissiveColor;
Quantity_Color mySpecularColor;

View File

@ -13,7 +13,6 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <VrmlData_Scene.hxx>
#include <VrmlData_Appearance.hxx>
#include <VrmlData_Box.hxx>
#include <VrmlData_Cone.hxx>
@ -46,6 +45,8 @@
#pragma warning (disable:4996)
#endif
#define VRMLDATA_LCOMPARE_SKIP(aa, bb) (strncmp (aa, bb, sizeof(bb)-1) == 0)
static void dumpNode (Standard_OStream& theStream,
const Handle(VrmlData_Node)& theNode,
const TCollection_AsciiString& theIndent);
@ -508,7 +509,8 @@ VrmlData_ErrorStatus VrmlData_Scene::createNode
// create the new node
if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Appearance"))
aNode = new VrmlData_Appearance (* this, strName);
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Shape"))
else if (!VRMLDATA_LCOMPARE_SKIP(theBuffer.LinePtr, "ShapeHints")
&& VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Shape"))
aNode = new VrmlData_ShapeNode (* this, strName);
else if (VRMLDATA_LCOMPARE(theBuffer.LinePtr, "Box"))
aNode = new VrmlData_Box (* this, strName);

View File

@ -0,0 +1,7 @@
puts "========"
puts "0033426: Data Exchange, VRML - Impossible to import VRML V1"
puts "========"
puts ""
loadvrml sh [locate_data_file bug33426.vrml]
checknbshapes sh -vertex 0 -edge 6 -wire 6 -face 1 -shell 0 -solid 0 -compsolid 0 -compound 5 -shape 18