1 /**************************************************************************\
2  * Copyright (c) Kongsberg Oil & Gas Technologies AS
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  *
12  * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  *
16  * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 \**************************************************************************/
32 
33 /*!
34   \class SoMultiTextureImageElement Inventor/elements/SoMultiTextureImageElement.h
35   \brief The SoMultiTextureImageElement class is yet to be documented.
36 
37   \ingroup elements
38 
39   FIXME: write doc.
40 
41   \COIN_CLASS_EXTENSION
42 
43   \since Coin 2.2
44 */
45 
46 #include "coindefs.h"
47 #include "SbBasicP.h"
48 
49 #include <Inventor/elements/SoMultiTextureImageElement.h>
50 #include <Inventor/elements/SoGLMultiTextureImageElement.h>
51 #include <Inventor/nodes/SoNode.h>
52 #include <Inventor/misc/SoGLImage.h>
53 #include <Inventor/SbImage.h>
54 #include <Inventor/lists/SbList.h>
55 #include <cassert>
56 
57 class SoMultiTextureImageElementP {
58 public:
ensureCapacity(int unit) const59   void ensureCapacity(int unit) const {
60     while (unit >= this->unitdata.getLength()) {
61       this->unitdata.append(SoMultiTextureImageElement::UnitData());
62     }
63   }
64   mutable SbList<SoMultiTextureImageElement::UnitData> unitdata;
65 };
66 
67 SO_ELEMENT_CUSTOM_CONSTRUCTOR_SOURCE(SoMultiTextureImageElement);
68 
69 #define PRIVATE(obj) obj->pimpl
70 
SoMultiTextureImageElement(void)71 SoMultiTextureImageElement::SoMultiTextureImageElement(void)
72 {
73   PRIVATE(this) = new SoMultiTextureImageElementP;
74 
75   this->setTypeId(SoMultiTextureImageElement::classTypeId);
76   this->setStackIndex(SoMultiTextureImageElement::classStackIndex);
77 }
78 
79 /*!
80   This static method initializes static data for the
81   SoMultiTextureImageElement class.
82 */
83 
84 void
initClass(void)85 SoMultiTextureImageElement::initClass(void)
86 {
87   SO_ELEMENT_INIT_CLASS(SoMultiTextureImageElement, inherited);
88 }
89 
90 /*!
91   The destructor.
92 */
93 
~SoMultiTextureImageElement()94 SoMultiTextureImageElement::~SoMultiTextureImageElement()
95 {
96   delete PRIVATE(this);
97 }
98 
99 //! FIXME: write doc.
100 
101 void
init(SoState * state)102 SoMultiTextureImageElement::init(SoState * state)
103 {
104   inherited::init(state);
105 }
106 
107 /*!
108   Resets this element to its original values.
109 */
110 void
setDefault(SoState * const state,SoNode * const COIN_UNUSED_ARG (node),const int unit)111 SoMultiTextureImageElement::setDefault(SoState * const state, SoNode * const COIN_UNUSED_ARG(node), const int unit)
112 {
113   SoMultiTextureImageElement * elem =
114     coin_safe_cast<SoMultiTextureImageElement *>
115     (state->getElement(classStackIndex));
116   PRIVATE(elem)->ensureCapacity(unit);
117   PRIVATE(elem)->unitdata[unit] = UnitData();
118 }
119 
120 //! FIXME: write doc.
121 void
set(SoState * const state,SoNode * const node,const int unit,const SbVec2s & size,const int numComponents,const unsigned char * bytes,const Wrap wrapS,const Wrap wrapT,const Model model,const SbColor & blendColor)122 SoMultiTextureImageElement::set(SoState * const state, SoNode * const node,
123                                 const int unit,
124                                 const SbVec2s & size, const int numComponents,
125                                 const unsigned char * bytes,
126                                 const Wrap wrapS,
127                                 const Wrap wrapT,
128                                 const Model model,
129                                 const SbColor & blendColor)
130 {
131   SoMultiTextureImageElement * elem =
132     coin_safe_cast<SoMultiTextureImageElement *>
133     (state->getElement(classStackIndex));
134 
135   PRIVATE(elem)->ensureCapacity(unit);
136   elem->setElt(unit, node->getNodeId(), size, numComponents, bytes, wrapS, wrapT,
137                model, blendColor);
138 }
139 
140 /*!
141   FIXME: write doc.
142 
143   \COIN_FUNCTION_EXTENSION
144 */
145 void
set(SoState * const state,SoNode * const node,const int unit,const SbVec3s & size,const int numComponents,const unsigned char * bytes,const Wrap wrapS,const Wrap wrapT,const Wrap wrapR,const Model model,const SbColor & blendColor)146 SoMultiTextureImageElement::set(SoState * const state, SoNode * const node,
147                                 const int unit,
148                                 const SbVec3s & size, const int numComponents,
149                                 const unsigned char * bytes,
150                                 const Wrap wrapS,
151                                 const Wrap wrapT,
152                                 const Wrap wrapR,
153                                 const Model model,
154                                 const SbColor & blendColor)
155 {
156   SoMultiTextureImageElement * elem = coin_safe_cast<SoMultiTextureImageElement *>
157     (state->getElement(classStackIndex));
158 
159   PRIVATE(elem)->ensureCapacity(unit);
160   elem->setElt(unit, node->getNodeId(), size, numComponents, bytes, wrapS, wrapT, wrapR,
161                model, blendColor);
162 }
163 
164 //! FIXME: write doc.
165 
166 const unsigned char *
get(SoState * const state,const int unit,SbVec2s & size,int & numComponents,Wrap & wrapS,Wrap & wrapT,Model & model,SbColor & blendColor)167 SoMultiTextureImageElement::get(SoState * const state,
168                                 const int unit,
169                                 SbVec2s & size,
170                                 int & numComponents,
171                                 Wrap & wrapS,
172                                 Wrap & wrapT,
173                                 Model & model,
174                                 SbColor &blendColor)
175 {
176   const SoMultiTextureImageElement * elem =
177     coin_assert_cast<const SoMultiTextureImageElement *>
178     (getConstElement(state, classStackIndex));
179 
180   PRIVATE(elem)->ensureCapacity(unit);
181   const UnitData & ud = PRIVATE(elem)->unitdata[unit];
182 
183   wrapS = ud.wrapS;
184   wrapT = ud.wrapT;
185   model = ud.model;
186   blendColor = ud.blendColor;
187 
188   return getImage(state, unit, size, numComponents);
189 }
190 
191 /*!
192   FIXME: write doc.
193 
194   \COIN_FUNCTION_EXTENSION
195 
196 */
197 const unsigned char *
get(SoState * const state,const int unit,SbVec3s & size,int & numComponents,Wrap & wrapS,Wrap & wrapT,Wrap & wrapR,Model & model,SbColor & blendColor)198 SoMultiTextureImageElement::get(SoState * const state,
199                                 const int unit,
200                                 SbVec3s & size,
201                                 int & numComponents,
202                                 Wrap & wrapS,
203                                 Wrap & wrapT,
204                                 Wrap & wrapR,
205                                 Model & model,
206                                 SbColor &blendColor)
207 {
208   const SoMultiTextureImageElement * elem =
209     coin_assert_cast<const SoMultiTextureImageElement *>
210     (getConstElement(state, classStackIndex));
211 
212   PRIVATE(elem)->ensureCapacity(unit);
213   const UnitData & ud = PRIVATE(elem)->unitdata[unit];
214 
215   wrapS = ud.wrapS;
216   wrapT = ud.wrapT;
217   wrapR = ud.wrapR;
218   model = ud.model;
219   blendColor = ud.blendColor;
220 
221   return getImage(state, unit, size, numComponents);
222 }
223 
224 /*!
225   FIXME: write doc
226 */
227 const unsigned char *
getImage(SoState * const state,const int unit,SbVec2s & size,int & numComponents)228 SoMultiTextureImageElement::getImage(SoState * const state,
229                                      const int unit,
230                                      SbVec2s &size,
231                                      int & numComponents)
232 {
233   const SoMultiTextureImageElement * elem =
234     coin_assert_cast<const SoMultiTextureImageElement *>
235     (getConstElement(state, classStackIndex));
236 
237   PRIVATE(elem)->ensureCapacity(unit);
238   const UnitData & ud = PRIVATE(elem)->unitdata[unit];
239 
240   size.setValue(ud.size[0], ud.size[1]);
241   numComponents = ud.numComponents;
242   return ud.bytes;
243 }
244 
245 /*!
246   FIXME: write doc
247 */
248 const unsigned char *
getImage(SoState * const state,const int unit,SbVec3s & size,int & numComponents)249 SoMultiTextureImageElement::getImage(SoState * const state,
250                                      const int unit,
251                                      SbVec3s & size,
252                                      int & numComponents)
253 {
254   const SoMultiTextureImageElement * elem =
255     coin_assert_cast<const SoMultiTextureImageElement *>
256     (getConstElement(state, classStackIndex));
257 
258   PRIVATE(elem)->ensureCapacity(unit);
259   const UnitData & ud = PRIVATE(elem)->unitdata[unit];
260 
261   size = ud.size;
262   numComponents = ud.numComponents;
263   return ud.bytes;
264 }
265 
266 
267 //! FIXME: write doc.
268 
269 SbBool
containsTransparency(SoState * const state)270 SoMultiTextureImageElement::containsTransparency(SoState * const state)
271 {
272   const SoMultiTextureImageElement * elem =
273     coin_assert_cast<const SoMultiTextureImageElement *>
274     (getConstElement(state, classStackIndex));
275 
276   for (int i = 0; i < PRIVATE(elem)->unitdata.getLength(); i++) {
277     if (elem->hasTransparency(i)) return TRUE;
278   }
279   return FALSE;
280 }
281 
282 /*!
283   Called by containsTransparency(). Returns \e TRUE if image data has
284   transparency. Default method does a very poor job of detecting this,
285   since it returns \e TRUE when the number of components are 2 or
286   4. Override whenever it is important to know this
287   (SoGLTextureImageElement overrides it to avoid transparency handling
288   where possible).
289 */
290 SbBool
hasTransparency(const int unit) const291 SoMultiTextureImageElement::hasTransparency(const int unit) const
292 {
293   if (unit < PRIVATE(this)->unitdata.getLength()) {
294     const UnitData & ud = PRIVATE(this)->unitdata[unit];
295     return (ud.numComponents==2 || ud.numComponents==4);
296   }
297   return FALSE;
298 }
299 
300 const SoMultiTextureImageElement::UnitData &
getUnitData(const int unit) const301 SoMultiTextureImageElement::getUnitData(const int unit) const
302 {
303   assert(unit < PRIVATE(this)->unitdata.getLength());
304   return PRIVATE(this)->unitdata[unit];
305 }
306 
307 /*!
308   Get the number of units with image data set.
309 */
310 int
getNumUnits() const311 SoMultiTextureImageElement::getNumUnits() const
312 {
313   return PRIVATE(this)->unitdata.getLength();
314 }
315 
316 //! FIXME: write doc.
317 
318 const unsigned char *
getDefault(SbVec2s & size,int & numComponents)319 SoMultiTextureImageElement::getDefault(SbVec2s & size, int & numComponents)
320 {
321   size.setValue(0,0);
322   numComponents = 0;
323   return NULL;
324 }
325 
326 /*!
327   FIXME: write doc.
328 
329 */
330 const unsigned char *
getDefault(SbVec3s & size,int & numComponents)331 SoMultiTextureImageElement::getDefault(SbVec3s & size, int & numComponents)
332 {
333   size.setValue(0,0,0);
334   numComponents = 0;
335   return NULL;
336 }
337 
338 void
push(SoState * COIN_UNUSED_ARG (state))339 SoMultiTextureImageElement::push(SoState * COIN_UNUSED_ARG(state))
340 {
341   const SoMultiTextureImageElement * prev =
342     coin_assert_cast<SoMultiTextureImageElement *>
343     (this->getNextInStack());
344 
345   PRIVATE(this)->unitdata = PRIVATE(prev)->unitdata;
346 }
347 
348 SbBool
matches(const SoElement * elem) const349 SoMultiTextureImageElement::matches(const SoElement * elem) const
350 {
351   const SoMultiTextureImageElement * e =
352     coin_assert_cast<const SoMultiTextureImageElement *>
353     (elem);
354   const int n = PRIVATE(e)->unitdata.getLength();
355   if (n != PRIVATE(this)->unitdata.getLength()) return FALSE;
356 
357   for (int i = 0; i < n; i++) {
358     if (PRIVATE(e)->unitdata[i].nodeid != PRIVATE(this)->unitdata[i].nodeid) {
359       return FALSE;
360     }
361   }
362   return TRUE;
363 }
364 
365 SoElement *
copyMatchInfo(void) const366 SoMultiTextureImageElement::copyMatchInfo(void) const
367 {
368   SoMultiTextureImageElement * elem = static_cast<SoMultiTextureImageElement *>
369     (getTypeId().createInstance());
370   PRIVATE(elem)->unitdata = PRIVATE(this)->unitdata;
371   return elem;
372 }
373 
374 
375 //! FIXME: write doc.
376 
377 void
setElt(const int unit,const SbUniqueId nodeid,const SbVec2s & size,const int numComponents,const unsigned char * bytes,const Wrap wrapS,const Wrap wrapT,const Model model,const SbColor & blendColor)378 SoMultiTextureImageElement::setElt(const int unit,
379                                    const SbUniqueId nodeid,
380                                    const SbVec2s &size, const int numComponents,
381                                    const unsigned char * bytes,
382                                    const Wrap wrapS,
383                                    const Wrap wrapT,
384                                    const Model model,
385                                    const SbColor &blendColor)
386 {
387   assert(unit < PRIVATE(this)->unitdata.getLength());
388   UnitData & ud = PRIVATE(this)->unitdata[unit];
389 
390   ud.nodeid = nodeid;
391   ud.size.setValue(size[0],size[1],1);
392   ud.numComponents = numComponents;
393   ud.bytes = bytes;
394   ud.wrapS = wrapS;
395   ud.wrapT = wrapT;
396   ud.wrapR = REPEAT;
397   ud.model = model;
398   ud.blendColor = blendColor;
399 }
400 
401 /*!
402   FIXME: write doc.
403 */
404 void
setElt(const int unit,const SbUniqueId nodeid,const SbVec3s & size,const int numComponents,const unsigned char * bytes,const Wrap wrapS,const Wrap wrapT,const Wrap wrapR,const Model model,const SbColor & blendColor)405 SoMultiTextureImageElement::setElt(const int unit,
406                                    const SbUniqueId nodeid,
407                                    const SbVec3s & size, const int numComponents,
408                                    const unsigned char * bytes,
409                                    const Wrap wrapS,
410                                    const Wrap wrapT,
411                                    const Wrap wrapR,
412                                    const Model model,
413                                    const SbColor &blendColor)
414 {
415   assert(unit < PRIVATE(this)->unitdata.getLength());
416   UnitData & ud = PRIVATE(this)->unitdata[unit];
417 
418   ud.nodeid = nodeid;
419   ud.size = size;
420   ud.numComponents = numComponents;
421   ud.bytes = bytes;
422   ud.wrapS = wrapS;
423   ud.wrapT = wrapT;
424   ud.wrapR = wrapR;
425   ud.model = model;
426   ud.blendColor = blendColor;
427 }
428 
429 /*!
430   FIXME: write doc.
431 */
432 const SbColor &
getBlendColor(SoState * const state,const int unit)433 SoMultiTextureImageElement::getBlendColor(SoState * const state, const int unit)
434 {
435   const SoMultiTextureImageElement * elem =
436     coin_assert_cast<const SoMultiTextureImageElement *>
437     (getConstElement(state, classStackIndex));
438 
439   PRIVATE(elem)->ensureCapacity(unit);
440   return PRIVATE(elem)->unitdata[unit].blendColor;
441 }
442 
443 /*!
444   FIXME: write doc.
445 */
446 SoMultiTextureImageElement::Wrap
getWrapS(SoState * const state,const int unit)447 SoMultiTextureImageElement::getWrapS(SoState * const state, const int unit)
448 {
449   const SoMultiTextureImageElement * elem =
450     coin_assert_cast<const SoMultiTextureImageElement *>
451     (getConstElement(state, classStackIndex));
452 
453   PRIVATE(elem)->ensureCapacity(unit);
454   return PRIVATE(elem)->unitdata[unit].wrapT;
455 }
456 
457 /*!
458   FIXME: write doc.
459 */
460 SoMultiTextureImageElement::Wrap
getWrapT(SoState * const state,const int unit)461 SoMultiTextureImageElement::getWrapT(SoState * const state, const int unit)
462 {
463   const SoMultiTextureImageElement * elem =
464     coin_assert_cast<const SoMultiTextureImageElement *>
465     (getConstElement(state, classStackIndex));
466 
467   PRIVATE(elem)->ensureCapacity(unit);
468   return PRIVATE(elem)->unitdata[unit].wrapS;
469 }
470 
471 /*!
472   FIXME: write doc.
473 */
474 SoMultiTextureImageElement::Wrap
getWrapR(SoState * const state,const int unit)475 SoMultiTextureImageElement::getWrapR(SoState * const state, const int unit)
476 {
477   const SoMultiTextureImageElement * elem =
478     coin_assert_cast<const SoMultiTextureImageElement *>
479     (getConstElement(state, classStackIndex));
480 
481   PRIVATE(elem)->ensureCapacity(unit);
482   return PRIVATE(elem)->unitdata[unit].wrapR;
483 }
484 
485 /*!
486   FIXME: write doc.
487 */
488 SoMultiTextureImageElement::Model
getModel(SoState * const state,const int unit)489 SoMultiTextureImageElement::getModel(SoState * const state, const int unit)
490 {
491   const SoMultiTextureImageElement * elem =
492     coin_assert_cast<const SoMultiTextureImageElement *>
493     (getConstElement(state, classStackIndex));
494 
495   PRIVATE(elem)->ensureCapacity(unit);
496   return PRIVATE(elem)->unitdata[unit].model;
497 }
498 
UnitData()499 SoMultiTextureImageElement::UnitData::UnitData()
500   : nodeid(0),
501     size(0,0,0),
502     numComponents(0),
503     bytes(0),
504     wrapS(SoMultiTextureImageElement::REPEAT),
505     wrapT(SoMultiTextureImageElement::REPEAT),
506     wrapR(SoMultiTextureImageElement::REPEAT),
507     model(SoMultiTextureImageElement::MODULATE),
508     blendColor(0.0f, 0.0f, 0.0f)
509 {
510 }
511 
UnitData(const UnitData & org)512 SoMultiTextureImageElement::UnitData::UnitData(const UnitData & org)
513   : nodeid(org.nodeid),
514     size(org.size),
515     numComponents(org.numComponents),
516     bytes(org.bytes),
517     wrapS(org.wrapS),
518     wrapT(org.wrapT),
519     wrapR(org.wrapR),
520     model(org.model),
521     blendColor(org.blendColor)
522 {
523 }
524 
525 #undef PRIVATE
526