1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //---------------------------------------------------------------------------
41 //---------------------------------------------------------------------------
46 #include "OSGConfig.h"
51 #include "OSGMaterialChunk.h"
52 #include "OSGShaderAttribute.h"
53 #include "OSGDrawEnv.h"
57 // Documentation for this class is emited in the
58 // OSGMaterialChunkBase.cpp file.
59 // To modify it, please change the .fcd file (OSGMaterialChunk.fcd) and
60 // regenerate the base file.
62 /***************************************************************************\
64 \***************************************************************************/
66 StateChunkClass
MaterialChunk::_class("Material", 1, 100);
68 volatile UInt16
MaterialChunk::_uiChunkCounter
= 1;
70 /***************************************************************************\
72 \***************************************************************************/
74 void MaterialChunk::initMethod(InitPhase ePhase
)
76 Inherited::initMethod(ePhase
);
79 /***************************************************************************\
81 \***************************************************************************/
83 /*-------------------------------------------------------------------------*\
85 \*-------------------------------------------------------------------------*/
87 MaterialChunk::MaterialChunk(void) :
93 MaterialChunk::MaterialChunk(const MaterialChunk
&source
) :
99 MaterialChunk::~MaterialChunk(void)
104 void MaterialChunk::onCreate(const MaterialChunk
*source
)
106 Inherited::onCreate(source
);
108 if(GlobalSystemState
== Startup
)
111 _uiChunkId
= _uiChunkCounter
++;
114 void MaterialChunk::onCreateAspect(const MaterialChunk
*createAspect
,
115 const MaterialChunk
*source
)
117 Inherited::onCreateAspect(createAspect
, source
);
119 _uiChunkId
= createAspect
->_uiChunkId
;
122 /*------------------------- Chunk Class Access ---------------------------*/
124 const StateChunkClass
*MaterialChunk::getClass(void) const
129 /*------------------------------- Sync -----------------------------------*/
131 void MaterialChunk::changed(ConstFieldMaskArg whichField
,
135 Inherited::changed(whichField
, origin
, details
);
138 UInt16
MaterialChunk::getChunkId(void)
143 /*------------------------------ Output ----------------------------------*/
145 void MaterialChunk::dump( UInt32 uiIndent
,
146 const BitVector bvFlags
) const
148 Inherited::dump(uiIndent
, bvFlags
);
150 if((bvFlags
& DiffuseFieldMask
) != 0)
152 indentLog(uiIndent
, PLOG
);
153 PLOG
<< "diffuse " << _sfDiffuse
.getValue() << "\n";
156 if((bvFlags
& AmbientFieldMask
) != 0)
158 indentLog(uiIndent
, PLOG
);
159 PLOG
<< "ambient " << _sfAmbient
.getValue() << "\n";
162 if((bvFlags
& SpecularFieldMask
) != 0)
164 indentLog(uiIndent
, PLOG
);
165 PLOG
<< "specular " << _sfSpecular
.getValue() << "\n";
168 if((bvFlags
& EmissionFieldMask
) != 0)
170 indentLog(uiIndent
, PLOG
);
171 PLOG
<< "emission " << _sfEmission
.getValue() << "\n";
174 if((bvFlags
& ShininessFieldMask
) != 0)
176 indentLog(uiIndent
, PLOG
);
177 PLOG
<< "shininess " << _sfShininess
.getValue() << "\n";
180 if((bvFlags
& LitFieldMask
) != 0)
182 indentLog(uiIndent
, PLOG
);
183 PLOG
<< "lit " << _sfLit
.getValue() << "\n";
186 if((bvFlags
& ColorMaterialFieldMask
) != 0)
188 indentLog(uiIndent
, PLOG
);
189 PLOG
<< "colorMaterial "
190 << GLDefineMapper::the()->toString(_sfColorMaterial
.getValue())
194 if((bvFlags
& BackMaterialFieldMask
) != 0)
196 indentLog(uiIndent
, PLOG
);
197 PLOG
<< "backMaterial " << _sfBackMaterial
.getValue() << "\n";
200 if((bvFlags
& BackDiffuseFieldMask
) != 0)
202 indentLog(uiIndent
, PLOG
);
203 PLOG
<< "backDiffuse " << _sfBackDiffuse
.getValue() << "\n";
206 if((bvFlags
& BackAmbientFieldMask
) != 0)
208 indentLog(uiIndent
, PLOG
);
209 PLOG
<< "backAmbient " << _sfBackAmbient
.getValue() << "\n";
212 if((bvFlags
& BackSpecularFieldMask
) != 0)
214 indentLog(uiIndent
, PLOG
);
215 PLOG
<< "backSpecular " << _sfBackSpecular
.getValue() << "\n";
218 if((bvFlags
& BackEmissionFieldMask
) != 0)
220 indentLog(uiIndent
, PLOG
);
221 PLOG
<< "backEmission " << _sfBackEmission
.getValue() << "\n";
224 if((bvFlags
& BackShininessFieldMask
) != 0)
226 indentLog(uiIndent
, PLOG
);
227 PLOG
<< "backShininess " << _sfBackShininess
.getValue() << "\n";
231 /*------------------------------ State ------------------------------------*/
233 void MaterialChunk::activate(DrawEnv
*pEnv
, UInt32
)
235 glErr("material:activate:precheck");
237 #if !defined(OSG_OGL_COREONLY) || defined(OSG_CHECK_COREONLY)
240 pEnv
->incNumChunkChanges();
242 if(getBackMaterial())
246 if(getColorMaterial() == GL_NONE
&& getBackColorMaterial() == GL_NONE
)
248 glDisable(GL_COLOR_MATERIAL
);
250 else if(getColorMaterial() == GL_NONE
)
252 glColorMaterial(GL_BACK
, getBackColorMaterial());
253 glEnable(GL_COLOR_MATERIAL
);
255 else if(getBackColorMaterial() == GL_NONE
)
257 glColorMaterial(GL_FRONT
, getColorMaterial());
258 glEnable(GL_COLOR_MATERIAL
);
260 else if(getColorMaterial() != getBackColorMaterial())
262 FWARNING(("MaterialChunk::activate: can't have different "
263 "back and front colorMaterial types!\n"));
264 glEnable(GL_COLOR_MATERIAL
);
268 glColorMaterial(GL_FRONT_AND_BACK
, getColorMaterial());
269 glEnable(GL_COLOR_MATERIAL
);
274 target
= GL_FRONT_AND_BACK
;
276 if(getColorMaterial() == GL_NONE
)
278 glDisable(GL_COLOR_MATERIAL
);
282 glColorMaterial(GL_FRONT_AND_BACK
, getColorMaterial());
283 glEnable(GL_COLOR_MATERIAL
);
287 glColor4fv(_sfDiffuse
.getValue().getValuesRGBA());
291 glMaterialfv(target
, GL_DIFFUSE
,
292 _sfDiffuse
.getValue().getValuesRGBA());
293 glMaterialfv(target
, GL_AMBIENT
,
294 _sfAmbient
.getValue().getValuesRGBA());
295 glMaterialfv(target
, GL_SPECULAR
,
296 _sfSpecular
.getValue().getValuesRGBA());
297 glMaterialfv(target
, GL_EMISSION
,
298 _sfEmission
.getValue().getValuesRGBA());
299 glMaterialf (target
, GL_SHININESS
, _sfShininess
.getValue());
301 if(getBackMaterial())
303 glMaterialfv(GL_BACK
, GL_DIFFUSE
,
304 _sfBackDiffuse
.getValue().getValuesRGBA());
305 glMaterialfv(GL_BACK
, GL_AMBIENT
,
306 _sfBackAmbient
.getValue().getValuesRGBA());
307 glMaterialfv(GL_BACK
, GL_SPECULAR
,
308 _sfBackSpecular
.getValue().getValuesRGBA());
309 glMaterialfv(GL_BACK
, GL_EMISSION
,
310 _sfBackEmission
.getValue().getValuesRGBA());
311 glMaterialf (GL_BACK
, GL_SHININESS
, _sfBackShininess
.getValue());
314 glEnable(GL_LIGHTING
);
318 glDisable(GL_LIGHTING
);
321 glVertexAttrib4fv( ShaderConstants::Attribute3Index
,
322 _sfDiffuse
.getValue().getValuesRGBA());
324 // OSG_ASSERT(false);
327 glErr("material:activate:postcheck");
330 void MaterialChunk::changeFrom(DrawEnv
*pEnv
,
331 StateChunk
*old_chunk
,
334 glErr("material:changed:precheck");
336 #if !defined(OSG_OGL_COREONLY) || defined(OSG_CHECK_COREONLY)
337 MaterialChunk
const *old
= dynamic_cast<MaterialChunk
const*>(old_chunk
);
339 // change from me to me?
340 // this assumes I haven't changed in the meantime. is that a valid
345 // Reset it, as Geometry colors might have changed it
346 glColor4fv(_sfDiffuse
.getValue().getValuesRGBA());
350 pEnv
->incNumChunkChanges();
352 if(getColorMaterial() != old
->getColorMaterial () ||
353 getBackColorMaterial() != old
->getBackColorMaterial() )
355 if(getBackMaterial())
357 if(getColorMaterial () == GL_NONE
&&
358 getBackColorMaterial() == GL_NONE
)
360 glDisable(GL_COLOR_MATERIAL
);
362 else if(getColorMaterial() == GL_NONE
)
364 glColorMaterial(GL_BACK
, getBackColorMaterial());
365 glEnable(GL_COLOR_MATERIAL
);
367 else if(getBackColorMaterial() == GL_NONE
)
369 glColorMaterial(GL_FRONT
, getColorMaterial());
370 glEnable(GL_COLOR_MATERIAL
);
372 else if(getColorMaterial() != getBackColorMaterial())
374 FWARNING(("MaterialChunk::changeFrom: can't have different "
375 "back and front colorMaterial types!\n"));
376 glEnable(GL_COLOR_MATERIAL
);
380 glColorMaterial(GL_FRONT_AND_BACK
, getColorMaterial());
381 glEnable(GL_COLOR_MATERIAL
);
386 if(getColorMaterial() == GL_NONE
)
388 glDisable(GL_COLOR_MATERIAL
);
392 glColorMaterial(GL_FRONT_AND_BACK
, getColorMaterial());
393 glEnable(GL_COLOR_MATERIAL
);
398 glColor4fv(_sfDiffuse
.getValue().getValuesRGBA());
400 if(getLit() && ! old
->getLit())
401 glEnable(GL_LIGHTING
);
402 else if(! getLit() && old
->getLit())
403 glDisable(GL_LIGHTING
);
409 if(getBackMaterial())
415 target
= GL_FRONT_AND_BACK
;
418 glMaterialfv(target
, GL_DIFFUSE
,
419 _sfDiffuse
.getValue().getValuesRGBA());
420 glMaterialfv(target
, GL_AMBIENT
,
421 _sfAmbient
.getValue().getValuesRGBA());
422 glMaterialfv(target
, GL_SPECULAR
,
423 _sfSpecular
.getValue().getValuesRGBA());
424 glMaterialfv(target
, GL_EMISSION
,
425 _sfEmission
.getValue().getValuesRGBA());
426 // adjust shininess only if it differs enough
427 if(osgAbs(_sfShininess
.getValue() - old
->getShininess()) > 1e-4)
428 glMaterialf(target
, GL_SHININESS
, _sfShininess
.getValue());
430 if(getBackMaterial())
432 glMaterialfv(GL_BACK
, GL_DIFFUSE
,
433 _sfBackDiffuse
.getValue().getValuesRGBA());
434 glMaterialfv(GL_BACK
, GL_AMBIENT
,
435 _sfBackAmbient
.getValue().getValuesRGBA());
436 glMaterialfv(GL_BACK
, GL_SPECULAR
,
437 _sfBackSpecular
.getValue().getValuesRGBA());
438 glMaterialfv(GL_BACK
, GL_EMISSION
,
439 _sfBackEmission
.getValue().getValuesRGBA());
440 // adjust shininess only if it differs enough
441 if(osgAbs(_sfBackShininess
.getValue() -
442 old
->getBackShininess() ) > 1e-4)
444 glMaterialf(GL_BACK
, GL_SHININESS
,
445 _sfBackShininess
.getValue());
450 glVertexAttrib4fv( ShaderConstants::Attribute3Index
,
451 _sfDiffuse
.getValue().getValuesRGBA());
452 // OSG_ASSERT(false);
455 glErr("material:changed:postcheck");
458 void MaterialChunk::deactivate(DrawEnv
*, UInt32
)
460 #if !defined(OSG_OGL_COREONLY) || defined(OSG_CHECK_COREONLY)
462 glDisable(GL_LIGHTING
);
464 if(getColorMaterial() != GL_NONE
)
465 glDisable(GL_COLOR_MATERIAL
);
467 // OSG_ASSERT(false);
472 /*-------------------------- Comparison -----------------------------------*/
474 Real32
MaterialChunk::switchCost(StateChunk
*OSG_CHECK_ARG(chunk
))
479 bool MaterialChunk::isTransparent(void) const
481 return(getDiffuse()[3] <(1.f
- TypeTraits
<Real32
>::getDefaultEps()));
485 bool MaterialChunk::operator <(const StateChunk
&other
) const
487 return this < &other
;
490 bool MaterialChunk::operator ==(const StateChunk
&other
) const
492 MaterialChunk
const *tother
= dynamic_cast<MaterialChunk
const*>(&other
);
500 if(!getAmbient ().equals(tother
->getAmbient (),
501 TypeTraits
<Real32
>::getDefaultEps()) ||
502 !getDiffuse ().equals(tother
->getDiffuse (),
503 TypeTraits
<Real32
>::getDefaultEps()) ||
504 !getSpecular ().equals(tother
->getSpecular (),
505 TypeTraits
<Real32
>::getDefaultEps()) ||
506 !getEmission ().equals(tother
->getEmission (),
507 TypeTraits
<Real32
>::getDefaultEps()) ||
508 getShininess() != tother
->getShininess() ||
509 getLit() != tother
->getLit() ||
510 getColorMaterial() != tother
->getColorMaterial()
517 bool MaterialChunk::operator !=(const StateChunk
&other
) const
519 return !(*this == other
);