0024947: Redesign OCCT legacy type system -- automatic
[occt.git] / src / VrmlData / VrmlData_Material.cxx
1 // Created on: 2007-07-17
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2007-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <VrmlData_Material.hxx>
17 #include <Precision.hxx>
18 #include <VrmlData_InBuffer.hxx>
19 #include <VrmlData_Scene.hxx>
20 #include <gp_XYZ.hxx>
21
22 #ifdef WNT
23 #define _CRT_SECURE_NO_DEPRECATE
24 #pragma warning (disable:4996)
25 #endif
26
27
28 //=======================================================================
29 //function : VrmlData_Material()
30 //purpose  : Empty Constructor
31 //=======================================================================
32
33 VrmlData_Material::VrmlData_Material ()
34   : myAmbientIntensity        (0.2),
35     myShininess               (0.2),
36     myTransparency            (0.),
37     myDiffuseColor            (0.8, 0.8, 0.8, Quantity_TOC_RGB),
38     myEmissiveColor           (0., 0., 0., Quantity_TOC_RGB),
39     mySpecularColor           (0., 0., 0., Quantity_TOC_RGB)
40 {}
41
42 //=======================================================================
43 //function : VrmlData_Material
44 //purpose  : Constructor
45 //=======================================================================
46
47 VrmlData_Material::VrmlData_Material (const VrmlData_Scene&  theScene,
48                                       const char             * theName,
49                                       const Standard_Real    theAmbientIntens,
50                                       const Standard_Real    theShininess,
51                                       const Standard_Real    theTransparency)
52   : VrmlData_Node             (theScene, theName),
53     myAmbientIntensity        (theAmbientIntens < 0. ? 0.2 : theAmbientIntens),
54     myShininess               (theShininess     < 0. ? 0.2 : theShininess),
55     myTransparency            (theTransparency  < 0  ? 0.  : theTransparency),
56     myDiffuseColor            (0.8, 0.8, 0.8, Quantity_TOC_RGB),
57     myEmissiveColor           (0., 0., 0., Quantity_TOC_RGB),
58     mySpecularColor           (0., 0., 0., Quantity_TOC_RGB)
59 {}
60
61
62 //=======================================================================
63 //function : VrmlData_Material::Clone
64 //purpose  : 
65 //=======================================================================
66
67 Handle(VrmlData_Node) VrmlData_Material::Clone
68                                 (const Handle(VrmlData_Node)& theOther) const
69 {
70   Handle(VrmlData_Material) aResult =
71     Handle(VrmlData_Material)::DownCast (VrmlData_Node::Clone(theOther));
72   if (aResult.IsNull())
73     aResult =
74       new VrmlData_Material (theOther.IsNull() ? Scene() : theOther->Scene(),
75                              Name());
76
77   aResult->SetAmbientIntensity (myAmbientIntensity);
78   aResult->SetShininess        (myShininess);
79   aResult->SetTransparency     (myTransparency);
80   aResult->SetDiffuseColor     (myDiffuseColor);
81   aResult->SetEmissiveColor    (myEmissiveColor);
82   aResult->SetSpecularColor    (mySpecularColor);
83   return aResult;
84 }
85
86 //=======================================================================
87 //function : VrmlData_Material::Read
88 //purpose  : 
89 //=======================================================================
90
91 VrmlData_ErrorStatus VrmlData_Material::Read (VrmlData_InBuffer& theBuffer)
92 {
93   VrmlData_ErrorStatus aStatus;
94   const Standard_Real aConf = 0.001 * Precision::Confusion();
95   Standard_Real anIntensity[3] = { 0.2, 0.2, 0. };
96   gp_XYZ        aColor[3] = {
97     gp_XYZ (0.8, 0.8, 0.8),
98     gp_XYZ (0.0, 0.0, 0.0),
99     gp_XYZ (0.0, 0.0, 0.0)
100   };
101   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
102     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ambientIntensity")) {
103       if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[0],
104                                         Standard_False, Standard_False)))
105         if (anIntensity[0] < -aConf || anIntensity[0] > 1.+aConf) {
106           aStatus = VrmlData_IrrelevantNumber;
107           break;
108         }
109     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "shininess")) {
110       if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[1],
111                                         Standard_False, Standard_False)))
112         if (anIntensity[1] < -aConf || anIntensity[1] > 1.+aConf) {
113           aStatus = VrmlData_IrrelevantNumber;
114           break;
115         }
116     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "transparency")) {
117       if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[2],
118                                         Standard_False, Standard_False)))
119         if (anIntensity[2] < -aConf || anIntensity[2] > 1.+aConf) {
120           aStatus = VrmlData_IrrelevantNumber;
121           break;
122         }
123     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "diffuseColor")) {
124       if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[0],
125                                        Standard_False, Standard_False)))
126         if (aColor[0].X() < -aConf || aColor[0].X() > 1.+aConf ||
127             aColor[0].Y() < -aConf || aColor[0].Y() > 1.+aConf ||
128             aColor[0].Z() < -aConf || aColor[0].Z() > 1.+aConf)
129         {
130           aStatus = VrmlData_IrrelevantNumber;
131           break;
132         }
133     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "emissiveColor")) {
134       if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[1],
135                                        Standard_False, Standard_False)))
136         if (aColor[1].X() < -aConf || aColor[1].X() > 1.+aConf ||
137             aColor[1].Y() < -aConf || aColor[1].Y() > 1.+aConf ||
138             aColor[1].Z() < -aConf || aColor[1].Z() > 1.+aConf)
139         {
140           aStatus = VrmlData_IrrelevantNumber;
141           break;
142         }
143     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "specularColor")) {
144       if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[2],
145                                        Standard_False, Standard_False)))
146         if (aColor[2].X() < -aConf || aColor[2].X() > 1.+aConf ||
147             aColor[2].Y() < -aConf || aColor[2].Y() > 1.+aConf ||
148             aColor[2].Z() < -aConf || aColor[2].Z() > 1.+aConf)
149         {
150           aStatus = VrmlData_IrrelevantNumber;
151           break;
152         }
153     } else
154       break;
155
156     if (!OK(aStatus))
157       break;
158   }
159           
160   // Read the terminating (closing) brace
161   if (OK(aStatus))
162     aStatus = readBrace (theBuffer);
163
164   // Store the values in the Material node instance
165   if (OK(aStatus)) {
166     myAmbientIntensity  = anIntensity[0];
167     myShininess         = anIntensity[1];
168     myTransparency      = anIntensity[2];
169     myDiffuseColor.SetValues  (aColor[0].X(), aColor[0].Y(), aColor[0].Z(),
170                                Quantity_TOC_RGB);
171     myEmissiveColor.SetValues (aColor[1].X(), aColor[1].Y(), aColor[1].Z(),
172                                Quantity_TOC_RGB);
173     mySpecularColor.SetValues (aColor[2].X(), aColor[2].Y(), aColor[2].Z(),
174                                Quantity_TOC_RGB);
175   }
176   return aStatus;
177 }
178
179 //=======================================================================
180 //function : VrmlData_Material::Write
181 //purpose  : 
182 //=======================================================================
183
184 VrmlData_ErrorStatus VrmlData_Material::Write (const char * thePrefix) const
185 {
186   VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
187   const VrmlData_Scene& aScene = Scene();
188   static char header[] = "Material {";
189   if (aScene.IsDummyWrite() == Standard_False &&
190       OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent())))
191   {
192     char buf[128];
193     Standard_Real val[3];
194     Quantity_TypeOfColor bidType (Quantity_TOC_RGB);
195     const Standard_Real aConf (0.001 * Precision::Confusion());
196
197     if (OK(aStatus) && fabs(myAmbientIntensity - 0.2) > aConf) {
198       Sprintf (buf, "%.6g", myAmbientIntensity);
199       aStatus = aScene.WriteLine ("ambientIntensity ", buf);
200     }
201     if (OK(aStatus)) {
202       myDiffuseColor.Values  (val[0], val[1], val[2], bidType);
203       if ((val[0] - 0.8) * (val[0] - 0.8) +
204           (val[1] - 0.8) * (val[1] - 0.8) +
205           (val[2] - 0.8) * (val[2] - 0.8) > 1e-7)
206       {
207         Sprintf (buf, "%.6g %.6g %.6g", val[0], val[1], val[2]);
208         aStatus = aScene.WriteLine ("diffuseColor     ", buf);
209       }
210     }
211     if (OK(aStatus)) {
212       myEmissiveColor.Values  (val[0], val[1], val[2], bidType);
213       if (val[0] * val[0] + val[1] * val[1] + val[2] * val[2] > 1e-7) {      
214         Sprintf (buf, "%.6g %.6g %.6g", val[0], val[1], val[2]);
215         aStatus = aScene.WriteLine ("emissiveColor    ", buf);
216       }
217     }
218     if (OK(aStatus) && fabs(myShininess - 0.2) > aConf) {
219       Sprintf (buf, "%.6g", myShininess);
220       aStatus = aScene.WriteLine ("shininess        ", buf);
221     }
222     if (OK(aStatus)) {
223       mySpecularColor.Values  (val[0], val[1], val[2], bidType);
224       if (val[0] * val[0] + val[1] * val[1] + val[2] * val[2] > 1e-7) {      
225         Sprintf (buf, "%.6g %.6g %.6g", val[0], val[1], val[2]);
226         aStatus = aScene.WriteLine ("specularColor    ", buf);
227       }
228     }
229     if (OK(aStatus) && myTransparency > aConf) {
230       Sprintf (buf, "%.6g", myTransparency);
231       aStatus = aScene.WriteLine ("transparency     ", buf);
232     }
233
234     aStatus = WriteClosing();
235   }
236   return aStatus;
237 }
238
239 //=======================================================================
240 //function : IsDefault
241 //purpose  : 
242 //=======================================================================
243
244 Standard_Boolean VrmlData_Material::IsDefault () const
245 {
246   const Standard_Real aConf (0.001 * Precision::Confusion());
247   Standard_Boolean aResult (Standard_False);
248   if (fabs(myAmbientIntensity - 0.2) < aConf &&
249       fabs(myShininess - 0.2)        < aConf &&
250       myTransparency                 < aConf)
251   {
252     Standard_Real val[3][3];
253     Quantity_TypeOfColor bidType (Quantity_TOC_RGB);
254     myDiffuseColor.Values  (val[0][0], val[0][1], val[0][2], bidType);
255     myEmissiveColor.Values (val[1][0], val[1][1], val[1][2], bidType);
256     mySpecularColor.Values (val[2][0], val[2][1], val[2][2], bidType);
257     aResult = (((val[0][0] - 0.8)*(val[0][0] - 0.8) +
258                 (val[0][1] - 0.8)*(val[0][1] - 0.8) +
259                 (val[0][2] - 0.8)*(val[0][2] - 0.8) < 1e-7) &&
260                (val[1][0] * val[1][0] +
261                 val[1][1] * val[1][0] +
262                 val[1][2] * val[1][0] < 1e-7) &&
263                (val[2][0] * val[2][0] +
264                 val[2][1] * val[2][0] +
265                 val[2][2] * val[2][0] < 1e-7));
266   }
267   return aResult;
268 }
269
270