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  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 
52 
53 //=============================================================================
54 //
55 // CLASS MaterialNode - IMPLEMENTATION
56 //
57 //=============================================================================
58 
59 
60 //== INCLUDES =================================================================
61 
62 
63 #include "MaterialNode.hh"
64 
65 #include <cstdio>
66 #include <sstream>
67 
68 #if QT_VERSION >= 0x050000
69 #include <QJsonDocument>
70 #include <QJsonObject>
71 #elif defined(ENABLE_QJSON)
72 #include <QJson/Serializer>
73 #include <QJson/Parser>
74 #endif
75 
76 #if defined(ENABLE_QJSON) || QT_VERSION >= 0x050000
77 #define JSON_SERIALIZABLE 1
78 #else
79 #define JSON_SERIALIZABLE 0
80 #endif
81 
82 //== NAMESPACES ===============================================================
83 
84 namespace {
85 
86 enum ClassProperties {
87 #if JSON_SERIALIZABLE
88  CP_JSON_SERIALIZABLE = 1
89 #else
90  CP_JSON_SERIALIZABLE = 0
91 #endif
92 };
93 
94 inline QVariantList col2vl(const ACG::Vec4f &col) {
95  return QVariantList() << col[0] << col[1] << col[2] << col[3];
96 }
97 
98 inline ACG::Vec4f vl2col(const QVariantList &vl) {
99  if (vl.size() < 4) return ACG::Vec4f();
100  return ACG::Vec4f(vl[0].toFloat(), vl[1].toFloat(), vl[2].toFloat(), vl[3].toFloat());
101 }
102 
103 } /* anonymous namespace */
104 
105 namespace ACG {
106 
107 QVariantMap json_to_variant_map(QString json) {
108 #ifdef ENABLE_QJSON
109  QJson::Parser parser;
110  bool ok;
111  QVariantMap matMap = parser.parse(json.toUtf8(), &ok).toMap();
112  if (!ok) return QVariantMap();
113  return matMap;
114 #elif QT_VERSION >= 0x050000
115  QJsonParseError error;
116  QJsonDocument jsonDoc = QJsonDocument::fromJson(json.toUtf8(), &error);
117  if (error.error != QJsonParseError::NoError || !jsonDoc.isObject())
118  return QVariantMap();
119  return jsonDoc.object().toVariantMap();
120 #else
121  return QVariantMap();
122 #endif
123 }
124 
125 namespace SceneGraph {
126 
127 
128 //== IMPLEMENTATION ==========================================================
129 
130 bool Material::support_json_serialization() {
131  return CP_JSON_SERIALIZABLE;
132 }
133 
134 QString Material::serializeToJson() const {
135 #if JSON_SERIALIZABLE
136  QVariantMap matMap;
137 
138  matMap["baseColor"] = col2vl(baseColor_);
139  matMap["ambientColor"] = col2vl(ambientColor_);
140  matMap["diffuseColor"] = col2vl(diffuseColor_);
141  matMap["specularColor"] = col2vl(specularColor_);
142  matMap["overlayColor"] = col2vl(overlayColor_);
143  matMap["shininess"] = shininess_;
144  matMap["reflectance"] = reflectance_;
145  matMap["pointSize"] = pointSize_;
146  matMap["lineWidth"] = lineWidth_;
147  matMap["roundPoints"] = roundPoints_;
148  matMap["linesSmooth"] = linesSmooth_;
149  matMap["alphaTest"] = alphaTest_;
150  matMap["alphaClip"] = alphaClip_;
151  matMap["blending"] = blending_;
152  matMap["blendParam1"] = blendParam1_;
153  matMap["blendParam2"] = blendParam2_;
154  matMap["colorMaterial"] = colorMaterial_;
155  matMap["backfaceCulling"] = backfaceCulling_;
156  matMap["multiSampling"] = multiSampling_;
157 
158 #ifdef ENABLE_QJSON
159  QJson::Serializer serializer;
160  QByteArray bytes = serializer.serialize(matMap);
161  return QString::fromUtf8(bytes.constData(), bytes.size());
162 #elif QT_VERSION >= 0x050000
163  const QJsonDocument json_doc(QJsonObject::fromVariantMap(matMap));
164  return QString::fromUtf8(
165  json_doc.toJson(QJsonDocument::Indented));
166 #endif
167 
168 #else
169  return QString("<No suitable serializer at the moment. Sorry.>");
170 #endif
171 }
172 
173 void Material::deserializeFromVariantMap(const QVariantMap &matMap) {
174  if (matMap.contains("baseColor")) baseColor_ = vl2col(matMap["baseColor"].toList());
175  if (matMap.contains("ambientColor")) ambientColor_ = vl2col(matMap["ambientColor"].toList());
176  if (matMap.contains("diffuseColor")) diffuseColor_ = vl2col(matMap["diffuseColor"].toList());
177  if (matMap.contains("specularColor")) specularColor_ = vl2col(matMap["specularColor"].toList());
178  if (matMap.contains("overlayColor")) overlayColor_ = vl2col(matMap["overlayColor"].toList());
179  if (matMap.contains("shininess")) shininess_ = matMap["shininess"].toFloat();
180  if (matMap.contains("reflectance")) reflectance_ = matMap["reflectance"].toDouble();
181  if (matMap.contains("pointSize")) pointSize_ = matMap["pointSize"].toFloat();
182  if (matMap.contains("lineWidth")) lineWidth_ = matMap["lineWidth"].toFloat();
183  if (matMap.contains("roundPoints")) roundPoints_ = matMap["roundPoints"].toBool();
184  if (matMap.contains("linesSmooth")) linesSmooth_ = matMap["linesSmooth"].toBool();
185  if (matMap.contains("alphaTest")) alphaTest_ = matMap["alphaTest"].toBool();
186  if (matMap.contains("alphaClip")) alphaClip_ = matMap["alphaClip"].toFloat();
187  if (matMap.contains("blending")) blending_ = matMap["blending"].toBool();
188  if (matMap.contains("blendParam1")) blendParam1_ = matMap["blendParam1"].toUInt();
189  if (matMap.contains("blendParam2")) blendParam2_ = matMap["blendParam2"].toUInt();
190  if (matMap.contains("colorMaterial")) colorMaterial_ = matMap["colorMaterial"].toBool();
191  if (matMap.contains("backfaceCulling")) backfaceCulling_ = matMap["backfaceCulling"].toBool();
192  if (matMap.contains("multiSampling")) multiSampling_ = matMap["multiSampling"].toBool();
193 }
194 
195 void Material::deserializeFromJson(const QString &json) {
196  deserializeFromVariantMap(ACG::json_to_variant_map(json));
197 }
198 
200  const std::string& _name,
201  unsigned int _applyProperties )
202  : BaseNode(_parent, _name),
203  applyProperties_(_applyProperties)
204 {}
205 
206 
207 //----------------------------------------------------------------------------
208 
209 
210 void MaterialNode::enter(GLState& _state, const DrawModes::DrawMode& _drawmode )
211 {
213  {
214  materialBackup_.baseColor_ = _state.base_color();
215  _state.set_base_color(material_.baseColor_);
216  }
217 
219  {
220  materialBackup_.ambientColor_ = _state.ambient_color();
221  materialBackup_.diffuseColor_ = _state.diffuse_color();
222  materialBackup_.specularColor_ = _state.specular_color();
223  materialBackup_.overlayColor_ = _state.overlay_color();
224  materialBackup_.shininess_ = _state.shininess();
225 
226  _state.set_ambient_color(material_.ambientColor_);
227  _state.set_diffuse_color(material_.diffuseColor_);
228  _state.set_specular_color(material_.specularColor_);
229  _state.set_overlay_color(material_.overlayColor_);
230  _state.set_shininess(material_.shininess_);
231  }
232 
234  {
235  materialBackup_.pointSize_ = _state.point_size();
236  _state.set_point_size(material_.pointSize_);
237  }
238 
240  {
241  materialBackup_.lineWidth_ = _state.line_width();
242  _state.set_line_width(material_.lineWidth_);
243  }
244 
246  {
247  materialBackup_.roundPoints_ = glIsEnabled(GL_POINT_SMOOTH) &&
248  glIsEnabled(GL_ALPHA_TEST);
249 
250  if( material_.roundPoints_ ) {
251  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
252  ACG::GLState::enable(GL_POINT_SMOOTH);
253  } else
254  ACG::GLState::disable(GL_POINT_SMOOTH);
255  }
256 
258  {
259  materialBackup_.linesSmooth_ = glIsEnabled(GL_LINE_SMOOTH) &&
260  glIsEnabled(GL_ALPHA_TEST);
261 
262  if( material_.linesSmooth_ ) {
263  glHint(GL_LINE_SMOOTH_HINT,GL_NICEST);
264  ACG::GLState::enable(GL_LINE_SMOOTH);
265  } else
266  ACG::GLState::disable(GL_LINE_SMOOTH);
267  }
268 
270  {
271  materialBackup_.multiSampling_ = _state.multisampling();
272  _state.set_multisampling( material_.multiSampling_ );
273  }
274 
276  {
277  materialBackup_.alphaTest_ = glIsEnabled(GL_ALPHA_TEST);
278  glGetFloatv(GL_ALPHA_TEST_REF, &materialBackup_.alphaClip_);
279 
280  if(material_.alphaTest_)
281  {
282  ACG::GLState::alphaFunc(GL_GREATER, material_.alphaClip_ );
283  ACG::GLState::enable(GL_ALPHA_TEST);
284  }
285  else
286  {
287  ACG::GLState::disable(GL_ALPHA_TEST);
288  }
289  }
290 
291 
293  {
294  materialBackup_.blending_ = _state.blending();
295  glGetIntegerv( GL_BLEND_SRC, (GLint*) &materialBackup_.blendParam1_);
296  glGetIntegerv( GL_BLEND_DST, (GLint*) &materialBackup_.blendParam2_);
297 
298  _state.set_blending(material_.blending_);
299 
300  if (material_.blending_)
301  {
302  _state.set_depthFunc(GL_LEQUAL);
303  ACG::GLState::blendFunc(material_.blendParam1_, material_.blendParam2_);
304  ACG::GLState::enable(GL_BLEND);
305  }
306  else
307  {
308  _state.set_depthFunc(GL_LESS);
309  ACG::GLState::disable(GL_BLEND);
310  }
311  }
312 
313 
315  {
316  materialBackup_.backfaceCulling_ = glIsEnabled(GL_CULL_FACE);
317 
318  if ( material_.backfaceCulling_ )
319  ACG::GLState::enable( GL_CULL_FACE );
320  else
321  ACG::GLState::disable( GL_CULL_FACE );
322 
323  }
324 
326  {
327  materialBackup_.colorMaterial_ = glIsEnabled(GL_COLOR_MATERIAL);
328 
329  if (material_.colorMaterial_ ) {
330  ACG::GLState::disable( GL_COLOR_MATERIAL );
331  glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );
332  ACG::GLState::enable( GL_COLOR_MATERIAL );
333  } else
334  ACG::GLState::disable( GL_COLOR_MATERIAL );
335  }
336 
337 }
338 
339 //----------------------------------------------------------------------------
340 
341 void MaterialNode::enterPick(GLState& _state , PickTarget /*_target*/, const DrawModes::DrawMode& /*_drawMode*/ ) {
342 
344  {
345  materialBackup_.pointSize_ = _state.point_size();
346  _state.set_point_size(material_.pointSize_);
347  }
348 
350  {
351  materialBackup_.lineWidth_ = _state.line_width();
352  _state.set_line_width(material_.lineWidth_);
353  }
354 }
355 
356 void MaterialNode::leavePick(GLState& _state, PickTarget /*_target*/, const DrawModes::DrawMode& /*_drawMode*/ ) {
357 
359  {
360  _state.set_point_size(materialBackup_.pointSize_);
361  }
362 
363 
365  {
366  _state.set_line_width(materialBackup_.lineWidth_);
367  }
368 }
369 
370 
371 //----------------------------------------------------------------------------
372 
373 
374 void MaterialNode::leave(GLState& _state, const DrawModes::DrawMode& _drawmode )
375 {
377  {
378  _state.set_base_color(materialBackup_.baseColor_);
379  }
380 
381 
383  {
384  _state.set_ambient_color(materialBackup_.ambientColor_);
385  _state.set_diffuse_color(materialBackup_.diffuseColor_);
386  _state.set_specular_color(materialBackup_.specularColor_);
387  _state.set_overlay_color(materialBackup_.overlayColor_);
388  _state.set_shininess(materialBackup_.shininess_);
389  }
390 
391 
393  {
394  _state.set_point_size(materialBackup_.pointSize_);
395  }
396 
397 
399  {
400  _state.set_line_width(materialBackup_.lineWidth_);
401  }
402 
403 
405  {
406  if( materialBackup_.roundPoints_)
407  ACG::GLState::enable(GL_POINT_SMOOTH);
408  else
409  ACG::GLState::disable(GL_POINT_SMOOTH);
410  }
411 
413  {
414  if( materialBackup_.linesSmooth_)
415  ACG::GLState::enable(GL_LINE_SMOOTH);
416  else
417  ACG::GLState::disable(GL_LINE_SMOOTH);
418  }
419 
421  _state.set_multisampling( materialBackup_.multiSampling_ );
422 
424  {
425  if (materialBackup_.alphaTest_)
426  {
427  ACG::GLState::alphaFunc(GL_GREATER, materialBackup_.alphaClip_);
428  ACG::GLState::enable(GL_ALPHA_TEST);
429  }
430  else
431  {
432  ACG::GLState::disable(GL_ALPHA_TEST);
433  }
434  }
435 
436 
438  {
439  _state.set_blending(materialBackup_.blending_);
440 
441  if (materialBackup_.blending_)
442  {
443  _state.set_depthFunc(GL_LEQUAL);
444  ACG::GLState::blendFunc(materialBackup_.blendParam1_, materialBackup_.blendParam2_);
445  ACG::GLState::enable(GL_BLEND);
446  }
447  else
448  {
449  _state.set_depthFunc(GL_LESS);
450  ACG::GLState::disable(GL_BLEND);
451  }
452  }
453 
454 
456  {
457  if (materialBackup_.backfaceCulling_)
458  ACG::GLState::enable( GL_CULL_FACE );
459  else
460  ACG::GLState::disable( GL_CULL_FACE );
461  }
462 
464  {
465  if (materialBackup_.colorMaterial_ ) {
466  ACG::GLState::enable( GL_COLOR_MATERIAL );
467  } else
468  ACG::GLState::disable( GL_COLOR_MATERIAL );
469  }
470 
471 }
472 
473 
474 //----------------------------------------------------------------------------
475 
476 
477 void
478 MaterialNode::read(std::istream& _is)
479 {
480 
481  char s[200];
482  float x, y, z, u;
483 
484  while (_is && (!_is.eof()) && _is.getline(s,200) ) {
485  std::istringstream buffer(s);
486 
487  // comment or empty
488  if ( s[0] == '#')
489  continue;
490 
491  std::string specifier = "";
492 
493  // Read specifier from buffer
494  buffer >> specifier;
495 
496  // BaseColor
497  if (specifier == "BaseColor") {
498  buffer >> x >> y >> z >> u;
499 
500  if (buffer.good()) {
501  material_.baseColor(Vec4f(x, y, z, u));
502  }
503  }
504  // AmbientColor
505  else if (specifier == "AmbientColor") {
506  buffer >> x >> y >> z >> u;
507 
508  if (buffer.good()) {
509  material_.ambientColor(Vec4f(x, y, z, u));
510  }
511  }
512  // DiffuseColor
513  else if (specifier == "DiffuseColor") {
514  buffer >> x >> y >> z >> u;
515 
516  if (buffer.good()) {
517  material_.diffuseColor(Vec4f(x, y, z, u));
518  }
519  }
520  // SpecularColor
521  else if (specifier == "SpecularColor") {
522  buffer >> x >> y >> z >> u;
523 
524  if (buffer.good()) {
525  material_.specularColor(Vec4f(x, y, z, u));
526  }
527  }
528  // OverlayColor
529  else if (specifier == "OverlayColor") {
530  buffer >> x >> y >> z >> u;
531 
532  if (buffer.good()) {
533  material_.overlayColor(Vec4f(x, y, z, u));
534  }
535  }
536  // Shininess
537  else if (specifier == "Shininess") {
538  buffer >> x;
539 
540  if (buffer.good()) {
541  material_.shininess(x);
542  }
543  }
544  // PointSize
545  else if (specifier == "PointSize") {
546  buffer >> x;
547 
548  if (buffer.good()) {
549  material_.pointSize(x);
550  }
551  }
552  // LineWidth
553  else if (specifier == "LineWidth") {
554  buffer >> x;
555 
556  if (buffer.good()) {
557  material_.lineWidth(x);
558  }
559  }
560 
561  if (!buffer.good())
562  std::cerr << "MaterialNode parse error while reading string : " << s << std::endl;
563 
564  }
565 }
566 
567 //=============================================================================
568 } // namespace SceneGraph
569 } // namespace ACG
570 //=============================================================================
void set_line_width(float _f)
set line width
void pointSize(float _sz)
set point size (default: 1.0)
Definition: MeshNode2T.cc:211
ACG::SceneGraph::Material materialBackup_
Material Backup.
Definition: MeshNode2T.cc:557
void enterPick(GLState &_state, PickTarget _target, const DrawModes::DrawMode &_drawMode)
Do nothing in picking.
VectorT< float, 4 > Vec4f
Definition: VectorT.hh:144
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: MeshNode2T.cc:314
ACGDLLEXPORT DrawMode SOLID_FACES_COLORED_SMOOTH_SHADED
draw smooth shaded and colored faces (requires vertex normals and face colors)
Definition: DrawModes.cc:101
void baseColor(const Vec4f &_c)
set the base color
Definition: MeshNode2T.cc:167
const Vec4f & overlay_color() const
Get overlay color.
Definition: MeshNode2T.cc:958
static void alphaFunc(GLenum _func, GLclampf _ref)
replaces glAlphaFunc, supports locking
void set_specular_color(const Vec4f &_col)
set specular color
float shininess() const
get specular shininess (must be in [0, 128])
Definition: MeshNode2T.cc:963
float line_width() const
get line width
Definition: MeshNode2T.cc:978
void read(std::istream &_is)
read MaterialFile
static void enable(GLenum _cap)
replaces glEnable, but supports locking
void set_overlay_color(const Vec4f &_col)
set overlay color
Color Material ( Only when a drawmode using shading and lighting is enabled )
Definition: MeshNode2T.cc:351
const Vec4f & ambient_color() const
get ambient color
Definition: MeshNode2T.cc:934
void enter(GLState &_state, const DrawModes::DrawMode &_drawmode)
set current GL-color and GL-material
draw smooth (round) points using glPoint()
Definition: MeshNode2T.cc:341
float point_size() const
get point size
Definition: MeshNode2T.cc:973
static void disable(GLenum _cap)
replaces glDisable, but supports locking
MaterialNode(BaseNode *_parent=0, const std::string &_name="<MaterialNode>", unsigned int _applyProperties=(All &~BackFaceCulling))
Default constructor. Applies all properties.
void set_base_color(const Vec4f &_col)
set base color (used when lighting is off)
ACGDLLEXPORT DrawMode SOLID_FACES_COLORED_FLAT_SHADED
draw flat shaded and colored faces (requires face normals and colors)
Definition: DrawModes.cc:100
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void set_blending(bool _b)
set whether transparent or solid objects should be drawn
Definition: MeshNode2T.cc:1036
bool blending()
get whether transparenet or solid objects should be drawn
Definition: MeshNode2T.cc:1038
void lineWidth(float _sz)
set line width (default: 1.0)
Definition: MeshNode2T.cc:216
void diffuseColor(const Vec4f &_d)
set the diffuse color.
Definition: MeshNode2T.cc:177
void leave(GLState &_state, const DrawModes::DrawMode &_drawmode)
restores original GL-color and GL-material
void set_shininess(float _shininess)
set specular shininess (must be in [0, 128])
void leavePick(GLState &_state, PickTarget _target, const DrawModes::DrawMode &_drawMode)
Do nothing in picking.
void set_depthFunc(const GLenum &_depth_func)
Call glDepthFunc() to actually change the depth comparison function, and store the new value in this ...
const Vec4f & base_color() const
get base color (used when lighting is off)
Definition: MeshNode2T.cc:929
int applyProperties_
OR&#39;ed ApplyProperties.
Definition: MeshNode2T.cc:551
void set_ambient_color(const Vec4f &_col)
set ambient color
void overlayColor(const Vec4f &_s)
set the overlay color (This can be used to render overlays e.g. additional wireframes in a different ...
Definition: MeshNode2T.cc:187
void set_multisampling(bool _b)
Enable or disable multisampling.
bool multisampling()
Get current multisampling state.
Definition: MeshNode2T.cc:1051
const Vec4f & diffuse_color() const
get diffuse color
Definition: MeshNode2T.cc:939
void set_diffuse_color(const Vec4f &_col)
set diffuse color
void shininess(float _s)
set shininess
Definition: MeshNode2T.cc:201
ACG::SceneGraph::Material material_
Local material class that actually stores the properties.
Definition: MeshNode2T.cc:554
void set_point_size(float _f)
set point size
void ambientColor(const Vec4f &_a)
set the ambient color.
Definition: MeshNode2T.cc:172
void specularColor(const Vec4f &_s)
set the specular color
Definition: MeshNode2T.cc:182
const Vec4f & specular_color() const
get specular color
Definition: MeshNode2T.cc:944