Developer Documentation
MaterialNode.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 
43 
44 
45 
46 
47 //=============================================================================
48 //
49 // CLASS MaterialNode - IMPLEMENTATION
50 //
51 //=============================================================================
52 
53 
54 //== INCLUDES =================================================================
55 
56 
57 #include "MaterialNode.hh"
58 
59 #include <cstdio>
60 #include <sstream>
61 
62 #include <QJsonDocument>
63 #include <QJsonObject>
64 
65 
66 //== NAMESPACES ===============================================================
67 
68 namespace {
69 
70 enum ClassProperties {
71  CP_JSON_SERIALIZABLE = 1
72 };
73 
74 inline QVariantList col2vl(const ACG::Vec4f &col) {
75  return QVariantList() << col[0] << col[1] << col[2] << col[3];
76 }
77 
78 inline ACG::Vec4f vl2col(const QVariantList &vl) {
79  if (vl.size() < 4) return ACG::Vec4f();
80  return ACG::Vec4f(vl[0].toFloat(), vl[1].toFloat(), vl[2].toFloat(), vl[3].toFloat());
81 }
82 
83 } /* anonymous namespace */
84 
85 namespace ACG {
86 
87 QVariantMap json_to_variant_map(QString json) {
88  QJsonParseError error;
89  QJsonDocument jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &error);
90  if (error.error != QJsonParseError::NoError || !jsonDoc.isObject())
91  return QVariantMap();
92  return jsonDoc.object().toVariantMap();
93 }
94 
95 namespace SceneGraph {
96 
97 
98 //== IMPLEMENTATION ==========================================================
99 
100 bool Material::support_json_serialization() {
101  return CP_JSON_SERIALIZABLE;
102 }
103 
104 QString Material::serializeToJson() const {
105  QVariantMap matMap;
106 
107  matMap["baseColor"] = col2vl(baseColor_);
108  matMap["ambientColor"] = col2vl(ambientColor_);
109  matMap["diffuseColor"] = col2vl(diffuseColor_);
110  matMap["specularColor"] = col2vl(specularColor_);
111  matMap["overlayColor"] = col2vl(overlayColor_);
112  matMap["shininess"] = shininess_;
113  matMap["reflectance"] = reflectance_;
114  matMap["indexOfRefraction"] = indexOfRefraction_;
115  matMap["isRefractive"] = isRefractive_;
116  matMap["pointSize"] = pointSize_;
117  matMap["lineWidth"] = lineWidth_;
118  matMap["roundPoints"] = roundPoints_;
119  matMap["linesSmooth"] = linesSmooth_;
120  matMap["alphaTest"] = alphaTest_;
121  matMap["alphaClip"] = alphaClip_;
122  matMap["blending"] = blending_;
123  matMap["blendParam1"] = blendParam1_;
124  matMap["blendParam2"] = blendParam2_;
125  matMap["colorMaterial"] = colorMaterial_;
126  matMap["backfaceCulling"] = backfaceCulling_;
127  matMap["multiSampling"] = multiSampling_;
128 
129  const QJsonDocument json_doc(QJsonObject::fromVariantMap(matMap));
130  return QString::fromUtf8(
131  json_doc.toJson(QJsonDocument::Indented));
132 }
133 
134 void Material::deserializeFromVariantMap(const QVariantMap &matMap) {
135  if (matMap.contains("baseColor")) baseColor_ = vl2col(matMap["baseColor"].toList());
136  if (matMap.contains("ambientColor")) ambientColor_ = vl2col(matMap["ambientColor"].toList());
137  if (matMap.contains("diffuseColor")) diffuseColor_ = vl2col(matMap["diffuseColor"].toList());
138  if (matMap.contains("specularColor")) specularColor_ = vl2col(matMap["specularColor"].toList());
139  if (matMap.contains("overlayColor")) overlayColor_ = vl2col(matMap["overlayColor"].toList());
140  if (matMap.contains("shininess")) shininess_ = matMap["shininess"].toFloat();
141  if (matMap.contains("reflectance")) reflectance_ = matMap["reflectance"].toDouble();
142  if (matMap.contains("indexOfRefraction")) indexOfRefraction_ = matMap["indexOfRefraction"].toDouble();
143  if (matMap.contains("isRefractive")) isRefractive_ = matMap["isRefractive"].toBool();
144  if (matMap.contains("pointSize")) pointSize_ = matMap["pointSize"].toFloat();
145  if (matMap.contains("lineWidth")) lineWidth_ = matMap["lineWidth"].toFloat();
146  if (matMap.contains("roundPoints")) roundPoints_ = matMap["roundPoints"].toBool();
147  if (matMap.contains("linesSmooth")) linesSmooth_ = matMap["linesSmooth"].toBool();
148  if (matMap.contains("alphaTest")) alphaTest_ = matMap["alphaTest"].toBool();
149  if (matMap.contains("alphaClip")) alphaClip_ = matMap["alphaClip"].toFloat();
150  if (matMap.contains("blending")) blending_ = matMap["blending"].toBool();
151  if (matMap.contains("blendParam1")) blendParam1_ = matMap["blendParam1"].toUInt();
152  if (matMap.contains("blendParam2")) blendParam2_ = matMap["blendParam2"].toUInt();
153  if (matMap.contains("colorMaterial")) colorMaterial_ = matMap["colorMaterial"].toBool();
154  if (matMap.contains("backfaceCulling")) backfaceCulling_ = matMap["backfaceCulling"].toBool();
155  if (matMap.contains("multiSampling")) multiSampling_ = matMap["multiSampling"].toBool();
156 }
157 
158 void Material::deserializeFromJson(const QString &json) {
159  deserializeFromVariantMap(ACG::json_to_variant_map(json));
160 }
161 
163  const std::string& _name,
164  unsigned int _applyProperties )
165  : BaseNode(_parent, _name),
166  applyProperties_(_applyProperties)
167 {}
168 
169 
170 //----------------------------------------------------------------------------
171 
172 
173 void MaterialNode::enter(GLState& _state, const DrawModes::DrawMode& _drawmode )
174 {
176  {
177  materialBackup_.baseColor_ = _state.base_color();
178  _state.set_base_color(material_.baseColor_);
179  }
180 
182  {
183  materialBackup_.ambientColor_ = _state.ambient_color();
184  materialBackup_.diffuseColor_ = _state.diffuse_color();
185  materialBackup_.specularColor_ = _state.specular_color();
186  materialBackup_.overlayColor_ = _state.overlay_color();
187  materialBackup_.shininess_ = _state.shininess();
188 
189  _state.set_ambient_color(material_.ambientColor_);
190  _state.set_diffuse_color(material_.diffuseColor_);
191  _state.set_specular_color(material_.specularColor_);
192  _state.set_overlay_color(material_.overlayColor_);
193  _state.set_shininess(material_.shininess_);
194  }
195 
197  {
198  materialBackup_.pointSize_ = _state.point_size();
199  _state.set_point_size(material_.pointSize_);
200  }
201 
203  {
204  materialBackup_.lineWidth_ = _state.line_width();
205  _state.set_line_width(material_.lineWidth_);
206  }
207 
208  if (_state.compatibilityProfile())
209  {
210  // deprecated opengl caps
211 
213  {
214  materialBackup_.roundPoints_ = glIsEnabled(GL_POINT_SMOOTH) &&
215  glIsEnabled(GL_ALPHA_TEST);
216 
217  if (material_.roundPoints_) {
218  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
219  ACG::GLState::enable(GL_POINT_SMOOTH);
220  }
221  else
222  ACG::GLState::disable(GL_POINT_SMOOTH);
223  }
224 
226  {
227  materialBackup_.linesSmooth_ = glIsEnabled(GL_LINE_SMOOTH) &&
228  glIsEnabled(GL_ALPHA_TEST);
229 
230  if (material_.linesSmooth_) {
231  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
232  ACG::GLState::enable(GL_LINE_SMOOTH);
233  }
234  else
235  ACG::GLState::disable(GL_LINE_SMOOTH);
236  }
237 
239  {
240  materialBackup_.alphaTest_ = glIsEnabled(GL_ALPHA_TEST);
241  glGetFloatv(GL_ALPHA_TEST_REF, &materialBackup_.alphaClip_);
242 
243  if (material_.alphaTest_)
244  {
245  ACG::GLState::alphaFunc(GL_GREATER, material_.alphaClip_);
246  ACG::GLState::enable(GL_ALPHA_TEST);
247  }
248  else
249  {
250  ACG::GLState::disable(GL_ALPHA_TEST);
251  }
252  }
253 
254  }
255 
257  {
258  materialBackup_.multiSampling_ = _state.multisampling();
259  _state.set_multisampling( material_.multiSampling_ );
260  }
261 
262 
264  {
265  materialBackup_.blending_ = _state.blending();
266  glGetIntegerv( GL_BLEND_SRC, (GLint*) &materialBackup_.blendParam1_);
267  glGetIntegerv( GL_BLEND_DST, (GLint*) &materialBackup_.blendParam2_);
268 
269  _state.set_blending(material_.blending_);
270 
271  if (material_.blending_)
272  {
273  _state.set_depthFunc(GL_LEQUAL);
274  ACG::GLState::blendFunc(material_.blendingParam1(), material_.blendingParam2());
275  ACG::GLState::enable(GL_BLEND);
276  }
277  else
278  {
279  _state.set_depthFunc(GL_LESS);
280  ACG::GLState::disable(GL_BLEND);
281  }
282  }
283 
284 
286  {
287  materialBackup_.backfaceCulling_ = glIsEnabled(GL_CULL_FACE);
288 
289  if ( material_.backfaceCulling_ )
290  ACG::GLState::enable( GL_CULL_FACE );
291  else
292  ACG::GLState::disable( GL_CULL_FACE );
293 
294  }
295 
297  {
298  materialBackup_.colorMaterial_ = glIsEnabled(GL_COLOR_MATERIAL);
299 
300  if(_state.compatibilityProfile())
301  {
302  if (material_.colorMaterial_ ) {
303  ACG::GLState::disable( GL_COLOR_MATERIAL );
304  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
305  ACG::GLState::enable( GL_COLOR_MATERIAL );
306  } else
307  ACG::GLState::disable( GL_COLOR_MATERIAL );
308  }
309  }
310 
311 }
312 
313 //----------------------------------------------------------------------------
314 
315 void MaterialNode::enterPick(GLState& _state , PickTarget /*_target*/, const DrawModes::DrawMode& /*_drawMode*/ ) {
316 
318  {
319  materialBackup_.pointSize_ = _state.point_size();
320  _state.set_point_size(material_.pointSize_);
321  }
322 
324  {
325  materialBackup_.lineWidth_ = _state.line_width();
326  _state.set_line_width(material_.lineWidth_);
327  }
328 }
329 
330 void MaterialNode::leavePick(GLState& _state, PickTarget /*_target*/, const DrawModes::DrawMode& /*_drawMode*/ ) {
331 
333  {
334  _state.set_point_size(materialBackup_.pointSize_);
335  }
336 
337 
339  {
340  _state.set_line_width(materialBackup_.lineWidth_);
341  }
342 }
343 
344 
345 //----------------------------------------------------------------------------
346 
347 
348 void MaterialNode::leave(GLState& _state, const DrawModes::DrawMode& _drawmode )
349 {
351  {
352  _state.set_base_color(materialBackup_.baseColor_);
353  }
354 
355 
357  {
358  _state.set_ambient_color(materialBackup_.ambientColor_);
359  _state.set_diffuse_color(materialBackup_.diffuseColor_);
360  _state.set_specular_color(materialBackup_.specularColor_);
361  _state.set_overlay_color(materialBackup_.overlayColor_);
362  _state.set_shininess(materialBackup_.shininess_);
363  }
364 
365 
367  {
368  _state.set_point_size(materialBackup_.pointSize_);
369  }
370 
371 
373  {
374  _state.set_line_width(materialBackup_.lineWidth_);
375  }
376 
377 
378  if ((applyProperties_ & RoundPoints) && _state.compatibilityProfile())
379  {
380  if( materialBackup_.roundPoints_)
381  ACG::GLState::enable(GL_POINT_SMOOTH);
382  else
383  ACG::GLState::disable(GL_POINT_SMOOTH);
384  }
385 
386  if ((applyProperties_ & LineSmooth) && _state.compatibilityProfile())
387  {
388  if( materialBackup_.linesSmooth_)
389  ACG::GLState::enable(GL_LINE_SMOOTH);
390  else
391  ACG::GLState::disable(GL_LINE_SMOOTH);
392  }
393 
395  _state.set_multisampling( materialBackup_.multiSampling_ );
396 
397  if ((applyProperties_ & AlphaTest) && _state.compatibilityProfile())
398  {
399  if (materialBackup_.alphaTest_)
400  {
401  ACG::GLState::alphaFunc(GL_GREATER, materialBackup_.alphaClip_);
402  ACG::GLState::enable(GL_ALPHA_TEST);
403  }
404  else
405  {
406  ACG::GLState::disable(GL_ALPHA_TEST);
407  }
408  }
409 
410 
412  {
413  _state.set_blending(materialBackup_.blending_);
414 
415  if (materialBackup_.blending_)
416  {
417  _state.set_depthFunc(GL_LEQUAL);
418  ACG::GLState::blendFunc(materialBackup_.blendParam1_, materialBackup_.blendParam2_);
419  ACG::GLState::enable(GL_BLEND);
420  }
421  else
422  {
423  _state.set_depthFunc(GL_LESS);
424  ACG::GLState::disable(GL_BLEND);
425  }
426  }
427 
428 
430  {
431  if (materialBackup_.backfaceCulling_)
432  ACG::GLState::enable( GL_CULL_FACE );
433  else
434  ACG::GLState::disable( GL_CULL_FACE );
435  }
436 
438  {
439  if(_state.compatibilityProfile())
440  {
441  if (materialBackup_.colorMaterial_ ) {
442  ACG::GLState::enable( GL_COLOR_MATERIAL );
443  } else
444  ACG::GLState::disable( GL_COLOR_MATERIAL );
445  }
446  }
447 
448 }
449 
450 
451 //----------------------------------------------------------------------------
452 
453 
454 void
455 MaterialNode::read(std::istream& _is)
456 {
457 
458  char s[200];
459  float x, y, z, u;
460  bool b;
461 
462  while (_is && (!_is.eof()) && _is.getline(s,200) ) {
463  std::istringstream buffer(s);
464 
465  // comment or empty
466  if ( s[0] == '#')
467  continue;
468 
469  std::string specifier = "";
470 
471  // Read specifier from buffer
472  buffer >> specifier;
473 
474  // BaseColor
475  if (specifier == "BaseColor") {
476  buffer >> x >> y >> z >> u;
477 
478  if (buffer.good()) {
479  material_.baseColor(Vec4f(x, y, z, u));
480  }
481  }
482  // AmbientColor
483  else if (specifier == "AmbientColor") {
484  buffer >> x >> y >> z >> u;
485 
486  if (buffer.good()) {
487  material_.ambientColor(Vec4f(x, y, z, u));
488  }
489  }
490  // DiffuseColor
491  else if (specifier == "DiffuseColor") {
492  buffer >> x >> y >> z >> u;
493 
494  if (buffer.good()) {
495  material_.diffuseColor(Vec4f(x, y, z, u));
496  }
497  }
498  // SpecularColor
499  else if (specifier == "SpecularColor") {
500  buffer >> x >> y >> z >> u;
501 
502  if (buffer.good()) {
503  material_.specularColor(Vec4f(x, y, z, u));
504  }
505  }
506  // OverlayColor
507  else if (specifier == "OverlayColor") {
508  buffer >> x >> y >> z >> u;
509 
510  if (buffer.good()) {
511  material_.overlayColor(Vec4f(x, y, z, u));
512  }
513  }
514  // Shininess
515  else if (specifier == "Shininess") {
516  buffer >> x;
517 
518  if (buffer.good()) {
519  material_.shininess(x);
520  }
521  }
522  // Refractive
523  else if (specifier == "isRefractive") {
524  buffer >> b;
525 
526  if (buffer.good()) {
528  }
529  }
530  // Refraction Index
531  else if (specifier == "indexOfRefraction") {
532  buffer >> x;
533 
534  if (buffer.good()) {
536  }
537  }
538  // PointSize
539  else if (specifier == "PointSize") {
540  buffer >> x;
541 
542  if (buffer.good()) {
543  material_.pointSize(x);
544  }
545  }
546  // LineWidth
547  else if (specifier == "LineWidth") {
548  buffer >> x;
549 
550  if (buffer.good()) {
551  material_.lineWidth(x);
552  }
553  }
554 
555  if (!buffer.good())
556  std::cerr << "MaterialNode parse error while reading string : " << s << std::endl;
557 
558  }
559 }
560 
561 //=============================================================================
562 } // namespace SceneGraph
563 } // namespace ACG
564 //=============================================================================
void set_shininess(float _shininess)
set specular shininess (must be in [0, 128])
Definition: GLState.cc:761
static void enable(GLenum _cap, bool _warnRemoved=true)
replaces glEnable, but supports locking
Definition: GLState.cc:1507
void pointSize(float _sz)
set point size (default: 1.0)
const Vec4f & specular_color() const
get specular color
Definition: GLState.hh:966
void set_diffuse_color(const Vec4f &_col)
set diffuse color
Definition: GLState.cc:722
float point_size() const
get point size
Definition: GLState.hh:995
static void alphaFunc(GLenum _func, GLclampf _ref)
replaces glAlphaFunc, supports locking
Definition: GLState.cc:1708
void enterPick(GLState &_state, PickTarget _target, const DrawModes::DrawMode &_drawMode) override
Do nothing in picking.
Namespace providing different geometric functions concerning angles.
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:138
MaterialNode(BaseNode *_parent=0, const std::string &_name="<MaterialNode>", unsigned int _applyProperties=(All &~BackFaceCulling))
Default constructor. Applies all properties.
const Vec4f & overlay_color() const
Get overlay color.
Definition: GLState.hh:980
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) ) ...
draw smooth lines using glLine()
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: GLState.hh:951
void set_overlay_color(const Vec4f &_col)
set overlay color
Definition: GLState.cc:752
const Vec4f & diffuse_color() const
get diffuse color
Definition: GLState.hh:961
float shininess() const
get specular shininess (must be in [0, 128])
Definition: GLState.hh:985
void overlayColor(const Vec4f &_s)
set the overlay color (This can be used to render overlays e.g. additional wireframes in a different ...
void lineWidth(float _sz)
set line width (default: 1.0)
ACG::SceneGraph::Material material_
Local material class that actually stores the properties.
ACG::SceneGraph::Material materialBackup_
Material Backup.
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
void ambientColor(const Vec4f &_a)
set the ambient color.
void leave(GLState &_state, const DrawModes::DrawMode &_drawmode) override
restores original GL-color and GL-material
void diffuseColor(const Vec4f &_d)
set the diffuse color.
void set_blending(bool _b)
set whether transparent or solid objects should be drawn
Definition: GLState.hh:1058
static void disable(GLenum _cap, bool _warnRemoved=true)
replaces glDisable, but supports locking
Definition: GLState.cc:1527
void set_ambient_color(const Vec4f &_col)
set ambient color
Definition: GLState.cc:707
void set_point_size(float _f)
set point size
Definition: GLState.cc:776
DrawMode SOLID_FACES_COLORED_FLAT_SHADED
draw flat shaded and colored faces (requires face normals and colors)
Definition: DrawModes.cc:94
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:307
void set_specular_color(const Vec4f &_col)
set specular color
Definition: GLState.cc:737
void set_line_width(float _f)
set line width
Definition: GLState.cc:791
void leavePick(GLState &_state, PickTarget _target, const DrawModes::DrawMode &_drawMode) override
Do nothing in picking.
void set_base_color(const Vec4f &_col)
set base color (used when lighting is off)
Definition: GLState.cc:677
void specularColor(const Vec4f &_s)
set the specular color
draw smooth (round) points using glPoint()
int applyProperties_
OR&#39;ed ApplyProperties.
void setRefractive(bool _r)
set refractive flag
Color Material ( Only when a drawmode using shading and lighting is enabled )
void read(std::istream &_is)
read MaterialFile
bool blending()
get whether transparenet or solid objects should be drawn
Definition: GLState.hh:1060
float line_width() const
get line width
Definition: GLState.hh:1000
void set_multisampling(bool _b)
Enable or disable multisampling.
Definition: GLState.cc:839
DrawMode SOLID_FACES_COLORED_SMOOTH_SHADED
draw smooth shaded and colored faces (requires vertex normals and face colors)
Definition: DrawModes.cc:95
void enter(GLState &_state, const DrawModes::DrawMode &_drawmode) override
set current GL-color and GL-material
void set_depthFunc(const GLenum &_depth_func)
Call glDepthFunc() to actually change the depth comparison function, and store the new value in this ...
Definition: GLState.cc:948
bool multisampling()
Get current multisampling state.
Definition: GLState.hh:1073
void shininess(float _s)
set shininess
void indexOfRefraction(double _m)
set index of refraction
const Vec4f & ambient_color() const
get ambient color
Definition: GLState.hh:956