0029528: Visualization, TKOpenGl - allow defining sRGB textures
[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 IMPLEMENT_STANDARD_RTTIEXT(VrmlData_Material,VrmlData_Node)
23
24 #ifdef _MSC_VER
25 #define _CRT_SECURE_NO_DEPRECATE
26 #pragma warning (disable:4996)
27 #endif
28
29
30 //=======================================================================
31 //function : VrmlData_Material()
32 //purpose  : Empty Constructor
33 //=======================================================================
34
35 VrmlData_Material::VrmlData_Material ()
36   : myAmbientIntensity        (0.2),
37     myShininess               (0.2),
38     myTransparency            (0.),
39     myDiffuseColor            (0.8, 0.8, 0.8, Quantity_TOC_sRGB),
40     myEmissiveColor           (Quantity_NOC_BLACK),
41     mySpecularColor           (Quantity_NOC_BLACK)
42 {}
43
44 //=======================================================================
45 //function : VrmlData_Material
46 //purpose  : Constructor
47 //=======================================================================
48
49 VrmlData_Material::VrmlData_Material (const VrmlData_Scene&  theScene,
50                                       const char             * theName,
51                                       const Standard_Real    theAmbientIntens,
52                                       const Standard_Real    theShininess,
53                                       const Standard_Real    theTransparency)
54   : VrmlData_Node             (theScene, theName),
55     myAmbientIntensity        (theAmbientIntens < 0. ? 0.2 : theAmbientIntens),
56     myShininess               (theShininess     < 0. ? 0.2 : theShininess),
57     myTransparency            (theTransparency  < 0  ? 0.  : theTransparency),
58     myDiffuseColor            (0.8, 0.8, 0.8, Quantity_TOC_sRGB),
59     myEmissiveColor           (Quantity_NOC_BLACK),
60     mySpecularColor           (Quantity_NOC_BLACK)
61 {}
62
63
64 //=======================================================================
65 //function : VrmlData_Material::Clone
66 //purpose  : 
67 //=======================================================================
68
69 Handle(VrmlData_Node) VrmlData_Material::Clone
70                                 (const Handle(VrmlData_Node)& theOther) const
71 {
72   Handle(VrmlData_Material) aResult =
73     Handle(VrmlData_Material)::DownCast (VrmlData_Node::Clone(theOther));
74   if (aResult.IsNull())
75     aResult =
76       new VrmlData_Material (theOther.IsNull() ? Scene() : theOther->Scene(),
77                              Name());
78
79   aResult->SetAmbientIntensity (myAmbientIntensity);
80   aResult->SetShininess        (myShininess);
81   aResult->SetTransparency     (myTransparency);
82   aResult->SetDiffuseColor     (myDiffuseColor);
83   aResult->SetEmissiveColor    (myEmissiveColor);
84   aResult->SetSpecularColor    (mySpecularColor);
85   return aResult;
86 }
87
88 //=======================================================================
89 //function : VrmlData_Material::Read
90 //purpose  : 
91 //=======================================================================
92
93 VrmlData_ErrorStatus VrmlData_Material::Read (VrmlData_InBuffer& theBuffer)
94 {
95   VrmlData_ErrorStatus aStatus;
96   const Standard_Real aConf = 0.001 * Precision::Confusion();
97   Standard_Real anIntensity[3] = { 0.2, 0.2, 0. };
98   gp_XYZ        aColor[3] = {
99     gp_XYZ (0.8, 0.8, 0.8),
100     gp_XYZ (0.0, 0.0, 0.0),
101     gp_XYZ (0.0, 0.0, 0.0)
102   };
103   while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer))) {
104     if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ambientIntensity")) {
105       if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[0],
106                                         Standard_False, Standard_False)))
107         if (anIntensity[0] < -aConf || anIntensity[0] > 1.+aConf) {
108           aStatus = VrmlData_IrrelevantNumber;
109           break;
110         }
111     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "shininess")) {
112       if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[1],
113                                         Standard_False, Standard_False)))
114         if (anIntensity[1] < -aConf || anIntensity[1] > 1.+aConf) {
115           aStatus = VrmlData_IrrelevantNumber;
116           break;
117         }
118     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "transparency")) {
119       if (OK(aStatus, Scene().ReadReal (theBuffer, anIntensity[2],
120                                         Standard_False, Standard_False)))
121         if (anIntensity[2] < -aConf || anIntensity[2] > 1.+aConf) {
122           aStatus = VrmlData_IrrelevantNumber;
123           break;
124         }
125     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "diffuseColor")) {
126       if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[0],
127                                        Standard_False, Standard_False)))
128         if (aColor[0].X() < -aConf || aColor[0].X() > 1.+aConf ||
129             aColor[0].Y() < -aConf || aColor[0].Y() > 1.+aConf ||
130             aColor[0].Z() < -aConf || aColor[0].Z() > 1.+aConf)
131         {
132           aStatus = VrmlData_IrrelevantNumber;
133           break;
134         }
135     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "emissiveColor")) {
136       if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[1],
137                                        Standard_False, Standard_False)))
138         if (aColor[1].X() < -aConf || aColor[1].X() > 1.+aConf ||
139             aColor[1].Y() < -aConf || aColor[1].Y() > 1.+aConf ||
140             aColor[1].Z() < -aConf || aColor[1].Z() > 1.+aConf)
141         {
142           aStatus = VrmlData_IrrelevantNumber;
143           break;
144         }
145     } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "specularColor")) {
146       if (OK(aStatus, Scene().ReadXYZ (theBuffer, aColor[2],
147                                        Standard_False, Standard_False)))
148         if (aColor[2].X() < -aConf || aColor[2].X() > 1.+aConf ||
149             aColor[2].Y() < -aConf || aColor[2].Y() > 1.+aConf ||
150             aColor[2].Z() < -aConf || aColor[2].Z() > 1.+aConf)
151         {
152           aStatus = VrmlData_IrrelevantNumber;
153           break;
154         }
155     } else
156       break;
157
158     if (!OK(aStatus))
159       break;
160   }
161           
162   // Read the terminating (closing) brace
163   if (OK(aStatus))
164     aStatus = readBrace (theBuffer);
165
166   // Store the values in the Material node instance
167   if (OK(aStatus)) {
168     myAmbientIntensity  = anIntensity[0];
169     myShininess         = anIntensity[1];
170     myTransparency      = anIntensity[2];
171     myDiffuseColor.SetValues  (aColor[0].X(), aColor[0].Y(), aColor[0].Z(),
172                                Quantity_TOC_sRGB);
173     myEmissiveColor.SetValues (aColor[1].X(), aColor[1].Y(), aColor[1].Z(),
174                                Quantity_TOC_sRGB);
175     mySpecularColor.SetValues (aColor[2].X(), aColor[2].Y(), aColor[2].Z(),
176                                Quantity_TOC_sRGB);
177   }
178   return aStatus;
179 }
180
181 //=======================================================================
182 //function : VrmlData_Material::Write
183 //purpose  : 
184 //=======================================================================
185
186 VrmlData_ErrorStatus VrmlData_Material::Write (const char * thePrefix) const
187 {
188   VrmlData_ErrorStatus aStatus = VrmlData_StatusOK;
189   const VrmlData_Scene& aScene = Scene();
190   static char header[] = "Material {";
191   if (aScene.IsDummyWrite() == Standard_False &&
192       OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent())))
193   {
194     char buf[128];
195     Standard_Real val[3];
196     const Quantity_TypeOfColor bidType = Quantity_TOC_sRGB;
197     const Standard_Real aConf (0.001 * Precision::Confusion());
198
199     if (OK(aStatus) && fabs(myAmbientIntensity - 0.2) > aConf) {
200       Sprintf (buf, "%.6g", myAmbientIntensity);
201       aStatus = aScene.WriteLine ("ambientIntensity ", buf);
202     }
203     if (OK(aStatus)) {
204       myDiffuseColor.Values  (val[0], val[1], val[2], bidType);
205       if ((val[0] - 0.8) * (val[0] - 0.8) +
206           (val[1] - 0.8) * (val[1] - 0.8) +
207           (val[2] - 0.8) * (val[2] - 0.8) > 1e-7)
208       {
209         Sprintf (buf, "%.6g %.6g %.6g", val[0], val[1], val[2]);
210         aStatus = aScene.WriteLine ("diffuseColor     ", buf);
211       }
212     }
213     if (OK(aStatus)) {
214       myEmissiveColor.Values  (val[0], val[1], val[2], bidType);
215       if (val[0] * val[0] + val[1] * val[1] + val[2] * val[2] > 1e-7) {      
216         Sprintf (buf, "%.6g %.6g %.6g", val[0], val[1], val[2]);
217         aStatus = aScene.WriteLine ("emissiveColor    ", buf);
218       }
219     }
220     if (OK(aStatus) && fabs(myShininess - 0.2) > aConf) {
221       Sprintf (buf, "%.6g", myShininess);
222       aStatus = aScene.WriteLine ("shininess        ", buf);
223     }
224     if (OK(aStatus)) {
225       mySpecularColor.Values  (val[0], val[1], val[2], bidType);
226       if (val[0] * val[0] + val[1] * val[1] + val[2] * val[2] > 1e-7) {      
227         Sprintf (buf, "%.6g %.6g %.6g", val[0], val[1], val[2]);
228         aStatus = aScene.WriteLine ("specularColor    ", buf);
229       }
230     }
231     if (OK(aStatus) && myTransparency > aConf) {
232       Sprintf (buf, "%.6g", myTransparency);
233       aStatus = aScene.WriteLine ("transparency     ", buf);
234     }
235
236     aStatus = WriteClosing();
237   }
238   return aStatus;
239 }
240
241 //=======================================================================
242 //function : IsDefault
243 //purpose  : 
244 //=======================================================================
245
246 Standard_Boolean VrmlData_Material::IsDefault () const
247 {
248   const Standard_Real aConf (0.001 * Precision::Confusion());
249   Standard_Boolean aResult (Standard_False);
250   if (fabs(myAmbientIntensity - 0.2) < aConf &&
251       fabs(myShininess - 0.2)        < aConf &&
252       myTransparency                 < aConf)
253   {
254     Standard_Real val[3][3];
255     const Quantity_TypeOfColor bidType = Quantity_TOC_sRGB;
256     myDiffuseColor.Values  (val[0][0], val[0][1], val[0][2], bidType);
257     myEmissiveColor.Values (val[1][0], val[1][1], val[1][2], bidType);
258     mySpecularColor.Values (val[2][0], val[2][1], val[2][2], bidType);
259     aResult = (((val[0][0] - 0.8)*(val[0][0] - 0.8) +
260                 (val[0][1] - 0.8)*(val[0][1] - 0.8) +
261                 (val[0][2] - 0.8)*(val[0][2] - 0.8) < 1e-7) &&
262                (val[1][0] * val[1][0] +
263                 val[1][1] * val[1][0] +
264                 val[1][2] * val[1][0] < 1e-7) &&
265                (val[2][0] * val[2][0] +
266                 val[2][1] * val[2][0] +
267                 val[2][2] * val[2][0] < 1e-7));
268   }
269   return aResult;
270 }
271
272