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 "OSGMaterialDrawable.h"
53 #include "OSGChunkMaterial.h"
54 #include "OSGChunkBlock.h"
58 // Documentation for this class is emited in the
59 // OSGChunkMaterialBase.cpp file.
60 // To modify it, please change the .fcd file (OSGChunkMaterial.fcd) and
61 // regenerate the base file.
63 /***************************************************************************\
65 \***************************************************************************/
67 /*-------------------------------------------------------------------------*\
69 \*-------------------------------------------------------------------------*/
71 void ChunkMaterial::initMethod(InitPhase ePhase
)
73 Inherited::initMethod(ePhase
);
76 /***************************************************************************\
78 \***************************************************************************/
80 /*------------- constructors & destructors --------------------------------*/
82 ChunkMaterial::ChunkMaterial(void) :
87 ChunkMaterial::ChunkMaterial(const ChunkMaterial
&source
) :
92 ChunkMaterial::~ChunkMaterial(void)
96 void ChunkMaterial::pushToChunks(StateChunk
* const value
)
101 editMField(ChunksFieldMask
, _mfChunks
);
103 _mfChunks
.push_back(value
);
107 void ChunkMaterial::assignChunks (const MFUnrecStateChunkPtr
&value
)
109 MFUnrecStateChunkPtr::const_iterator elemIt
=
111 MFUnrecStateChunkPtr::const_iterator elemEnd
=
114 static_cast<ChunkMaterial
*>(this)->clearChunks();
116 while(elemIt
!= elemEnd
)
118 this->pushToChunks(*elemIt
);
125 void ChunkMaterial::removeFromChunks(UInt32 uiIndex
)
127 if(uiIndex
< _mfChunks
.size())
129 editMField(ChunksFieldMask
, _mfChunks
);
132 MFUnrecStateChunkPtr::iterator fieldIt = _mfChunks.begin_nc();
137 _mfChunks
.erase(uiIndex
);
139 if(uiIndex
< _mfSlots
.size())
141 editMField(SlotsFieldMask
, _mfSlots
);
143 MFInt32::iterator slotIt
= _mfSlots
.begin();
147 _mfSlots
.erase(slotIt
);
152 void ChunkMaterial::removeFromChunksByObj(StateChunk
* const value
)
154 Int32 iElemIdx
= _mfChunks
.findIndex(value
);
158 editMField(ChunksFieldMask
, _mfChunks
);
161 MFUnrecStateChunkPtr::iterator fieldIt = _mfChunks.begin_nc();
166 _mfChunks
.erase(iElemIdx
);
168 if(iElemIdx
< Int32(_mfSlots
.size()))
170 editMField(SlotsFieldMask
, _mfSlots
);
172 MFInt32::iterator slotIt
= _mfSlots
.begin();
176 _mfSlots
.erase(slotIt
);
181 void ChunkMaterial::replaceChunk(UInt32 uiIndex
,
182 StateChunk
* const value
)
184 if(uiIndex
< _mfChunks
.size() && value
!= NULL
)
186 editMField(ChunksFieldMask
, _mfChunks
);
188 _mfChunks
.replace(uiIndex
, value
);
193 void ChunkMaterial::changed(ConstFieldMaskArg whichField
,
197 Inherited::changed(whichField
, origin
, details
);
201 /*-------------------------- your_category---------------------------------*/
203 /*! Add the given chunk to the material. It is possible to specify
204 which slot this chunk should be associated with. See \ref StateChunkClass
205 for a general description of the slots concept. The default slot is
206 State::AutoSlotReplace.
209 bool ChunkMaterial::addChunk(StateChunk
*chunk
, Int32 slot
)
214 if(slot
!= State::AutoSlotReplace
)
216 editMField(SlotsFieldMask
, _mfSlots
);
218 while(_mfSlots
.size() < _mfChunks
.size())
219 _mfSlots
.push_back(State::AutoSlotReplace
);
222 editMField(ChunksFieldMask
, _mfChunks
);
224 _mfChunks
.push_back(chunk
);
226 if(slot
!= State::AutoSlotReplace
)
228 editMField(SlotsFieldMask
, _mfSlots
);
230 _mfSlots
.push_back(slot
);
236 /*! Remove the given chunk from the material. If the slot is not
237 State::AutoSlotReplace, only the given slot will be searched and
238 removed if found. Returns true if the chunk couldn't be found. */
240 bool ChunkMaterial::subChunk(StateChunk
*chunk
, Int32 slot
)
244 const ChunkMaterial
*pThis
= this;
246 for(i
= 0; i
< _mfChunks
.size(); ++i
)
248 if(pThis
->_mfChunks
[i
] == chunk
&&
249 ((i
< _mfSlots
.size() && pThis
->_mfSlots
[i
] == slot
) ||
250 slot
== State::AutoSlotReplace
))
252 editMField(ChunksFieldMask
, _mfChunks
);
256 if(i
< _mfSlots
.size())
258 editMField(SlotsFieldMask
, _mfSlots
);
260 _mfSlots
.erase(_mfSlots
.begin() + i
);
267 SWARNING
<< "ChunkMaterial::subChunk(" << this << ") has no chunk "
268 << chunk
<< " with slot " << slot
<< std::endl
;
273 /*! Add the given chunk to the material at a certain index. It is possible to
274 specify which slot this chunk should be associated with.
275 See \ref StateChunkClass for a general description of the slots concept.
276 The default slot is State::AutoSlotReplace. */
278 bool ChunkMaterial::insertChunk(StateChunk
*chunk
, UInt32 chunkIndex
, Int32 slot
)
284 if(chunkIndex
>= _mfChunks
.size())
285 return addChunk(chunk
, slot
);
287 if(slot
!= State::AutoSlotReplace
)
289 editMField(SlotsFieldMask
, _mfSlots
);
291 while(_mfSlots
.size() < chunkIndex
+1)
292 _mfSlots
.push_back(State::AutoSlotReplace
);
294 _mfSlots
.insert(_mfSlots
.begin()+chunkIndex
, slot
);
298 if(_mfSlots
.size() > chunkIndex
)
300 editMField(SlotsFieldMask
, _mfSlots
);
302 _mfSlots
.insert(_mfSlots
.begin()+chunkIndex
, slot
);
306 editMField(ChunksFieldMask
, _mfChunks
);
308 _mfChunks
.insert(_mfChunks
.begin_nc() + chunkIndex
, chunk
);
313 /*! Retrieve slot information from the given chunk. Returns false if the
314 chunk couldn't be found. */
316 bool ChunkMaterial::getChunkSlot(StateChunk
*chunk
, Int32
&slot
) const
321 Int32 chunkIndex
= this->find(chunk
);
326 if(Int32(_mfSlots
.size()) <= chunkIndex
)
327 slot
= State::AutoSlotReplace
;
329 slot
= _mfSlots
[chunkIndex
];
334 /*! Update slot information for the given chunk. Returns false if the
335 chunk couldn't be found. */
337 bool ChunkMaterial::setChunkSlot(StateChunk
*chunk
, Int32 slot
)
342 Int32 chunkIndex
= this->find(chunk
);
347 editMField(SlotsFieldMask
, _mfSlots
);
349 while(Int32(_mfSlots
.size()) <= chunkIndex
)
350 _mfSlots
.push_back(State::AutoSlotReplace
);
352 _mfSlots
[chunkIndex
] = slot
;
357 /*! Search the list of chunks for the given chunk. Returns its index, -1
358 if the chunk is not used in the material.
361 Int32
ChunkMaterial::find(StateChunk
*chunk
) const
365 for(i
= 0; i
< _mfChunks
.size(); ++i
)
367 if(_mfChunks
[i
] == chunk
)
374 /*! Search the list of chunks for a chunk of the given type and the given
375 slot. If slot is State::AutoSlotReplace, all slots are searched and the
376 first found chunk is returned.
377 For searching a specific chunk with a AutoSlotReplace slot,
378 the slot parameter is interpreted as a index.
381 StateChunk
*ChunkMaterial::find(const FieldContainerType
&type
,
386 for(UInt32 i
= 0; i
< _mfChunks
.size(); ++i
)
388 StateChunk
*p
= _mfChunks
[i
];
390 Int32 s
= State::AutoSlotReplace
;
392 if(i
< getMFSlots()->size())
395 if(s
== State::AutoSlotReplace
)
398 if(p
->getType() == type
)
400 if(slot
== State::AutoSlotReplace
|| slot
== s
)
411 bool ChunkMaterial::operator==(const ChunkMaterial
&other
) const
413 return Inherited::operator==(other
);
417 void ChunkMaterial::clearChunks(void)
419 editMField(ChunksFieldMask
, _mfChunks
);
420 editMField(SlotsFieldMask
, _mfSlots
);
426 void ChunkMaterial::fill(ChunkBlock
*pBlock
)
431 pBlock
->clearChunks();
433 const MFUnrecStateChunkPtr
*chunks
= this->getMFChunks();
434 const MFInt32
*slots
= this->getMFSlots ();
436 for(SizeT i
= 0; i
< chunks
->size(); ++i
)
438 int slot
= i
< slots
->size() ?
440 State::AutoSlotReplace
;
442 StateChunk
*chunk
= (*chunks
)[i
];
445 pBlock
->addChunk(chunk
, slot
);
450 /*! Add chunks to the given state. Needed for ordering in the drived
454 void ChunkMaterial::addChunks(State
*state
) const
458 for(i
= 0; i
< _mfChunks
.size(); ++i
)
460 state
->addChunk(_mfChunks
[i
],
461 (i
< _mfSlots
.size()) ? _mfSlots
[i
]
462 : State::AutoSlotReplace
);
466 /*! Rebuild the internal State. Just collects the chunks in the State.
469 void ChunkMaterial::rebuildState(void)
471 FDEBUG(("ChunkMat::rebuild state\n"));
475 _pState
->clearChunks();
479 _pState
= State::createLocal();
481 _pState
->setDefaultSortKey(this->getId());
485 _pState
->setCoreGLChunkLimit(_sfCoreGLChunkLimit
.getValue());
486 _pState
->setTransparencyMode(_sfTransparencyMode
.getValue());
491 /*! Check if the Material (i.e. any of its chunks) is transparent..
494 bool ChunkMaterial::isTransparent(void) const
496 Int32 tm
= getTransparencyMode();
498 if(tm
!= Material::TransparencyAutoDetection
)
500 return (tm
== Material::TransparencyForceTransparent
);
503 bool returnValue
= false;
505 MFChunksType::const_iterator chunksIt
= _mfChunks
.begin();
506 MFChunksType::const_iterator chunksEnd
= _mfChunks
.end ();
508 for(; chunksIt
!= chunksEnd
&& returnValue
== false; ++chunksIt
)
510 returnValue
= (*chunksIt
)->isTransparent();
516 /*------------------------------- dump ----------------------------------*/
518 void ChunkMaterial::dump( UInt32
OSG_CHECK_ARG(uiIndent
),
519 const BitVector
OSG_CHECK_ARG(bvFlags
)) const
521 SLOG
<< "ChunkMaterial at " << this << std::endl
;
522 SLOG
<< "Chunks: " << std::endl
;
526 for(i
= 0; i
< _mfChunks
.size(); ++i
)
528 SLOG
<< _mfChunks
[i
] << " "
529 << static_cast<Int32
>((i
< _mfSlots
.size())
531 : State::AutoSlotReplace
)