1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
7 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
9 \*---------------------------------------------------------------------------*/
10 /*---------------------------------------------------------------------------*\
13 * This library is free software; you can redistribute it and/or modify it *
14 * under the terms of the GNU Library General Public License as published *
15 * by the Free Software Foundation, version 2. *
17 * This library is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
20 * Library General Public License for more details. *
22 * You should have received a copy of the GNU Library General Public *
23 * License along with this library; if not, write to the Free Software *
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
26 \*---------------------------------------------------------------------------*/
27 /*---------------------------------------------------------------------------*\
35 \*---------------------------------------------------------------------------*/
37 //---------------------------------------------------------------------------
39 //---------------------------------------------------------------------------
45 #include "OSGConfig.h"
47 #include "OSGGeoFunctions.h"
48 #include "OSGGeoProperties.h"
49 #include "OSGGeoPropertyFactory.h"
50 #include "OSGTriangleIterator.h"
51 #include "OSGFaceIterator.h"
52 #include "OSGTypedGeoIntegralProperty.h"
53 #include "OSGStriperHalfEdgeGraph.h"
54 #include "OSGPrimeMaterial.h"
55 #include "OSGFieldContainerUtils.h"
57 // #include "OSGSingletonHolder.ins"
61 /*---------------------------------------------------------------------*/
62 /*! \name Merge helper struct */
65 /*! \ingroup GrpDrawablesGeometryUtils
70 typedef std::vector
<Int32
> Int32Vec
;
74 Int32
entry (Int32Vec
&indexVec
);
76 const Int32Vec
&entry (Int32 index
);
78 UInt32
entryCount(void ) const;
80 IndexDic(void) : _indexMap(), _indexVec() {}
84 typedef std::map
<Int32Vec
, Int32
> IndexMap
;
88 std::vector
<const Int32Vec
*> _indexVec
;
92 Int32
IndexDic::entry(Int32Vec
&indexVec
)
94 IndexMap::iterator iI
= _indexMap
.find(indexVec
);
96 if(iI
== _indexMap
.end())
98 std::pair
< IndexMap::iterator
, bool > mapRes
=
99 _indexMap
.insert(IndexMap::value_type(indexVec
, UInt32(_indexVec
.size())));
105 _indexVec
.push_back(&(iI
->first
));
109 FFATAL(("IndexDic::entry() map insert error\n"));
117 const IndexDic::Int32Vec
&IndexDic::entry(Int32 index
)
119 return *(_indexVec
[index
]);
123 UInt32
IndexDic::entryCount(void) const
125 return UInt32(_indexVec
.size());
128 /*! \ingroup GrpDrawablesGeometryUtils
132 template <class TypeT
>
135 bool operator ()(const TypeT
&a
, const TypeT
&b
) const
137 if(a
.second
&& b
.second
)
139 if(a
.second
== b
.second
)
141 return (memcmp(a
.first
, b
.first
, a
.second
) < 0) ? true : false;
145 FFATAL(("a.memSize != b.memSize in memless::operator()\n"));
150 FFATAL(("memSize is NULL in memless::operator()\n"));
157 /*---------------------------------------------------------------------*/
161 /*! \ingroup GrpDrawablesGeometryUtils
163 Calculate vertex normals for the given geometry.
165 It just averages all normals that use a given vertex (as indicated by its
166 index). It is smart enough to only change the normals that are used by this
167 Geometry, and tries to reuse indices if they're not shared on other
170 \warning This doesn't do anything for nonindexed geometries!
173 void calcVertexNormals(Geometry
*geo
)
175 GeoVectorPropertyUnrecPtr norms
;
176 GeoIntegralPropertyUnrecPtr normsIndex
;
177 GeoIntegralPropertyUnrecPtr posIndex
;
179 posIndex
= geo
->getIndex(Geometry::PositionsIndex
);
183 FWARNING(("calcVertexNormals: Geometry is not indexed, ignored!\n"));
187 norms
= geo
->getNormals();
191 norms
= GeoVec3fProperty::create();
194 norms
->resize(geo
->getPositions()->size());
197 normsIndex
= geo
->getIndex(Geometry::NormalsIndex
);
199 // No indices reuse positions
200 if(normsIndex
== NULL
)
202 normsIndex
= geo
->getIndex(Geometry::PositionsIndex
);
205 // Shared with something except posIndex, create new
206 // Might have side effects on the other instances
207 if(normsIndex
!= posIndex
&& geo
->indexOccurrence(normsIndex
) > 1)
209 normsIndex
= GeoUInt32Property::create();
212 if(normsIndex
!= posIndex
)
214 normsIndex
->resize(posIndex
->size());
218 for(UInt32 i
= 0; i
< posIndex
->size(); ++i
)
222 posIndex
->getValue(val
, i
);
223 normsIndex
->addValue(val
);
227 // problem: not all of the points of the property might be used by this
228 // geometry. If the property has more than 1 users, be careful.
231 for(UInt32 i
= 0; i
< posIndex
->size(); ++i
)
233 posIndex
->getValue(idx
, i
);
235 norms
->setValue(Vec3f(0, 0, 0), idx
);
238 for(TriangleIterator t
= geo
->beginTriangles();
239 t
!= geo
->endTriangles ();
242 Pnt3f p0
= t
.getPosition(0);
243 Pnt3f p1
= t
.getPosition(1);
244 Pnt3f p2
= t
.getPosition(2);
248 Int32 i0
= t
.getPositionIndex(0);
249 Int32 i1
= t
.getPositionIndex(1);
250 Int32 i2
= t
.getPositionIndex(2);
254 norms
->getValue(v
, i0
);
257 norms
->setValue(v
, i0
);
260 norms
->getValue(v
, i1
);
263 norms
->setValue(v
, i1
);
266 norms
->getValue(v
, i2
);
269 norms
->setValue(v
, i2
);
272 for(UInt32 i
= 0; i
< posIndex
->size(); ++i
)
274 posIndex
->getValue(idx
, i
);
278 norms
->getValue(n
, idx
);
280 norms
->setValue(n
, idx
);
283 geo
->setNormals(norms
);
284 geo
->setIndex(normsIndex
, Geometry::NormalsIndex
);
288 /*! \ingroup GrpDrawablesGeometryUtils
290 Calculate vertex normals for the given geometry. Only vertices whose
291 triangles have an angle less than \a creaseAngle radians to each other are
294 \warning This doesn't do anything for nonindexed geometries!
297 void calcVertexNormals(Geometry
*geo
,
300 GeoVectorPropertyUnrecPtr norms
;
301 GeoVectorPropertyUnrecPtr positions
;
302 GeoIntegralPropertyUnrecPtr normsIndex
;
303 GeoIntegralPropertyUnrecPtr posIndex
;
305 if(creaseAngle
>= Pi
)
307 calcVertexNormals(geo
);
311 // Get the positions property
312 if(geo
->getProperty(Geometry::PositionsIndex
) == NULL
)
314 FINFO(("Geo without positions in calcVertexNormals()\n"));
319 positions
= geo
->getProperty(Geometry::PositionsIndex
);
322 if(positions
->size() < 3)
324 FINFO(("Geo with less than 3 positions in calcVertexNormals()\n"));
328 posIndex
= geo
->getIndex(Geometry::PositionsIndex
);
332 FINFO(("Geo without position index in calcVertexNormals()\n"));
336 norms
= geo
->getProperty(Geometry::NormalsIndex
);
338 // Get normal property, create if needed
341 norms
= GeoVec3fProperty::create();
343 geo
->setProperty(norms
, Geometry::NormalsIndex
);
346 normsIndex
= geo
->getIndex(Geometry::NormalsIndex
);
348 // No indices reuse positions
349 if(normsIndex
== NULL
|| geo
->indexOccurrence(normsIndex
) > 1)
351 normsIndex
= GeoUInt32Property::create();
353 geo
->setIndex(normsIndex
, Geometry::NormalsIndex
);
356 UInt32 nind
= posIndex
->size32();
358 normsIndex
->resize(nind
);
361 // now calc the normals
362 // if creaseAngle is 0, it's simple: every face uses its own.
367 for(UInt32 i
= 0; i
< nind
; ++i
)
368 normsIndex
->setValue(i
, i
);
370 for(TriangleIterator ti
= geo
->beginTriangles();
371 ti
!= geo
->endTriangles();
374 Vec3f d1
= ti
.getPosition(1) - ti
.getPosition(0);
375 Vec3f d2
= ti
.getPosition(2) - ti
.getPosition(0);
380 norms
->setValue(d1
, ti
.getNormalIndex(0));
381 norms
->setValue(d1
, ti
.getNormalIndex(1));
382 norms
->setValue(d1
, ti
.getNormalIndex(2));
389 // opt + normal share code (written by jbehr)
390 // collect a map from points to faces using this point
391 // collect the face normals in a separate vector
392 //FLOG (("Run calcVertexNormals(%g)\n", creaseAngle));
394 std::vector
< Vec3f
> faceNormals
;
395 std::vector
< std::vector
< UInt32
> > pntFaceDic
;
398 UInt32 iTri
, pN
= positions
->size32();
400 pntFaceDic
.resize(pN
);
402 for( ti
= geo
->beginTriangles(), iTri
= 0;
403 ti
!= geo
->endTriangles();
406 Int32 v0
= ti
.getPositionIndex(0);
407 Int32 v1
= ti
.getPositionIndex(1);
408 Int32 v2
= ti
.getPositionIndex(2);
410 if(v0
!= v1
&& v0
!= v2
)
412 Vec3f d1
= ti
.getPosition(1) - ti
.getPosition(0);
413 Vec3f d2
= ti
.getPosition(2) - ti
.getPosition(0);
417 if(d1
.squareLength() >= 0)
421 faceNormals
.push_back(d1
);
423 pntFaceDic
[ti
.getPositionIndex(0)].push_back(iTri
);
424 pntFaceDic
[ti
.getPositionIndex(1)].push_back(iTri
);
425 pntFaceDic
[ti
.getPositionIndex(2)].push_back(iTri
);
429 faceNormals
.push_back(Vec3f(0, 0, 0));
434 faceNormals
.push_back(Vec3f(0, 0, 0));
440 Real32 cosCrease
= osgCos(creaseAngle
);
443 std::vector
< UInt32
> normset
;
444 std::vector
< std::map
< std::vector
< UInt32
> , UInt32
> > normDic
;
445 std::map
< std::vector
< UInt32
> , UInt32
>::iterator ndI
;
447 UInt32 normalIndex
= 0;
451 for(ti
= geo
->beginTriangles(); ti
!= geo
->endTriangles(); ++ti
)
453 UInt32 tind
= ti
.getIndex();
454 Vec3f
faceNorm(faceNormals
[tind
]);
456 if(faceNorm
.squareLength() != 0.0)
458 for(UInt16 i
= 0; i
< 3; ++i
)
460 // calculate the normal: average all different normals
461 // that use a point. Simple addition or weighted addition
462 // doesn't work, as it depends on the triangulation
465 UInt32 p
= ti
.getPositionIndex(i
);
466 UInt32 pf
, f
, fN
= UInt32(pntFaceDic
[p
].size());
471 for(f
= 0; f
< fN
; f
++)
473 if(((pf
= pntFaceDic
[p
][f
]) == tind
) ||
474 (faceNorm
.dot(faceNormals
[pf
]) > cosCrease
))
476 normset
.push_back(pf
);
480 if((nN
= UInt32(normset
.size())))
483 //std::sort ( normset.begin(), normset.end() );
484 ndI
= normDic
[p
].find(normset
);
486 if(ndI
== normDic
[p
].end())
488 norm
= faceNormals
[normset
[0]];
490 for(n
= 1; n
< nN
; ++n
)
491 norm
+= faceNormals
[normset
[n
]];
494 normalIndex
= norms
->size32();
495 norms
->push_back(norm
);
496 normDic
[p
][normset
] = normalIndex
;
500 normalIndex
= ndI
->second
;
506 FWARNING(("Empty normset for %d faces pos %d: %f/%f/%f\n",
507 fN
, i
, ti
.getPosition(i
).x(),
508 ti
.getPosition(i
).y(), ti
.getPosition(i
).z()
512 normsIndex
->setValue(normalIndex
, ti
.getIndex(i
));
517 // keep normal for degenerated triangle
519 normalIndex
= norms
->size32();
520 norms
->push_back(norm
);
522 normsIndex
->setValue(normalIndex
, ti
.getIndex(0));
523 normsIndex
->setValue(normalIndex
, ti
.getIndex(1));
524 normsIndex
->setValue(normalIndex
, ti
.getIndex(2));
529 /*! \ingroup GrpDrawablesGeometryUtils
532 void calcFaceNormals(Geometry
*geo
)
534 FFATAL(("calcFaceNormals:: NYI!\n"));
537 /*! \ingroup GrpDrawablesGeometryUtils
540 void calcVertexTangentsProp(Geometry
*geo
,
542 UInt32 srcNormalProp
,
546 GeoVec4fPropertyUnrecPtr tangentP
;
547 GeoVec4fPropertyUnrecPtr binormalP
;
548 GeoUInt32PropertyUnrecPtr tanBinIndexP
;
550 std::vector
<Vec3f
> tangent
, binormal
, normal
;
552 // can't eval what combination was meant
553 if( (srcTexProp
> Geometry::LastIndex
) ||
554 (srcNormalProp
> Geometry::LastIndex
) ||
555 (dstPropTan
> Geometry::LastIndex
) ||
556 (dstPropBin
> Geometry::LastIndex
) ||
557 (dstPropTan
== dstPropBin
) ||
559 (dstPropTan
== srcTexProp
) ||
560 (dstPropTan
== srcNormalProp
) ||
562 (dstPropBin
== srcTexProp
) ||
563 (dstPropBin
== srcNormalProp
) ||
565 (srcTexProp
== srcNormalProp
) )
567 FFATAL(("Index set %d %d %d %d not supported in "
568 "calcVertexTangents()\n",
576 GeoIntegralProperty
*posIdx
= geo
->getIndex(Geometry::PositionsIndex
);
578 // HACK but without indices it crashes
579 if(posIdx
== NULL
|| posIdx
->size() == 0)
581 FFATAL(("Geo without pos indices in calcVertexTangents()\n"));
585 GeoVectorProperty
*positions
= geo
->getPositions();
587 // Get the positions property
588 if(positions
== NULL
)
590 FFATAL(("Geo without positions in calcVertexTangents()\n"));
594 GeoVectorProperty
*srcTexCoords
= geo
->getProperty(srcTexProp
);
596 // Get the positions property
597 if(srcTexCoords
== NULL
)
599 FFATAL(("Geo without srcTexCoords in calcVertexTangents()\n"));
603 GeoVectorProperty
*srcNormals
= geo
->getProperty(srcNormalProp
);
605 // Get the positions property
606 if(srcNormals
== NULL
)
608 FFATAL(("Geo without srcNormals in calcVertexTangents()\n"));
612 UInt32 posIdxCount
= posIdx
->size32();
614 tangentP
= GeoVec4fProperty::create();
615 binormalP
= GeoVec4fProperty::create();
617 tanBinIndexP
= GeoUInt32Property::create();
618 tanBinIndexP
->resize(posIdxCount
);
620 geo
->setProperty(tangentP
, dstPropTan
);
621 geo
->setIndex (tanBinIndexP
, dstPropTan
);
623 geo
->setProperty(binormalP
, dstPropBin
);
624 geo
->setIndex (tanBinIndexP
, dstPropBin
);
629 Vec4f
vect(0, 0, 0, 0);
632 std::vector
<Int32
> indexVec
;
636 // Size of properties is number of unique index tuples, which requires
637 // looking at all of them - we take a best effort guess here and resize
639 tangent
.resize(posIdxCount
, Vec3f::Null
);
640 binormal
.resize(posIdxCount
, Vec3f::Null
);
641 normal
.resize(posIdxCount
, Vec3f::Null
);
645 for( tI
= geo
->beginTriangles(), iTri
= 0;
646 tI
!= geo
->endTriangles();
649 for(k
= 0; k
< 3; ++k
)
651 indexVec
[0] = tI
.getPropertyIndex(Geometry::PositionsIndex
, k
);
652 indexVec
[1] = tI
.getPropertyIndex(srcNormalProp
, k
);
653 indexVec
[2] = tI
.getPropertyIndex(srcTexProp
, k
);
655 v
[k
] = indexDic
.entry(indexVec
);
657 if(v
[k
] >= Int32(propSize
))
661 // resize properties if inital guess was too small
662 if(propSize
>= tangent
.size())
664 tangent
.resize(1.5f
* tangent
.size() + 1, Vec3f::Null
);
665 binormal
.resize(1.5f
* binormal
.size() + 1, Vec3f::Null
);
666 normal
.resize(1.5f
* normal
.size() + 1, Vec3f::Null
);
669 // second, calculate tangent and binormal for every tri
670 Vec2f t0
, t1
, t2
, tex1
, tex2
;
671 Vec3f edge1
, edge2
, sdir
, tdir
;
673 t0
= tI
.getTexCoords(srcTexProp
, 0);
674 t1
= tI
.getTexCoords(srcTexProp
, 1);
675 t2
= tI
.getTexCoords(srcTexProp
, 2);
677 edge1
= tI
.getPosition(1) - tI
.getPosition(0),
678 edge2
= tI
.getPosition(2) - tI
.getPosition(0);
683 Real32 invDet
= (tex1
[0]*tex2
[1] - tex2
[0]*tex1
[1]);
687 invDet
= 1.0f
/ invDet
;
694 sdir
= invDet
* (tex2
[1]*edge1
- tex1
[1]*edge2
); // tangent
695 tdir
= invDet
* (tex1
[0]*edge2
- tex2
[0]*edge1
); // binormal
697 for(k
= 0; k
< 3; ++k
)
699 tangent
[v
[k
]] += sdir
;
700 binormal
[v
[k
]] += tdir
;
701 normal
[v
[k
]] = tI
.getNormal(srcNormalProp
, k
);
703 tanBinIndexP
->setValue(v
[k
], tI
.getIndex(k
));
707 // adjust size - resizing above may have been to big
708 if(tangent
.size() > propSize
)
710 tangent
.resize(propSize
);
711 binormal
.resize(propSize
);
712 normal
.resize(propSize
);
715 // orthogonalize vectors (Gram-Schmidt) and calc handedness
723 for(UInt32 i
= 0; i
< tangent
.size(); i
++)
727 N
= normal
[i
]; // must be normalized: n*n = 1
729 sign
= ((N
.cross(T
)).dot(B
) < 0) ? -1 : 1;
731 T
= T
- N
.dot(T
) * N
;
735 B
= B
- N
.dot(B
) * N
- T
.dot(B
) * T
;
739 vect
.setValues(T
[0], T
[1], T
[2], sign
);
741 tangentP
->editField().push_back(vect
);
743 vect
.setValues(B
[0], B
[1], B
[2], sign
);
745 binormalP
->editField().push_back(vect
);
749 /*! \ingroup GrpDrawablesGeometryUtils
752 void calcVertexTangents(Geometry
*geo
,
757 calcVertexTangentsProp(geo
,
758 srcTexIndex
+ Geometry::TexCoordsIndex
,
759 Geometry::NormalsIndex
,
764 /*! \ingroup GrpDrawablesGeometryUtils
767 void calcVertexTexCoordsProp2D(Geometry
*geo
,
776 Int32 S
= -1, T
= -1, n
= 3, i
, j
;
777 Real32 sDenom
, tDenom
, sMin
, tMin
;
779 GeoIntegralPropertyUnrecPtr ip
= geo
->getIndices ();
780 GeoVectorPropertyUnrecPtr posP
= geo
->getPositions();
781 GeoVectorPropertyUnrecPtr texP
;
783 if(posP
== NULL
|| !posP
->size() || ip
== NULL
|| !ip
->size())
785 FFATAL(("Geo without indices/ positions in calcVertexTexCoords()\n"));
789 if(propIndex
> Geometry::LastIndex
)
791 FFATAL(("invalid propIndex %d in calcVertexTexCoords()\n",
796 MFParentFieldContainerPtr::const_iterator pnI
;
798 for( pnI
= geo
->getMFParents()->begin();
799 pnI
!= geo
->getMFParents()->end ();
802 Node
*node
= dynamic_cast<Node
*>(*pnI
);
806 BoxVolume
&bVol
= node
->editVolume(true);
810 bVol
.getBounds(min
, max
);
812 Vec3f
dia(max
- min
);
814 for(i
= 0; i
< 3; i
++)
816 key
[i
].value
= dia
[i
];
820 for(i
= 1; i
< n
; i
++)
822 for(j
= n
-1; j
>= i
; j
--)
824 if (key
[j
-1].value
> key
[j
].value
)
848 FFATAL(("Geo without parents in calcVertexTexCoords()\n"));
852 texP
= GeoPnt2fProperty::create();
854 geo
->setProperty(texP
, propIndex
);
855 geo
->setIndex (ip
, propIndex
);
860 Int32 len
= posP
->size32();
864 for(i
= 0; i
< len
; i
++)
866 posP
->getValue(point
, i
);
868 texCoord
[0] = (point
[S
] - sMin
) / sDenom
;
869 texCoord
[1] = (point
[T
] - tMin
) / tDenom
;
871 texP
->setValue(texCoord
, i
);
875 void calcVertexTexCoords(Geometry
*geo
,
878 calcVertexTexCoordsProp2D(geo
, texIndex
+ Geometry::TexCoordsIndex
);
881 /*! \ingroup GrpDrawablesGeometryUtils
883 setIndexFromVRMLData creates an OSG::Geometry's interleaved index data
884 from VRML-style separate indices, see \ref PageSystemGeoFunctionsMakeGeo
887 \a coordIndex, \a normalIndex, \a colorIndex and \a texCoordIndex are
888 VRML97-style indices. \a ccw sets whether poylgons are defined
889 counter-clockwise or clockwise, \a normalPerVertex and \a colorPerVertex
890 specify bindings, and \a faceSet defines whether a VRML IndexedFaceSet or
891 an IndexedLineSet is being generated. See the VRML97 specification at
892 http://www.vrml.org/XXX for details.
894 Note: the \a convex and \a createNormals parameters are ignored right now!
897 Int32
setIndexFromVRMLData( Geometry
*geoPtr
,
898 std::vector
<Int32
> &coordIndex
,
899 std::vector
<Int32
> &normalIndex
,
900 std::vector
<Int32
> &colorIndex
,
901 std::vector
<Int32
> &texCoordIndex
,
904 bool normalPerVertex
,
909 /** define the bag type */
910 typedef std::vector
<Int32
> *IndexBagP
;
912 /** defines the Index Types */
926 /** holds the Index types as str, mainly for log/debug outputs */
928 static const char *indexTypeStr
[] =
937 "PRIMITIVE_INDEX_IT",
938 "PRIMITIVE_CREATE_IT"
942 GeoVectorPropertyUnrecPtr posPtr
;
943 GeoVectorPropertyUnrecPtr normalPtr
;
944 GeoVectorPropertyUnrecPtr colorPtr
;
945 GeoVectorPropertyUnrecPtr texCoordsPtr
;
946 GeoIntegralPropertyUnrecPtr lensPtr
;
947 GeoIntegralPropertyUnrecPtr geoTypePtr
;
949 GeoIntegralPropertyUnrecPtr posIndexPtr
= NULL
;
951 Int32 index
, pi
, typei
, primitiveN
= 0, vN
= 0; // i
952 Int32 pType
= 0, localPType
;
953 Int32 maxPType
= (faceSet
? 5 : 3);
954 Int32 minPType
= (faceSet
? 3 : 2);
955 Int32 beginIndex
, endIndex
, step
, len
, sysPType
= 0;
956 Int32 piN
= 0, ciN
= 0, niN
= 0, tiN
= 0;
957 Int32 pN
= 0, nN
= 0, cN
= 0, tN
= 0;
958 IndexType indexType
[4];
959 IndexType
&coordIT
= indexType
[0];
960 IndexType
&normalIT
= indexType
[1];
961 IndexType
&colorIT
= indexType
[2];
962 IndexType
&textureIT
= indexType
[3];
963 Int32 primitiveTypeCount
[6];
965 // Int16 indexMap[4], indexMapID[4];
966 // UInt32 uiNumTextures = 0;
968 IndexBagP indexBag
[4] =
976 GeoIntegralPropertyUnrecPtr indexOutBag
[4] =
984 UInt16 indexOutBagID
[4] =
986 Geometry::PositionsIndex
,
987 Geometry::NormalsIndex
,
988 Geometry::ColorsIndex
,
989 Geometry::TexCoordsIndex
992 //----------------------------------------------------------------------
995 // indexMap[0] = Geometry::MapPosition;
997 //----------------------------------------------------------------------
998 // get the property pointer and element count
999 posPtr
= geoPtr
->getPositions();
1000 pN
= ((posPtr
== NULL
) ? 0 : posPtr
->size32());
1002 normalPtr
= geoPtr
->getNormals();
1003 nN
= ((normalPtr
== NULL
) ? 0 : normalPtr
->size32());
1005 colorPtr
= geoPtr
->getColors();
1006 cN
= ((colorPtr
== NULL
) ? 0 : colorPtr
->size32());
1008 texCoordsPtr
= geoPtr
->getTexCoords();
1009 tN
= ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1011 texCoordsPtr
= geoPtr
->getTexCoords1();
1013 texCoordsPtr
= geoPtr
->getTexCoords2();
1015 texCoordsPtr
= geoPtr
->getTexCoords3();
1017 FDEBUG(("vertex attrib count P/N/C/T: %d/%d/%d/%d\n", pN
, nN
, cN
, tN
));
1019 //----------------------------------------------------------------------
1020 // check the vertex index and count the primitives
1021 primitiveN
= index
= 0;
1023 for(pType
= 0; pType
< 6; pType
++)
1024 primitiveTypeCount
[pType
] = 0;
1028 FWARNING(("No points in OSG::setIndexFromVRMLData()\n"));
1033 piN
= UInt32(coordIndex
.size());
1037 for(Int32 i
= 0; i
<= piN
; i
++)
1039 index
= (i
== piN
) ? -1 : coordIndex
[i
];
1041 if((index
< 0) && vN
)
1043 primitiveTypeCount
[(vN
> maxPType
) ? maxPType
: vN
]++;
1049 if(index
>= pN
&& i
!= piN
)
1051 FWARNING(("Point index (%d/%d) out of range\n",
1063 FWARNING(("No coordIndex in OSG::setIndexFromVRMLData()\n"));
1068 //----------------------------------------------------------------------
1069 // check the normal index
1071 normalIT
= UNKNOWN_IT
;
1073 niN
= UInt32(normalIndex
.size());
1076 { // have normal elements
1079 // normal per vertex
1082 // valid normal index number
1083 for(Int32 i
= 0; i
< piN
; i
++)
1084 { // check if normal index equals the coord index
1085 if(normalIndex
[i
] != coordIndex
[i
])
1087 normalIT
= VERTEX_IT
;
1092 if(normalIT
== UNKNOWN_IT
)
1094 // if equal than delete unneeded normal index
1095 normalIT
= VERTEX_DUP_IT
;
1100 // no or not enough normal index
1101 normalIT
= VERTEX_COORD_IT
;
1104 FWARNING(("Not enough normal index (%" PRISize
",%d)\n",
1105 normalIndex
.size(), piN
));
1106 normalIndex
.clear();
1112 // normal per primitive
1113 if(niN
>= primitiveN
)
1115 // use one normal index per primitive
1116 normalIT
= PRIMITIVE_INDEX_IT
;
1120 if(nN
>= primitiveN
)
1122 // use one normal per primitive
1123 normalIT
= PRIMITIVE_IT
;
1127 FINFO(("not enough normal index (%d,%d)\n",
1137 if (normalPerVertex)
1138 normalIT = VERTEX_CREATE_IT;
1140 normalIT = PRIMITIVE_CREATE_IT;
1143 normalIT
= EMPTY_IT
;
1146 //----------------------------------------------------------------------
1147 // check the color index
1149 colorIT
= UNKNOWN_IT
;
1151 ciN
= UInt32(colorIndex
.size());
1154 { // have color elements
1160 // valid color index number
1161 for(Int32 i
= 0; i
< piN
; i
++)
1162 { // check if color index equals the coord index
1163 if(colorIndex
[i
] != coordIndex
[i
])
1165 colorIT
= VERTEX_IT
;
1170 if(colorIT
== UNKNOWN_IT
)
1172 // if equal than delete unneeded color index
1173 colorIT
= VERTEX_DUP_IT
;
1178 // no or not enough color index
1179 colorIT
= VERTEX_COORD_IT
;
1182 FWARNING(("Not enough color index (%" PRISize
",%d)\n",
1183 colorIndex
.size(), piN
));
1190 // color per primitive
1191 if(ciN
>= primitiveN
)
1193 // use one color index per primitive
1194 colorIT
= PRIMITIVE_INDEX_IT
;
1198 if(cN
>= primitiveN
)
1200 // use one color per primitive
1201 colorIT
= PRIMITIVE_IT
;
1205 FINFO(("not enough color index (%d,%d)\n",
1216 //----------------------------------------------------------------------
1217 // check the texture index
1219 textureIT
= UNKNOWN_IT
;
1220 tiN
= UInt32(texCoordIndex
.size());
1222 { // have texture elemnts
1225 // valid texture index number
1226 for(Int32 i
= 0; i
< piN
; i
++)
1227 { // check if texture index equals the coord index
1228 if(texCoordIndex
[i
] != coordIndex
[i
])
1230 textureIT
= VERTEX_IT
;
1235 if(textureIT
== UNKNOWN_IT
)
1237 // if equal than delete unneeded texture index
1238 textureIT
= VERTEX_DUP_IT
;
1243 // no or not enough texture index
1244 textureIT
= VERTEX_COORD_IT
;
1247 FWARNING(("Not enough texCoord index (%" PRISize
",%d)\n",
1248 texCoordIndex
.size(), piN
));
1249 texCoordIndex
.clear();
1255 textureIT
= EMPTY_IT
;
1260 FDEBUG(("primitiveN: %d, 0/%d 1/%d 2/%d 3/%d 4/%d poly/%d\n",
1261 primitiveN
, primitiveTypeCount
[0],
1262 primitiveTypeCount
[1], primitiveTypeCount
[2],
1263 primitiveTypeCount
[3], primitiveTypeCount
[4],
1264 primitiveTypeCount
[5]));
1268 FDEBUG(("primitiveN: %d, 0/%d 1/%d 2/%d 3/%d\n", primitiveN
,
1269 primitiveTypeCount
[0], primitiveTypeCount
[1],
1270 primitiveTypeCount
[2], primitiveTypeCount
[3]));
1273 FDEBUG(("IndexType: coord: %s, color: %s, normal: %s, texture: %s \n",
1274 indexTypeStr
[coordIT
], indexTypeStr
[colorIT
], indexTypeStr
[
1275 normalIT
], indexTypeStr
[textureIT
]));
1277 //----------------------------------------------------------------------
1278 // check/create the indexPtr/lengthsPtr/geoTypePtr
1279 posIndexPtr
= geoPtr
->getIndex(Geometry::PositionsIndex
);
1281 if(posIndexPtr
== NULL
)
1283 posIndexPtr
= GeoUInt32Property::create();
1287 posIndexPtr
->clear();
1290 for(Int32 i
= 1; i
< 4; ++i
)
1292 indexOutBag
[i
] = geoPtr
->getIndex(indexOutBagID
[i
]);
1294 if(indexOutBag
[i
] != NULL
)
1296 indexOutBag
[i
]->clear();
1300 lensPtr
= geoPtr
->getLengths();
1304 lensPtr
= GeoUInt32Property::create();
1311 geoTypePtr
= geoPtr
->getTypes();
1313 if(geoTypePtr
== NULL
)
1315 geoTypePtr
= GeoUInt8Property::create();
1319 geoTypePtr
->clear();
1322 //----------------------------------------------------------------------
1323 // set lens/geoType/index/mapping the index mapping
1325 geoPtr
->setLengths(lensPtr
);
1326 geoPtr
->setTypes (geoTypePtr
);
1328 geoPtr
->setIndex(posIndexPtr
, Geometry::PositionsIndex
);
1330 //----------------------------------------------------------------------
1331 // create index face/line data
1333 for(pType
= minPType
; pType
<= maxPType
; pType
++)
1335 // check for the pType count
1336 if(primitiveTypeCount
[pType
])
1338 // calc len/sysPType
1343 len
= primitiveTypeCount
[pType
] * pType
;
1345 sysPType
= (pType
== 3) ? GL_TRIANGLES
: GL_QUADS
;
1356 len
= primitiveTypeCount
[pType
] * pType
;
1357 sysPType
= GL_LINES
;
1368 lensPtr
->push_back(len
);
1370 geoTypePtr
->push_back(sysPType
);
1374 beginIndex
= endIndex
= -1;
1376 for(Int32 i
= 0; i
<= piN
; i
++)
1378 if(((i
== piN
) && (coordIndex
[i
- 1] >= 0)) ||
1379 ((i
< piN
) && (coordIndex
[i
] < 0)))
1381 len
= i
- beginIndex
;
1390 endIndex
= beginIndex
- 1;
1397 localPType
= (len
> maxPType
) ? maxPType
: len
;
1399 if((beginIndex
>= 0) && (localPType
== pType
))
1403 sysPType
= faceSet
? GL_POLYGON
: GL_LINE_STRIP
;
1405 lensPtr
->push_back(len
);
1407 geoTypePtr
->push_back(sysPType
);
1411 for(pi
= beginIndex
; pi
!= endIndex
; pi
+= step
)
1413 posIndexPtr
->push_back(coordIndex
[pi
]);
1415 for(typei
= 1; typei
<= 3; typei
++)
1419 switch(indexType
[typei
])
1423 case VERTEX_COORD_IT
:
1428 index
= (*indexBag
[typei
])[pi
];
1436 case PRIMITIVE_INDEX_IT
:
1438 index
= (*indexBag
[typei
])[
1443 default: //X_CREATE_IT
1449 if(indexOutBag
[typei
] == NULL
)
1451 indexOutBag
[typei
] = GeoUInt32Property::create();
1454 indexOutBag
[typei
]->push_back(index
);
1461 triCount
+= len
- 2;
1465 beginIndex
= endIndex
= -1;
1467 else if(beginIndex
< 0)
1476 for(UInt32 i
= 1; i
< 4; ++i
)
1478 if((indexType
[i
] == VERTEX_COORD_IT
|| indexType
[i
] == VERTEX_DUP_IT
) &&
1479 (indexOutBag
[i
] == NULL
|| indexOutBag
[i
]->size() == 0 ) )
1481 geoPtr
->setIndex(posIndexPtr
, indexOutBagID
[i
]);
1483 else if(indexOutBag
[i
] != NULL
&& indexOutBag
[i
]->size() != 0)
1485 geoPtr
->setIndex(indexOutBag
[i
], indexOutBagID
[i
]);
1493 /*! \ingroup GrpDrawablesGeometryUtils
1495 setIndexFromIndexedX3DData creates an OSG::Geometry's interleaved index data
1496 from X3D-style separate indices, see \ref PageSystemGeoFunctionsMakeGeo
1499 The \a primitiveType defines the GL-Primtive (e.g. GL_LINE, GL_TRIANGLE_STRIP,
1500 GL_POLYGON) which should be used.
1502 \a coordIndex, \a normalIndex, \a colorIndex and \a texCoordIndex are
1503 X3D-style indices. \a ccw sets whether poylgons are defined
1504 counter-clockwise or clockwise, \a normalPerVertex and \a colorPerVertex
1505 specify bindings. See the X3D specification at
1506 http://www.web3d.org for details.
1508 Note: the \a convex and \a createNormals parameters are ignored right now!
1511 Int32
setIndexFromIndexedX3DData ( Geometry
*geoPtr
,
1512 std::vector
<Int32
> &coordIndex
,
1513 std::vector
<Int32
> &normalIndex
,
1514 std::vector
<Int32
> &colorIndex
,
1515 std::vector
<Int32
> &texCoordIndex
,
1516 Int32 primitiveType
,
1519 bool normalPerVertex
,
1520 bool colorPerVertex
,
1523 /** define the bag type */
1524 typedef std::vector
<Int32
> *IndexBagP
;
1526 /** defines the Index Types */
1540 /** holds the Index types as str, mainly for log/debug outputs */
1541 static const char *indexTypeStr
[] =
1550 "PRIMITIVE_INDEX_IT",
1551 "PRIMITIVE_CREATE_IT"
1554 GeoVectorPropertyUnrecPtr posPtr
;
1555 GeoVectorPropertyUnrecPtr normalPtr
;
1556 GeoVectorPropertyUnrecPtr colorPtr
;
1557 GeoVectorPropertyUnrecPtr texCoordsPtr
;
1559 GeoIntegralPropertyUnrecPtr lensPtr
;
1560 GeoIntegralPropertyUnrecPtr geoTypePtr
;
1561 GeoIntegralPropertyUnrecPtr posIndexPtr
= NULL
;
1563 //bool faceSet = (primitiveType == GL_POLYGON);
1564 Int32 index
, pi
, typei
, primitiveN
= 0, vN
= 0;
1565 Int32 pType
= 0, localPType
;
1566 Int32 maxPType
= 0; // = (faceSet ? 5 : 3);
1567 Int32 minPType
= 0; // = (faceSet ? 3 : 2);
1568 Int32 beginIndex
, endIndex
, step
, len
, sysPType
= 0;
1569 Int32 piN
= 0, ciN
= 0, niN
= 0, tiN
= 0;
1570 Int32 pN
= 0, nN
= 0, cN
= 0, tN
= 0;
1571 IndexType indexType
[4];
1572 IndexType
&coordIT
= indexType
[0];
1573 IndexType
&normalIT
= indexType
[1];
1574 IndexType
&colorIT
= indexType
[2];
1575 IndexType
&textureIT
= indexType
[3];
1576 Int32 primitiveTypeCount
[6];
1577 UInt32 triCount
= 0;
1579 IndexBagP indexBag
[4] =
1587 GeoIntegralPropertyUnrecPtr indexOutBag
[4] =
1595 UInt16 indexOutBagID
[4] =
1597 Geometry::PositionsIndex
,
1598 Geometry::NormalsIndex
,
1599 Geometry::ColorsIndex
,
1600 Geometry::TexCoordsIndex
1603 static const UInt32 uiNumTexCoords
= 8;
1605 UInt32 texCoordN
[uiNumTexCoords
] =
1617 UInt16 texCoordIdx
[uiNumTexCoords
] =
1619 Geometry::TexCoordsIndex
,
1620 Geometry::TexCoords1Index
,
1621 Geometry::TexCoords2Index
,
1622 Geometry::TexCoords3Index
,
1623 Geometry::TexCoords4Index
,
1624 Geometry::TexCoords5Index
,
1625 Geometry::TexCoords6Index
,
1626 Geometry::TexCoords7Index
1629 //----------------------------------------------------------------------
1631 coordIT
= VERTEX_IT
;
1633 //----------------------------------------------------------------------
1634 // set maxPType and minPTypr from primitiveType
1635 switch (primitiveType
)
1657 case GL_TRIANGLE_STRIP
:
1661 case GL_TRIANGLE_FAN
:
1678 FFATAL (( "Can not fill index; Invalid primitiveType: %d\n",
1683 //----------------------------------------------------------------------
1684 // get the property pointer and element count
1685 posPtr
= geoPtr
->getPositions();
1686 pN
= ((posPtr
== NULL
) ? 0 : posPtr
->size32());
1688 normalPtr
= geoPtr
->getNormals();
1689 nN
= ((normalPtr
== NULL
) ? 0 : normalPtr
->size32());
1691 colorPtr
= geoPtr
->getColors();
1692 cN
= ((colorPtr
== NULL
) ? 0 : colorPtr
->size32());
1694 texCoordsPtr
= geoPtr
->getTexCoords();
1695 tN
= ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1698 texCoordsPtr
= geoPtr
->getTexCoords1();
1699 texCoordN
[1] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1701 texCoordsPtr
= geoPtr
->getTexCoords2();
1702 texCoordN
[2] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1704 texCoordsPtr
= geoPtr
->getTexCoords3();
1705 texCoordN
[3] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1707 texCoordsPtr
= geoPtr
->getTexCoords4();
1708 texCoordN
[4] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1710 texCoordsPtr
= geoPtr
->getTexCoords5();
1711 texCoordN
[5] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1713 texCoordsPtr
= geoPtr
->getTexCoords6();
1714 texCoordN
[6] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1716 texCoordsPtr
= geoPtr
->getTexCoords7();
1717 texCoordN
[7] = ((texCoordsPtr
== NULL
) ? 0 : texCoordsPtr
->size32());
1719 FDEBUG(("vertex attrib count P/N/C/T: %d/%d/%d/%d\n", pN
, nN
, cN
, tN
));
1721 //----------------------------------------------------------------------
1722 // check the vertex index and count the primitives
1723 primitiveN
= index
= 0;
1725 for(pType
= 0; pType
< 6; pType
++)
1726 primitiveTypeCount
[pType
] = 0;
1730 FINFO(("No points in OSG::setIndexFromVRMLData()\n"));
1735 piN
= UInt32(coordIndex
.size());
1739 for(Int32 i
= 0; i
<= piN
; i
++)
1741 index
= (i
== piN
) ? -1 : coordIndex
[i
];
1743 if((index
< 0) && vN
)
1745 primitiveTypeCount
[(vN
> maxPType
) ? maxPType
: vN
]++;
1751 if(index
>= pN
&& i
!= piN
)
1753 FWARNING(("Point index (%d/%d) out of range", index
, pN
));
1763 FWARNING(("No coordIndex in OSG::setIndexFromVRMLData()\n"));
1768 //----------------------------------------------------------------------
1769 // check the normal index
1771 normalIT
= UNKNOWN_IT
;
1773 niN
= UInt32(normalIndex
.size());
1776 { // have normal elements
1779 // normal per vertex
1782 // valid normal index number
1783 for(Int32 i
= 0; i
< piN
; i
++)
1784 { // check if normal index equals the coord index
1785 if(normalIndex
[i
] != coordIndex
[i
])
1787 normalIT
= VERTEX_IT
;
1792 if(normalIT
== UNKNOWN_IT
)
1794 // if equal than delete unneeded normal index
1795 normalIT
= VERTEX_DUP_IT
;
1800 // no or not enough normal index
1801 normalIT
= VERTEX_COORD_IT
;
1805 FWARNING(("Not enough normal index (%" PRISize
",%d)\n",
1806 normalIndex
.size(), piN
));
1807 normalIndex
.clear();
1813 // normal per primitive
1814 if(niN
>= primitiveN
)
1816 // use one normal index per primitive
1817 normalIT
= PRIMITIVE_INDEX_IT
;
1821 if(nN
>= primitiveN
)
1823 // use one normal per primitive
1824 normalIT
= PRIMITIVE_IT
;
1828 FINFO(("not enough normal index (%d,%d)\n", nN
, primitiveN
));
1837 if (normalPerVertex)
1838 normalIT = VERTEX_CREATE_IT;
1840 normalIT = PRIMITIVE_CREATE_IT;
1843 normalIT
= EMPTY_IT
;
1846 //----------------------------------------------------------------------
1847 // check the color index
1848 colorIT
= UNKNOWN_IT
;
1849 ciN
= UInt32(colorIndex
.size());
1851 { // have color elements
1857 // valid color index number
1858 for(Int32 i
= 0; i
< piN
; i
++)
1859 { // check if color index equals the coord index
1860 if(colorIndex
[i
] != coordIndex
[i
])
1862 colorIT
= VERTEX_IT
;
1867 if(colorIT
== UNKNOWN_IT
)
1869 // if equal than delete unneeded color index
1870 colorIT
= VERTEX_DUP_IT
;
1875 // no or not enough color index
1876 colorIT
= VERTEX_COORD_IT
;
1879 FWARNING(("Not enough color index (%" PRISize
",%d)\n",
1880 colorIndex
.size(), piN
));
1887 // color per primitive
1888 if(ciN
>= primitiveN
)
1890 // use one color index per primitive
1891 colorIT
= PRIMITIVE_INDEX_IT
;
1895 if(cN
>= primitiveN
)
1897 // use one color per primitive
1898 colorIT
= PRIMITIVE_IT
;
1902 FINFO(("not enough color index (%d,%d)\n", cN
, primitiveN
));
1912 //----------------------------------------------------------------------
1913 // check the texture index
1914 textureIT
= UNKNOWN_IT
;
1915 tiN
= UInt32(texCoordIndex
.size());
1917 { // have texture elemnts
1920 // valid texture index number
1921 for(Int32 i
= 0; i
< piN
; i
++)
1922 { // check if texture index equals the coord index
1923 if(texCoordIndex
[i
] != coordIndex
[i
])
1925 textureIT
= VERTEX_IT
;
1930 if(textureIT
== UNKNOWN_IT
)
1932 // if equal than delete unneeded texture index
1933 textureIT
= VERTEX_DUP_IT
;
1938 // no or not enough texture index
1939 textureIT
= VERTEX_COORD_IT
;
1942 FWARNING(("Not enough texCoord index (%" PRISize
",%d)\n",
1943 texCoordIndex
.size(), piN
));
1944 texCoordIndex
.clear();
1950 textureIT
= EMPTY_IT
;
1953 FNOTICE (( "primitiveN: %d, %d, 0/%d 1/%d 2/%d 3/%d 4/%d 5/%d\n",
1955 primitiveN
, primitiveTypeCount
[0],
1956 primitiveTypeCount
[1], primitiveTypeCount
[2],
1957 primitiveTypeCount
[3], primitiveTypeCount
[4],
1958 primitiveTypeCount
[5]));
1960 FNOTICE (( "IndexType: coord: %s, color: %s, normal: %s, texture: %s \n",
1961 indexTypeStr
[coordIT
], indexTypeStr
[colorIT
],
1962 indexTypeStr
[normalIT
], indexTypeStr
[textureIT
]));
1964 //----------------------------------------------------------------------
1965 // check/create the indexPtr/lengthsPtr/geoTypePtr
1967 posIndexPtr
= geoPtr
->getIndex(Geometry::PositionsIndex
);
1969 if(posIndexPtr
== NULL
)
1971 posIndexPtr
= GeoUInt32Property::create();
1975 posIndexPtr
->clear();
1978 for(Int32 i
= 1; i
< 4; ++i
)
1980 indexOutBag
[i
] = geoPtr
->getIndex(indexOutBagID
[i
]);
1982 if(indexOutBag
[i
] != NULL
)
1984 indexOutBag
[i
]->clear();
1988 for(UInt32 i
= 0; i
< uiNumTexCoords
; ++i
)
1990 geoPtr
->setIndex(NULL
, texCoordIdx
[i
]);
1993 lensPtr
= geoPtr
->getLengths();
1997 lensPtr
= GeoUInt32Property::create();
2004 geoTypePtr
= geoPtr
->getTypes();
2006 if(geoTypePtr
== NULL
)
2008 geoTypePtr
= GeoUInt8Property::create();
2012 geoTypePtr
->clear();
2015 //----------------------------------------------------------------------
2016 // set lens/geoType/index/mapping the index mapping
2018 geoPtr
->setLengths(lensPtr
);
2019 geoPtr
->setTypes(geoTypePtr
);
2021 geoPtr
->setIndex(posIndexPtr
, Geometry::PositionsIndex
);
2023 //----------------------------------------------------------------------
2024 // create index face/line data
2026 for(pType
= minPType
; pType
<= maxPType
; pType
++)
2028 // check for the pType count
2029 if(primitiveTypeCount
[pType
])
2031 // calc len/sysPType
2033 if(pType
< maxPType
)
2035 len
= primitiveTypeCount
[pType
] * pType
;
2040 sysPType
= GL_POINTS
;
2043 sysPType
= GL_LINES
;
2046 sysPType
= GL_TRIANGLES
;
2049 sysPType
= GL_QUADS
;
2061 lensPtr
->push_back(len
);
2063 geoTypePtr
->push_back(sysPType
);
2067 beginIndex
= endIndex
= -1;
2069 for(Int32 i
= 0; i
<= piN
; i
++)
2071 if(((i
== piN
) && (coordIndex
[i
- 1] >= 0)) ||
2072 ((i
< piN
) && (coordIndex
[i
] < 0)))
2074 len
= i
- beginIndex
;
2083 endIndex
= beginIndex
- 1;
2088 localPType
= (len
> maxPType
) ? maxPType
: len
;
2090 if((beginIndex
>= 0) && (localPType
== pType
))
2094 sysPType
= primitiveType
;
2096 lensPtr
->push_back(len
);
2097 geoTypePtr
->push_back(sysPType
);
2101 for(pi
= beginIndex
; pi
!= endIndex
; pi
+= step
)
2103 posIndexPtr
->push_back(coordIndex
[pi
]);
2105 for(typei
= 1; typei
<= 3; typei
++)
2109 switch(indexType
[typei
])
2113 case VERTEX_COORD_IT
:
2117 index
= (*indexBag
[typei
])[pi
];
2122 case PRIMITIVE_INDEX_IT
:
2123 index
= (*indexBag
[typei
])[primitiveN
];
2125 default: //X_CREATE_IT
2132 if(indexOutBag
[typei
] == NULL
)
2134 indexOutBag
[typei
] =
2135 GeoUInt32Property::create();
2138 indexOutBag
[typei
]->push_back(index
);
2144 triCount
+= len
- 2;
2148 beginIndex
= endIndex
= -1;
2150 else if(beginIndex
< 0)
2158 for(UInt32 i
= 1; i
< 4; ++i
)
2160 if((indexType
[i
] == VERTEX_COORD_IT
|| indexType
[i
] == VERTEX_DUP_IT
) &&
2161 (indexOutBag
[i
] == NULL
|| indexOutBag
[i
]->size() == 0 ) )
2163 geoPtr
->setIndex(posIndexPtr
, indexOutBagID
[i
]);
2165 else if(indexOutBag
[i
] != NULL
&& indexOutBag
[i
]->size() != 0)
2167 geoPtr
->setIndex(indexOutBag
[i
], indexOutBagID
[i
]);
2169 else if(indexOutBag
[i
] != NULL
&& indexOutBag
[i
]->size() == 0)
2171 geoPtr
->setIndex(NULL
, indexOutBagID
[i
]);
2175 for(UInt32 i
= 1; i
< uiNumTexCoords
; ++i
)
2177 if(texCoordN
[i
] != 0)
2179 if((indexType
[3] == VERTEX_COORD_IT
||
2180 indexType
[3] == VERTEX_DUP_IT
) &&
2181 (indexOutBag
[3] == NULL
||
2182 indexOutBag
[3]->size() == 0 ) )
2184 geoPtr
->setIndex(posIndexPtr
, texCoordIdx
[i
]);
2186 else if(indexOutBag
[3] != NULL
&& indexOutBag
[3]->size() != 0)
2188 geoPtr
->setIndex(indexOutBag
[3], texCoordIdx
[i
]);
2194 for(UInt32 i
= 1; i
< 4; ++i
)
2196 indexOutBag
[i
] = NULL
;
2202 /*! \ingroup GrpDrawablesGeometryUtils
2204 Int32
createOptimizedPrimitives(Geometry
*geo
,
2208 UInt32 minFanEdgeCount
,
2217 StriperHalfEdgeGraph graph
;
2220 UInt32 startCost
= 0;
2221 UInt32 bestCost
= 0;
2222 UInt32 worstCost
= 0;
2226 UInt32 patchesN
= 0;
2227 Int32 invalidTriCount
= 0;
2235 Geometry::IndexBag oGeoIndexBag
= geo
->getUniqueIndexBag();
2238 UInt32 indexMapSize
= UInt32(oGeoIndexBag
.size());
2239 bool remapIndex
= (indexMapSize
> 1) ? true : false;
2244 calcPrimitiveCount(geo
, triN
, lineN
, pointN
, patchesN
);
2246 GeoVectorProperty
*posPtr
= geo
->getPositions();
2248 UInt32 pN
= ((posPtr
== NULL
) ? 0 : posPtr
->size32());
2250 GeoIntegralProperty
*posIndexPtr
=
2251 geo
->getIndex(Geometry::PositionsIndex
);
2253 // Calculate startCost.
2254 if(posIndexPtr
== NULL
)
2260 startCost
= posIndexPtr
->size32();
2263 // Leave early if we have no indices or positions.
2264 if (pN
== 0 || posIndexPtr
== NULL
)
2269 FDEBUG(("GeoOpt: start/tri cost: %d/%d imp: %d tri/line/point: %d/%d/%d\n",
2270 startCost
, (triN
* 3), indexMapSize
, triN
, lineN
, pointN
));
2272 inputT
= getSystemTime();
2274 invalidTriCount
= 0;
2276 if (!remapIndex
&& (pN
> (triN
* 3)))
2278 FINFO(("Force index remap for unusual vertex/tri count: %d/%d\n",
2287 graph
.reserve(triN
* 3, triN
, 8);
2289 std::vector
< Int32
> indexVec(indexMapSize
);
2291 UInt32 triCount
= 0;
2293 for(TriangleIterator tI
= geo
->beginTriangles();
2294 (triCount
< triN
) && (tI
!= geo
->endTriangles());
2299 for(Int32 i
= 0; i
< 3; i
++)
2301 Int32 index
= tI
.getIndex(i
);
2303 for(UInt32 j
= 0; j
< indexMapSize
; j
++)
2305 indexVec
[j
] = oGeoIndexBag
[j
].first
->getValue(index
);
2308 v
[i
] = indexDic
.entry(indexVec
);
2311 invalidTriCount
+= graph
.addTriangle(v
[0], v
[1], v
[2]) ? 0 : 1;
2316 FDEBUG(("Multi-index dic entry: %d/%d\n", indexDic
.entryCount(),
2321 graph
.reserve(osgMin(pN
, triN
* 3), triN
, 8);
2323 UInt32 triCount
= 0;
2325 for(TriangleIterator tI
= geo
->beginTriangles();
2326 (triCount
< triN
) && (tI
!= geo
->endTriangles());
2330 graph
.addTriangle(tI
.getPositionIndex(0),
2331 tI
.getPositionIndex(1),
2332 tI
.getPositionIndex(2)) ? 0 : 1;
2340 FNOTICE(("%d invalid tri during halfegde construction found\n",
2348 time
= getSystemTime();
2349 inputT
= time
- inputT
;
2351 bestCost
= triN
* 3 + 1;
2354 cost
= graph
.calcOptPrim(iteration
,
2364 if(cost
> worstCost
)
2369 bestCost
= worstCost
= 0;
2373 if(bestCost
&& (bestCost
< startCost
))
2375 GeoIntegralPropertyUnrecPtr lensPtr
;
2376 GeoIntegralPropertyUnrecPtr geoTypePtr
;
2378 // check/create the indexPtr/lengthsPtr/geoTypePtr
2380 lensPtr
= geo
->getLengths();
2384 lensPtr
= OSG::GeoUInt32Property::create();
2386 geo
->setLengths(lensPtr
);
2389 geoTypePtr
= geo
->getTypes();
2391 if(geoTypePtr
== NULL
)
2393 geoTypePtr
= OSG::GeoUInt8Property::create();
2395 geo
->setTypes(geoTypePtr
);
2399 time
= getSystemTime();
2400 optimizeT
= time
- optimizeT
;
2404 geoTypePtr
->clear();
2406 for(UInt32 i
= 0; i
< indexMapSize
; ++i
)
2408 oGeoIndexBag
[i
].first
->clear();
2412 FDEBUG(("Start graph.getPrimitive() loop (triN: %d)\n", triN
));
2414 UInt32 numPrimitives
= graph
.primitiveCount();
2416 std::vector
< std::vector
<UInt32
> > primIndex(numPrimitives
);
2418 const Int32 typeVec
[] =
2425 const Int32 typeN
= sizeof(typeVec
) / sizeof(Int32
);
2429 for(Int32 t
= 0; t
< typeN
; ++t
)
2431 UInt32 triCount
= 0;
2433 bool stitch
= false;
2434 UInt32 windingCorrection
= 0;
2435 UInt32 lastTriStripIndex
= 0;
2436 UInt32 totalTriStripLength
= 0;
2438 for(Int32 i
= 0; i
< Int32(numPrimitives
); ++i
)
2440 graph
.getPrimitive(primIndex
[i
], typeVec
[t
]);
2442 const Int32 n
= UInt32(primIndex
[i
].size());
2451 if(typeVec
[t
] == GL_TRIANGLES
)
2453 triCount
+= (n
/ 3);
2455 else if (typeVec
[t
] == GL_TRIANGLE_STRIP
)
2461 // add the previous index and the first of the
2462 // new one, but make sure winding is still correct.
2465 for(UInt32 j
= 0; j
< 1+windingCorrection
; ++j
)
2467 for(UInt32 k
= 0; k
< indexMapSize
; ++k
)
2469 oGeoIndexBag
[k
].first
->push_back(
2471 lastTriStripIndex
)[k
]);
2474 for(UInt32 k
= 0; k
< indexMapSize
; ++k
)
2476 oGeoIndexBag
[k
].first
->push_back(
2477 indexDic
.entry(primIndex
[i
][0])[k
]);
2482 for(UInt32 j
= 0; j
< 1+windingCorrection
; ++j
)
2484 posIndexPtr
->push_back(lastTriStripIndex
);
2487 posIndexPtr
->push_back(primIndex
[i
][0]);
2490 totalTriStripLength
+= 2 + windingCorrection
;
2494 windingCorrection
= n
% 2;
2495 lastTriStripIndex
= primIndex
[i
][n
- 1];
2499 lensPtr
->push_back(n
);
2500 geoTypePtr
->push_back(typeVec
[t
]);
2505 lensPtr
->push_back(n
);
2506 geoTypePtr
->push_back(typeVec
[t
]);
2511 for(Int32 j
= 0; j
< n
; ++j
)
2513 for(UInt32 k
= 0; k
< indexMapSize
; ++k
)
2515 Int32 index
= indexDic
.entry(primIndex
[i
][j
])[k
];
2516 oGeoIndexBag
[k
].first
->push_back(index
);
2522 for(Int32 j
= 0; j
< n
; ++j
)
2524 posIndexPtr
->push_back(primIndex
[i
][j
]);
2528 totalTriStripLength
+= n
;
2531 if(triCount
&& typeVec
[t
] == GL_TRIANGLES
)
2533 lensPtr
->push_back(triCount
* 3);
2534 geoTypePtr
->push_back(GL_TRIANGLES
);
2537 if(stitchStrips
&& totalTriStripLength
&&
2538 typeVec
[t
] == GL_TRIANGLE_STRIP
)
2540 lensPtr
->push_back(totalTriStripLength
);
2541 geoTypePtr
->push_back(GL_TRIANGLE_STRIP
);
2545 time
= getSystemTime();
2546 outputT
= time
- outputT
;
2548 FNOTICE(("Graph in/opt/out timing: %g/%g/%g \n", inputT
, optimizeT
,
2551 if(cost
!= bestCost
)
2553 FWARNING(("cost != bestCost: %d/%d; we lost some nodes !\n",
2558 FINFO(("OptResult: %2g%%, Sampling (%di): cost %d/%d \n",
2559 double(double(bestCost
) / double(
2561 ), iteration
, bestCost
, worstCost
));
2566 FINFO(("startCost (%d) <= bestCost (%d), triCost(%d); keep geo data\n",
2567 startCost
, bestCost
, (triN
* 3)));
2573 /*! \ingroup GrpDrawablesGeometryUtils
2576 void createConvexPrimitives(Geometry
*geo
)
2578 FFATAL(("createConvexPrimitives:: NYI!\n"));
2581 /*! Adjusts the indices of \a geoPtr such that data is as much as possible
2584 \ingroup GrpDrawablesGeometryUtils
2586 Int32
createSharedIndex(Geometry
*geoPtr
)
2588 UInt32 indexSharedCount
= 0, dataRemapCount
= 0, indexRemapCount
= 0;
2589 UInt32 iN
, index
, si
, sN
;
2590 UInt32 indexBlock
= 0, masterDSize
;
2592 GeoVectorProperty
*masterProp
= NULL
, *slaveProp
= NULL
;
2594 const UInt8
*masterData
;
2596 std::vector
<UInt32
> slaveDSizeVec
;
2597 std::vector
<const UInt8
*> slaveDataVec
;
2599 // data pointer and size pair
2600 typedef std::pair
<const UInt8
*, UInt32
> Mem
;
2604 std::map
<Mem
, UInt32
, memless
<Mem
> > memMap
;
2605 std::map
<Mem
, UInt32
, memless
<Mem
> >::iterator mmI
;
2607 GeoIntegralProperty
*indexPtr
;
2609 const UChar8
*dataElem
;
2611 std::vector
< Int32
> indexRemap
;
2613 Geometry::IndexBag indexBag
;
2617 if(geoPtr
->getPositions() != NULL
)
2619 // check/create indexPtr
2620 iN
= geoPtr
->getPositions()->size32();
2622 indexBag
= geoPtr
->getUniqueIndexBag();
2624 if(indexBag
.size() == 0)
2627 indexPtr
= GeoIndicesUI32::create();
2628 indexPtr
->resize(iN
);
2630 for(i
= 0; i
< iN
; i
++)
2631 indexPtr
->setValue(i
, i
);
2633 beginEditCP(geoPtr
);
2635 geoPtr
->setIndices(indexPtr
);
2640 FNOTICE(("non indexed geo not handled in createSharedIndex()\n"));
2647 FNOTICE(("Invalid geoPtr->getPositions() in createSharedIndex()\n"));
2653 FNOTICE(("Invalid geoPtr in createSharedIndex()\n"));
2658 // reset stat counter
2659 indexSharedCount
= 0;
2661 indexRemapCount
= 0;
2663 // iterator over all index properties
2664 for(UInt32 i
= 0; i
< indexBag
.size(); ++i
)
2666 // first property indexed by index i is the master property
2667 masterProp
= geoPtr
->getProperty(indexBag
[i
].second
[0]);
2668 masterData
= masterProp
->getData();
2670 if(masterProp
!= NULL
&& masterData
!= NULL
)
2672 // calc master data element size
2674 masterProp
->getFormatSize() *
2675 masterProp
->getDimension () +
2676 masterProp
->getStride ();
2678 // all other properties indexed by index i are slave properties
2679 // find and store slave property data and sizes
2680 slaveDataVec
.clear();
2681 slaveDSizeVec
.clear();
2683 // store pointers to data and sizes of slave properties
2684 for(UInt32 j
= 1; j
< indexBag
[i
].second
.size(); ++j
)
2686 slaveProp
= geoPtr
->getProperty(indexBag
[i
].second
[j
]);
2688 // there may be no property to the index
2689 if(slaveProp
== NULL
)
2692 if(slaveProp
->getData() != NULL
)
2694 slaveDataVec
.push_back(slaveProp
->getData () );
2695 slaveDSizeVec
.push_back(slaveProp
->getFormatSize() *
2696 slaveProp
->getDimension () );
2700 FWARNING(("createSharedIndex: slaveProp %d has no data!\n",
2701 indexBag
[i
].second
[j
]));
2705 indexPtr
= indexBag
[i
].first
; // index i
2707 sN
= UInt32(slaveDataVec
. size()); // number of slave properties
2708 iN
= UInt32(indexPtr
->size()); // number of indices
2713 indexRemap
.resize(masterProp
->size(), -1);
2716 masterProp
->getFormatSize() * masterProp
->getDimension();
2718 for(UInt32 j
= 0; j
< iN
; ++j
)
2720 index
= indexPtr
->getValue(j
);
2722 if(indexRemap
[index
] >= 0)
2724 if(indexRemap
[index
] == Int32(index
))
2730 indexPtr
->setValue(indexRemap
[index
], j
);
2736 // find/include the data block
2737 dataElem
= masterData
+ (index
* masterDSize
);
2739 masterMem
.first
= dataElem
;
2741 mmI
= memMap
.find(masterMem
);
2743 if(mmI
== memMap
.end())
2745 // index not found; store new data/index
2746 memMap
[masterMem
] = index
;
2747 indexRemap
[index
] = index
;
2751 // data found; check slave property
2752 for(si
= 0; si
< sN
; si
++)
2754 if(memcmp(slaveDataVec
[si
] + (index
* slaveDSizeVec
[si
]),
2755 slaveDataVec
[si
] + (mmI
->second
* slaveDSizeVec
[si
]),
2762 // no or valid slave data; remap the index
2763 indexPtr
->setValue(mmI
->second
, j
);
2765 indexRemap
[index
] = mmI
->second
;
2770 // invalid slave data; cannot remap index
2771 indexRemap
[index
] = index
;
2779 FWARNING(("Invalid masterProp %p, block: %d\n",
2780 static_cast<void *>(masterProp
), indexBlock
));
2783 FINFO(("Create sharedIndex: %d pass; "
2784 "data/index remap: %d/%d \n",
2785 indexBlock
, dataRemapCount
,
2789 return indexRemapCount
+ dataRemapCount
;
2792 Int32
createSingleIndex(Geometry
*geo
)
2794 typedef std::vector
<UInt16
>::iterator IndexIt
;
2796 Int32 returnValue
= -1;
2801 Geometry::IndexBag oGeoIndexBag
= geo
->getUniqueIndexBag();
2803 if(oGeoIndexBag
.size() == 1 || oGeoIndexBag
.size() == 0)
2808 Geometry::IndexBag::iterator bIt
= oGeoIndexBag
.begin();
2809 Geometry::IndexBag::iterator bEnd
= oGeoIndexBag
.end ();
2811 for(; bIt
!= bEnd
; ++bIt
)
2813 Geometry::IndexBag::iterator rIt
= bIt
+ 1;
2815 for(; rIt
!= bEnd
; )
2817 if(compareContainerEqual(bIt
->first
, rIt
->first
, true, true))
2819 bIt
->second
.insert(bIt
->second
.end (),
2820 rIt
->second
.begin(),
2821 rIt
->second
.end ());
2823 rIt
= oGeoIndexBag
.erase(rIt
);
2825 bEnd
= oGeoIndexBag
.end();
2834 if(oGeoIndexBag
.size() == 1)
2836 GeoIntegralProperty
*pIndex
= oGeoIndexBag
.front().first
;
2838 IndexIt pIt
= oGeoIndexBag
.front().second
.begin();
2839 IndexIt pEnd
= oGeoIndexBag
.front().second
.end ();
2841 for(; pIt
!= pEnd
; ++pIt
)
2843 geo
->setIndex(pIndex
, *pIt
);
2850 std::vector
<Int32
> indexVec
;
2851 std::vector
<Int32
> sIndex
;
2855 Int32 indexMapSize
= UInt32(oGeoIndexBag
.size());
2858 indexVec
.resize(indexMapSize
);
2860 Int32 indexCount
= oGeoIndexBag
.front().first
->size32();
2862 sIndex
.resize(indexCount
);
2864 for(Int32 i
= 0; i
< indexCount
; i
++)
2866 for(Int32 j
= 0; j
< indexMapSize
; j
++)
2868 indexVec
[j
] = oGeoIndexBag
[j
].first
->getValue(i
);
2871 sIndex
[i
] = indexDic
.entry(indexVec
);
2874 vCount
= indexDic
.entryCount();
2878 for(Int32 i
= 0; i
< indexMapSize
; i
++)
2882 oGeoIndexBag
[0].second
.insert(oGeoIndexBag
[0].second
.end (),
2883 oGeoIndexBag
[i
].second
.begin(),
2884 oGeoIndexBag
[i
].second
.end ());
2887 for(UInt32 j
= 0; j
< oGeoIndexBag
[i
].second
.size(); ++j
)
2889 GeoVectorProperty
*pP
=
2890 geo
->getProperty(oGeoIndexBag
[i
].second
[j
]);
2892 if(pP
== NULL
|| pP
->getData() == NULL
)
2895 UInt32 valueSize
= (pP
->getFormatSize() *
2896 pP
->getDimension () +
2899 const UInt8
*data
= pP
->getData();
2901 GeoPropertyRefPtr pCloneProp
= pP
->clone();
2903 GeoVectorProperty
*pClone
=
2904 dynamic_cast<GeoVectorProperty
*>(pCloneProp
.get());
2906 pClone
->resize(vCount
);
2908 UInt8
*pData
= pClone
->editData();
2910 for(Int32 k
= 0; k
< vCount
; k
++)
2912 UInt32 index
= indexDic
.entry(k
)[i
];
2914 memcpy(pData
+ (valueSize
* k
),
2915 data
+ (valueSize
* index
),
2919 geo
->setProperty(pClone
,
2920 oGeoIndexBag
[i
].second
[j
]);
2925 oGeoIndexBag
.front().first
->clear();
2927 for(Int32 i
= 0; i
< indexCount
; i
++)
2929 oGeoIndexBag
.front().first
->push_back(sIndex
[i
]);
2932 GeoIntegralProperty
*pIndex
= oGeoIndexBag
.front().first
;
2934 IndexIt pIt
= oGeoIndexBag
.front().second
.begin();
2935 IndexIt pEnd
= oGeoIndexBag
.front().second
.end ();
2937 for(; pIt
!= pEnd
; ++pIt
)
2939 geo
->setIndex(pIndex
, *pIt
);
2947 /*! \ingroup GrpDrawablesGeometryUtils
2949 Calculate some basic statistics of the Geometry.
2951 UInt32
calcPrimitiveCount(Geometry
*geo
,
2957 GeoIntegralProperty
*geoTypePtr
;
2958 GeoIntegralProperty
*lensPtr
;
2960 UInt32 lN
, tN
, len
, type
;
2962 // TODO; should we really reset the values ?
2963 triangle
= line
= point
= patches
= 0;
2967 FINFO(("No geo in calcPrimitiveCount\n"));
2971 lensPtr
= geo
->getLengths();
2973 lN
= (lensPtr
== NULL
) ? 0 : lensPtr
->size32();
2976 geoTypePtr
= geo
->getTypes();
2978 tN
= (geoTypePtr
== NULL
) ? 0 : geoTypePtr
->size32();
2980 if((tN
== 0) || (lN
!= 0 && tN
!= lN
) || (lN
== 0 && tN
!= 1))
2985 for(UInt32 i
= 0; i
< geoTypePtr
->size(); ++i
)
2987 geoTypePtr
->getValue(type
, i
);
2991 lensPtr
->getValue(len
, i
);
2995 GeoVectorProperty
*pos
= geo
->getPositions();
2999 FINFO(("calcPrimitiveCount: no Points!\n"));
3003 len
= pos
->size32();
3021 triangle
+= len
/ 3;
3023 case GL_TRIANGLE_STRIP
:
3024 triangle
+= len
- 2;
3026 case GL_TRIANGLE_FAN
:
3027 triangle
+= len
- 2;
3030 triangle
+= len
/ 2;
3033 triangle
+= len
- 2;
3036 triangle
+= len
- 2;
3042 FWARNING(("calcPrimitiveCount(): Invalid geoType: %d\n",
3049 return triangle
+ line
+ point
;
3052 /*! \ingroup GrpDrawablesGeometryUtils
3054 Create a geometry of the vertex normals of the object. Useful for Visualizing
3057 \warning It does not check whether the normals are actually vertex normals,
3058 it just uses them as if.
3061 NodeTransitPtr
calcVertexNormalsGeo(Geometry
*geo
,
3064 GeoPnt3fPropertyUnrecPtr pnts
= GeoPnt3fProperty::create();
3068 PrimitiveIterator
pi(geo
);
3070 if(1 /* no easy way to check right now */ )
3072 for(pi
= geo
->beginPrimitives(); pi
!= geo
->endPrimitives(); ++pi
)
3074 for(UInt32 k
= 0; k
< pi
.getLength(); k
++)
3076 pnts
->push_back(pi
.getPosition(k
));
3077 pnts
->push_back(pi
.getPosition(k
) + length
* pi
.getNormal(k
));
3083 Pnt3f
center(0, 0, 0);
3085 for(pi
= geo
->beginPrimitives(); pi
!= geo
->endPrimitives(); ++pi
)
3087 for(UInt32 k
= 0; k
< pi
.getLength(); k
++)
3089 center
[0] += pi
.getPosition(k
)[0];
3090 center
[1] += pi
.getPosition(k
)[1];
3091 center
[2] += pi
.getPosition(k
)[2];
3094 pnts
->push_back(center
);
3095 pnts
->push_back(center
+ length
* pi
.getNormal(0));
3099 GeoIntegralPropertyUnrecPtr type
= GeoUInt8Property::create();
3101 type
->push_back(GL_LINES
);
3103 GeoIntegralPropertyUnrecPtr lens
= GeoUInt32Property::create();
3105 lens
->push_back(pnts
->size32());
3107 GeometryUnrecPtr g
= Geometry::create();
3109 g
->setTypes (type
);
3110 g
->setLengths (lens
);
3111 g
->setPositions(pnts
);
3112 g
->setMaterial (getDefaultUnlitMaterial());
3114 return makeNodeFor(g
);
3117 /*! \ingroup GrpDrawablesGeometryUtils
3119 void updateVertexNormalsGeo( Geometry
*pGeo
,
3121 const Geometry
*pRefGeo
)
3123 GeoPnt3fProperty
*pnts
=
3124 dynamic_cast<GeoPnt3fProperty
*>(
3125 pGeo
->getProperty(Geometry::PositionsIndex
));
3127 GeoIntegralProperty
*type
= pGeo
->getTypes();
3128 GeoIntegralProperty
*lens
= pGeo
->getLengths();
3130 if(pnts
== NULL
|| type
== NULL
|| lens
== NULL
)
3139 PrimitiveIterator
pi(pRefGeo
);
3141 if(1 /* no easy way to check right now */ )
3143 for(pi
= pRefGeo
->beginPrimitives();
3144 pi
!= pRefGeo
->endPrimitives (); ++pi
)
3146 for(UInt32 k
= 0; k
< pi
.getLength(); k
++)
3148 pnts
->push_back(pi
.getPosition(k
));
3149 pnts
->push_back(pi
.getPosition(k
) + length
* pi
.getNormal(k
));
3154 type
->push_back(GL_LINES
);
3156 lens
->push_back(pnts
->size());
3160 /*! \ingroup GrpDrawablesGeometryUtils
3162 Create a geometry of the face normals of the object. Useful for Visualizing
3165 \warning It does not check whether the normals are actually face normals,
3166 it just uses them as if.
3169 NodeTransitPtr
calcFaceNormalsGeo(Geometry
*geo
,
3172 NodeTransitPtr p
= Node::create();
3173 GeometryUnrecPtr g
= Geometry::create();
3174 GeoPnt3fPropertyUnrecPtr pnts
= GeoPnt3fProperty::create();
3175 GeoUInt32PropertyUnrecPtr index
= GeoUInt32Property::create();
3176 GeoUInt8PropertyUnrecPtr type
= GeoUInt8Property::create();
3177 GeoUInt32PropertyUnrecPtr lens
= GeoUInt32Property::create();
3181 FaceIterator faceIter
= geo
->beginFaces();
3184 for(; faceIter
!= geo
->endFaces(); ++faceIter
)
3190 for(UInt16 i
= 0; i
< faceIter
.getLength(); ++i
)
3192 center
[0] += faceIter
.getPosition(i
)[0] / faceIter
.getLength();
3193 center
[1] += faceIter
.getPosition(i
)[1] / faceIter
.getLength();
3194 center
[2] += faceIter
.getPosition(i
)[2] / faceIter
.getLength();
3197 pnts
->push_back(center
);
3199 switch(faceIter
.getType())
3201 case GL_TRIANGLE_STRIP
:
3202 pnts
->push_back(center
+ length
* faceIter
.getNormal(2));
3204 case GL_TRIANGLE_FAN
:
3205 pnts
->push_back(center
+ length
* faceIter
.getNormal(2));
3208 pnts
->push_back(center
+ length
* faceIter
.getNormal(3));
3211 //does not matter which point's normal
3212 pnts
->push_back(center
+ length
* faceIter
.getNormal(0));
3217 for(UInt32 i
= 0; i
< pnts
->size(); i
++)
3218 index
->push_back(i
);
3220 type
->push_back(GL_LINES
);
3222 lens
->push_back(index
->size32());
3224 g
->setTypes (type
);
3225 g
->setLengths (lens
);
3226 g
->setIndices (index
);
3227 g
->setPositions(pnts
);
3228 g
->setMaterial (getDefaultUnlitMaterial());
3235 /*! \ingroup GrpDrawablesGeometryUtils
3237 void separateProperties(Geometry
*geo
)
3239 FFATAL(("separateProperties: not implemented yet!\n"));
3243 /*! \ingroup GrpDrawablesGeometryUtils
3245 void mergeGeometries(std::vector
<Node
*> &nodes
,
3246 std::vector
<Node
*> &results
)
3248 FFATAL(("mergeGeometries: not implemented yet!\n"));
3255 // this anonymous namespace contains functions that are implementation
3256 // details for geometry merging
3258 /*! Returns the format to be used when merging a property of \a format1 with
3261 UInt32
calcMergeFormat(UInt32 format1
, UInt32 format2
)
3263 UInt32 format
= GL_BYTE
;
3270 case GL_BYTE
: format
= GL_BYTE
; break;
3271 case GL_UNSIGNED_BYTE
: format
= GL_SHORT
; break;
3272 case GL_SHORT
: format
= GL_SHORT
; break;
3273 case GL_UNSIGNED_SHORT
: format
= GL_INT
; break;
3274 case GL_INT
: format
= GL_INT
; break;
3275 case GL_UNSIGNED_INT
: format
= GL_INT
; break;
3277 case GL_FLOAT
: format
= GL_FLOAT
; break;
3278 #ifndef OSG_OGL_NO_DOUBLE
3279 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3284 case GL_UNSIGNED_BYTE
:
3287 case GL_BYTE
: format
= GL_SHORT
; break;
3288 case GL_UNSIGNED_BYTE
: format
= GL_UNSIGNED_BYTE
; break;
3289 case GL_SHORT
: format
= GL_SHORT
; break;
3290 case GL_UNSIGNED_SHORT
: format
= GL_UNSIGNED_SHORT
; break;
3291 case GL_INT
: format
= GL_INT
; break;
3292 case GL_UNSIGNED_INT
: format
= GL_UNSIGNED_INT
; break;
3294 case GL_FLOAT
: format
= GL_FLOAT
; break;
3295 #ifndef OSG_OGL_NO_DOUBLE
3296 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3304 case GL_BYTE
: format
= GL_SHORT
; break;
3305 case GL_UNSIGNED_BYTE
: format
= GL_SHORT
; break;
3306 case GL_SHORT
: format
= GL_SHORT
; break;
3307 case GL_UNSIGNED_SHORT
: format
= GL_INT
; break;
3308 case GL_INT
: format
= GL_INT
; break;
3309 case GL_UNSIGNED_INT
: format
= GL_INT
; break;
3311 case GL_FLOAT
: format
= GL_FLOAT
; break;
3312 #ifndef OSG_OGL_NO_DOUBLE
3313 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3318 case GL_UNSIGNED_SHORT
:
3321 case GL_BYTE
: format
= GL_INT
; break;
3322 case GL_UNSIGNED_BYTE
: format
= GL_UNSIGNED_SHORT
; break;
3323 case GL_SHORT
: format
= GL_INT
; break;
3324 case GL_UNSIGNED_SHORT
: format
= GL_UNSIGNED_SHORT
; break;
3325 case GL_INT
: format
= GL_INT
; break;
3326 case GL_UNSIGNED_INT
: format
= GL_UNSIGNED_INT
; break;
3328 case GL_FLOAT
: format
= GL_FLOAT
; break;
3329 #ifndef OSG_OGL_NO_DOUBLE
3330 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3338 case GL_BYTE
: format
= GL_INT
; break;
3339 case GL_UNSIGNED_BYTE
: format
= GL_INT
; break;
3340 case GL_SHORT
: format
= GL_INT
; break;
3341 case GL_UNSIGNED_SHORT
: format
= GL_INT
; break;
3342 case GL_INT
: format
= GL_INT
; break;
3343 case GL_UNSIGNED_INT
: format
= GL_INT
; break;
3345 case GL_FLOAT
: format
= GL_FLOAT
; break;
3346 #ifndef OSG_OGL_NO_DOUBLE
3347 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3352 case GL_UNSIGNED_INT
:
3355 case GL_BYTE
: format
= GL_INT
; break;
3356 case GL_UNSIGNED_BYTE
: format
= GL_UNSIGNED_INT
; break;
3357 case GL_SHORT
: format
= GL_INT
; break;
3358 case GL_UNSIGNED_SHORT
: format
= GL_UNSIGNED_INT
; break;
3359 case GL_INT
: format
= GL_INT
; break;
3360 case GL_UNSIGNED_INT
: format
= GL_UNSIGNED_INT
; break;
3362 case GL_FLOAT
: format
= GL_FLOAT
; break;
3363 #ifndef OSG_OGL_NO_DOUBLE
3364 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3372 case GL_BYTE
: format
= GL_FLOAT
; break;
3373 case GL_UNSIGNED_BYTE
: format
= GL_FLOAT
; break;
3374 case GL_SHORT
: format
= GL_FLOAT
; break;
3375 case GL_UNSIGNED_SHORT
: format
= GL_FLOAT
; break;
3376 case GL_INT
: format
= GL_FLOAT
; break;
3377 case GL_UNSIGNED_INT
: format
= GL_FLOAT
; break;
3379 case GL_FLOAT
: format
= GL_FLOAT
; break;
3380 #ifndef OSG_OGL_NO_DOUBLE
3381 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3386 #ifndef OSG_OGL_NO_DOUBLE
3390 case GL_BYTE
: format
= GL_DOUBLE
; break;
3391 case GL_UNSIGNED_BYTE
: format
= GL_DOUBLE
; break;
3392 case GL_SHORT
: format
= GL_DOUBLE
; break;
3393 case GL_UNSIGNED_SHORT
: format
= GL_DOUBLE
; break;
3394 case GL_INT
: format
= GL_DOUBLE
; break;
3395 case GL_UNSIGNED_INT
: format
= GL_DOUBLE
; break;
3397 case GL_FLOAT
: format
= GL_DOUBLE
; break;
3398 case GL_DOUBLE
: format
= GL_DOUBLE
; break;
3407 /*! Determines a format to store the combination of \a prop1 and \a prop2.
3408 If \a combineValues is \c true the contents are scanned to ensure the
3409 determined format can store the sum of the largest entries.
3411 void calcMergePropertyType(
3412 const GeoIntegralProperty
*prop1
,
3413 const GeoIntegralProperty
*prop2
,
3417 UInt32 form1
= prop1
->getFormat();
3418 UInt32 form2
= prop2
->getFormat();
3420 format
= calcMergeFormat(form1
, form2
);
3422 if(combineValues
&& format
!= GL_INT
&& format
!= GL_UNSIGNED_INT
)
3424 Int64 max1
= TypeTraits
<Int64
>::getMin();
3425 Int64 max2
= TypeTraits
<Int64
>::getMin();
3427 for(UInt32 i
= 0; i
< prop1
->size(); ++i
)
3429 if(max1
< prop1
->getValue
<Int64
>(i
))
3430 max1
= prop1
->getValue
<Int64
>(i
);
3433 for(UInt32 i
= 0; i
< prop2
->size(); ++i
)
3435 if(max2
< prop2
->getValue
<Int64
>(i
))
3436 max2
= prop2
->getValue
<Int64
>(i
);
3439 if(format
== GL_BYTE
&&
3440 (max1
+ max2
) > TypeTraits
<Int8
>::getMax() )
3444 else if(format
== GL_UNSIGNED_BYTE
&&
3445 (max1
+ max2
) > TypeTraits
<UInt8
>::getMax() )
3447 format
= GL_UNSIGNED_SHORT
;
3449 else if(format
== GL_SHORT
&&
3450 (max1
+ max2
) > TypeTraits
<Int16
>::getMax() )
3454 else if(format
== GL_UNSIGNED_SHORT
&&
3455 (max1
+ max2
) > TypeTraits
<UInt16
>::getMax() )
3457 format
= GL_UNSIGNED_INT
;
3462 /*! Determines a format to store the combination of \a prop1 and \a prop2.
3464 void calcMergePropertyType(
3465 const GeoVectorProperty
*prop1
,
3466 const GeoVectorProperty
*prop2
,
3467 UInt32
&format
, UInt32
&dim
,
3468 UInt32
&vecType
, UInt32
&normalize
)
3470 UInt32 dim1
= prop1
->getDimension ();
3471 UInt32 dim2
= prop2
->getDimension ();
3472 UInt32 form1
= prop1
->getFormat ();
3473 UInt32 form2
= prop2
->getFormat ();
3474 UInt32 vecType1
= prop1
->getVectorType();
3475 UInt32 vecType2
= prop2
->getVectorType();
3476 bool normalize1
= prop1
->getNormalize ();
3477 bool normalize2
= prop2
->getNormalize ();
3479 format
= calcMergeFormat(form1
, form2
);
3480 dim
= osgMax (dim1
, dim2
);
3482 if(vecType1
!= vecType2
)
3484 FWARNING(("calcMergePropertyType: Can not merge properties with "
3485 "conflicting vecTypes.\n"));
3492 if(normalize1
!= normalize2
)
3494 FWARNING(("calcMergePropertyType: Can not merge normalizing and "
3495 "non-normalizing property.\n"));
3499 normalize
= normalize1
;
3503 GeoIntegralPropertyTransitPtr
mergeIntegralProp(
3504 const GeoIntegralProperty
*src1Prop
,
3505 const GeoIntegralProperty
*src2Prop
) OSG_UNUSED_ATTRIB
;
3507 /*! Merges integral properties by appending \a src1Prop and \a src2Prop to a
3509 \note It is intended to merge the types and length properties.
3511 GeoIntegralPropertyTransitPtr
mergeIntegralProp(
3512 const GeoIntegralProperty
*src1Prop
,
3513 const GeoIntegralProperty
*src2Prop
)
3515 GeoIntegralPropertyTransitPtr dstProp
;
3518 calcMergePropertyType(src1Prop
, src2Prop
, false, dstFormat
);
3519 dstProp
= GeoPropertyFactory::the()->create(dstFormat
);
3521 UInt32 szSrc1
= src1Prop
->size32();
3522 UInt32 szSrc2
= src2Prop
->size32();
3524 // TODO: Optimize for matching src and dst types by not using generic
3526 for(UInt32 i
= 0; i
< szSrc1
; ++i
)
3527 dstProp
->addValue(src1Prop
->getValue(i
));
3529 for(UInt32 i
= 0; i
< szSrc2
; ++i
)
3530 dstProp
->addValue(src2Prop
->getValue(i
));
3538 UInt32
get(UInt32 idx
) const;
3539 void set(UInt32 idx
, UInt32 val
);
3541 IndexMap(void) : _iMap() {}
3544 typedef std::vector
<UInt32
> IMap
;
3550 UInt32
IndexMap::get(UInt32 idx
) const
3554 if(idx
>= _iMap
.size())
3555 returnValue
= TypeTraits
<UInt32
>::getMax();
3557 returnValue
= _iMap
[idx
];
3563 void IndexMap::set(UInt32 idx
, UInt32 val
)
3565 if(idx
>= _iMap
.size())
3566 _iMap
.resize(idx
+ 1, TypeTraits
<UInt32
>::getMax());
3572 /*! Copies and rewrites the index \a srcIdx to \a dstIdx storing the mapping
3573 between old and new indices in \a idxMap.
3574 This function must be called with a correct type argument.
3576 \warning \a dstIdx is expected to have sufficient storage allocated.
3578 template <class DescTypeT
> inline
3579 void copyIndex( GeoIntegralProperty
*dstIdx
,
3580 const GeoIntegralProperty
*srcIdx
,
3586 typedef TypedGeoIntegralProperty
<DescTypeT
> TypedProp
;
3587 typedef typename
TypedProp::StoredType StoredType
;
3588 typedef typename
TypedProp::StoredFieldType StoredField
;
3590 TypedProp
*typedDst
= dynamic_cast< TypedProp
*>(dstIdx
);
3591 const TypedProp
*typedSrc
= dynamic_cast<const TypedProp
*>(srcIdx
);
3592 StoredField
&dstF
= typedDst
->editField();
3593 const StoredField
&srcF
= typedSrc
->getField ();
3595 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3597 StoredType si
= srcF
[i
];
3598 UInt32 di
= idxMap
.get(si
);
3600 if(di
== TypeTraits
<UInt32
>::getMax())
3606 dstF
[i
+ dstOffset
] = di
;
3611 /*! Copies and rewrites the index \a srcIdx to \a dstIdx storing the mapping
3612 between old and new indices in \a idxMap.
3614 \warning \a dstIdx is expected to have sufficient storage allocated.
3617 void copyIndex( GeoIntegralProperty
*dstIdx
,
3618 const GeoIntegralProperty
*srcIdx
,
3624 UInt32 dstFormat
= dstIdx
->getFormat();
3625 UInt32 srcFormat
= srcIdx
->getFormat();
3627 if(dstFormat
== srcFormat
)
3629 // if the types are equal, use more efficient copying
3633 case GL_UNSIGNED_BYTE
:
3634 copyIndex
<GeoUInt8PropertyDesc
>(
3635 dstIdx
, srcIdx
, srcSz
, idxMap
, offset
, dstOffset
);
3638 case GL_UNSIGNED_SHORT
:
3639 copyIndex
<GeoUInt16PropertyDesc
>(
3640 dstIdx
, srcIdx
, srcSz
, idxMap
, offset
, dstOffset
);
3643 case GL_UNSIGNED_INT
:
3644 copyIndex
<GeoUInt32PropertyDesc
>(
3645 dstIdx
, srcIdx
, srcSz
, idxMap
, offset
, dstOffset
);
3652 // fallback to using the generic interface
3654 typedef GeoIntegralProperty::MaxTypeT IndexType
;
3656 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3658 IndexType si
= srcIdx
->getValue
<IndexType
>(i
);
3659 IndexType di
= idxMap
.get(si
);
3661 if(di
== TypeTraits
<UInt32
>::getMax())
3667 dstIdx
->setValue(di
, i
+ dstOffset
);
3672 /*! Copies from \a srcProp to \a dstProp the first srcSz values and stores them
3673 at positions starting at \a dstOffset.
3674 This function must be called with a correct type argument.
3676 \warning \a dstProp is expected to have sufficient storage allocated.
3678 template <class DescTypeT
> inline
3679 void copyIntegral( GeoIntegralProperty
*dstProp
,
3680 const GeoIntegralProperty
*srcProp
,
3684 typedef TypedGeoIntegralProperty
<DescTypeT
> TypedProp
;
3685 typedef typename
TypedProp::StoredFieldType StoredField
;
3687 TypedProp
*typedDst
= dynamic_cast< TypedProp
*>(dstProp
);
3688 const TypedProp
*typedSrc
= dynamic_cast<const TypedProp
*>(srcProp
);
3689 StoredField
&dstF
= typedDst
->editField();
3690 const StoredField
&srcF
= typedSrc
->getField ();
3692 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3693 dstF
[dstOffset
+ i
] = srcF
[i
];
3696 /*! Copies from \a srcProp to \a dstProp the first srcSz values and stores them
3697 at positions starting at \a dstOffset.
3699 \warning \a dstProp is expected to have sufficient storage allocated.
3702 void copyIntegral( GeoIntegralProperty
*dstProp
,
3703 const GeoIntegralProperty
*srcProp
,
3707 UInt32 dstFormat
= dstProp
->getFormat();
3708 UInt32 srcFormat
= srcProp
->getFormat();
3710 if(dstFormat
== srcFormat
)
3712 // if the types are equal, use more efficient copying
3716 case GL_UNSIGNED_BYTE
:
3717 copyIntegral
<GeoUInt8PropertyDesc
>(
3718 dstProp
, srcProp
, srcSz
, dstOffset
);
3721 case GL_UNSIGNED_SHORT
:
3722 copyIntegral
<GeoUInt16PropertyDesc
>(
3723 dstProp
, srcProp
, srcSz
, dstOffset
);
3726 case GL_UNSIGNED_INT
:
3727 copyIntegral
<GeoUInt32PropertyDesc
>(
3728 dstProp
, srcProp
, srcSz
, dstOffset
);
3734 // fallback to using the generic interface
3736 typedef GeoIntegralProperty::MaxTypeT ValueType
;
3738 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3739 dstProp
->setValue(srcProp
->getValue
<ValueType
>(i
), dstOffset
+ i
);
3743 template <class DescTypeT
> inline
3744 void copyVectorMapped( GeoVectorProperty
*dstProp
,
3745 const GeoVectorProperty
*srcProp
,
3746 const GeoIntegralProperty
*srcIdx
,
3748 const IndexMap
&idxMap
)
3750 typedef GeoIntegralProperty::MaxTypeT IndexType
;
3751 typedef TypedGeoVectorProperty
<DescTypeT
> TypedProp
;
3752 typedef typename
TypedProp::StoredFieldType StoredField
;
3754 TypedProp
*typedDst
= dynamic_cast< TypedProp
*>(dstProp
);
3755 const TypedProp
*typedSrc
= dynamic_cast<const TypedProp
*>(srcProp
);
3756 StoredField
&dstF
= typedDst
->editField();
3757 const StoredField
&srcF
= typedSrc
->getField ();
3759 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3761 IndexType si
= srcIdx
->getValue
<IndexType
>(i
);
3762 IndexType di
= idxMap
.get(si
);
3764 dstF
[di
] = srcF
[si
];
3768 /*! Copies from \a srcProp to \a dstProp values indexed by the first \a srcSz
3769 indices from \a srcIdx. The values are stored at the positions indicated
3772 \warning \a dstProp is expected to have sufficient storage allocated.
3775 void copyVectorMapped( GeoVectorProperty
*dstProp
,
3776 const GeoVectorProperty
*srcProp
,
3777 const GeoIntegralProperty
*srcIdx
,
3779 const IndexMap
&idxMap
)
3781 UInt32 dstFormat
= dstProp
->getFormat ();
3782 UInt32 dstDim
= dstProp
->getDimension ();
3783 UInt32 dstVecType
= dstProp
->getVectorType();
3785 UInt32 srcFormat
= srcProp
->getFormat ();
3786 UInt32 srcDim
= srcProp
->getDimension ();
3787 UInt32 srcVecType
= srcProp
->getVectorType();
3789 if(dstFormat
== srcFormat
&& dstFormat
== GL_FLOAT
)
3791 if(dstVecType
== srcVecType
&&
3792 dstVecType
== GeoProperty::VectorTypePoint
)
3794 if(dstDim
== srcDim
&& dstDim
== 1)
3796 copyVectorMapped
<GeoPnt1fPropertyDesc
>(
3797 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3800 else if(dstDim
== srcDim
&& dstDim
== 2)
3802 copyVectorMapped
<GeoPnt2fPropertyDesc
>(
3803 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3806 else if(dstDim
== srcDim
&& dstDim
== 3)
3808 copyVectorMapped
<GeoPnt3fPropertyDesc
>(
3809 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3812 else if(dstDim
== srcDim
&& dstDim
== 4)
3814 copyVectorMapped
<GeoPnt4fPropertyDesc
>(
3815 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3819 else if(dstVecType
== srcVecType
&&
3820 dstVecType
== GeoProperty::VectorTypeVector
)
3822 if(dstDim
== srcDim
&& dstDim
== 1)
3824 copyVectorMapped
<GeoVec1fPropertyDesc
>(
3825 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3828 else if(dstDim
== srcDim
&& dstDim
== 2)
3830 copyVectorMapped
<GeoVec2fPropertyDesc
>(
3831 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3834 else if(dstDim
== srcDim
&& dstDim
== 3)
3836 copyVectorMapped
<GeoVec3fPropertyDesc
>(
3837 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3840 else if(dstDim
== srcDim
&& dstDim
== 4)
3842 copyVectorMapped
<GeoVec4fPropertyDesc
>(
3843 dstProp
, srcProp
, srcIdx
, srcSz
, idxMap
);
3849 // if we get to this point: fallback to using the generic interface
3851 typedef GeoIntegralProperty::MaxTypeT IndexType
;
3852 typedef GeoVectorProperty ::MaxTypeT ValueType
;
3854 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3856 IndexType si
= srcIdx
->getValue
<IndexType
>(i
);
3857 IndexType di
= idxMap
.get(si
);
3859 dstProp
->setValue(srcProp
->getValue
<ValueType
>(si
), di
);
3863 // TODO: Optimize copyVector like the above.
3865 /*! Copies from \a srcProp to \a dstProp the first \a srcSz values and stores
3866 them at positions starting at \a dstOffset.
3868 \warning \a dstProp is expected to have sufficient storage allocated.
3871 void copyVector( GeoVectorProperty
*dstProp
,
3872 const GeoVectorProperty
*srcProp
,
3876 // fallback to using the generic interface
3878 typedef GeoVectorProperty::MaxTypeT ValueType
;
3880 for(UInt32 i
= 0; i
< srcSz
; ++i
)
3881 dstProp
->setValue(srcProp
->getValue
<ValueType
>(i
), dstOffset
+ i
);
3885 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
3887 GeoIntegralPropertyUnrecPtr dstTypes
;
3890 calcMergePropertyType(srcGeo1
->getSFTypes()->getValue(),
3891 srcGeo2
->getSFTypes()->getValue(), false, dstFormat
);
3892 dstTypes
= GeoPropertyFactory::the()->create(dstFormat
);
3894 UInt32 src1Sz
= srcGeo1
->getSFTypes()->getValue()->size32();
3895 UInt32 src2Sz
= srcGeo2
->getSFTypes()->getValue()->size32();
3897 dstTypes
->resize(src1Sz
+ src2Sz
);
3899 copyIntegral(dstTypes
, srcGeo1
->getSFTypes()->getValue(), src1Sz
, 0 );
3900 copyIntegral(dstTypes
, srcGeo2
->getSFTypes()->getValue(), src2Sz
, src1Sz
);
3902 dstGeo
->setTypes(dstTypes
);
3905 void mergeGeoLengths(
3906 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
3908 GeoIntegralPropertyUnrecPtr dstLengths
;
3911 calcMergePropertyType(srcGeo1
->getSFLengths()->getValue(),
3912 srcGeo2
->getSFLengths()->getValue(), false, dstFormat
);
3913 dstLengths
= GeoPropertyFactory::the()->create(dstFormat
);
3915 UInt32 src1Sz
= srcGeo1
->getSFLengths()->getValue()->size32();
3916 UInt32 src2Sz
= srcGeo2
->getSFLengths()->getValue()->size32();
3918 dstLengths
->resize(src1Sz
+ src2Sz
);
3920 copyIntegral(dstLengths
, srcGeo1
->getSFLengths()->getValue(), src1Sz
, 0 );
3921 copyIntegral(dstLengths
, srcGeo2
->getSFLengths()->getValue(), src2Sz
, src1Sz
);
3923 dstGeo
->setLengths(dstLengths
);
3926 // The following functions are implementing merges between all different
3927 // indexing variants for geometries.
3928 // The last four letters indicate the indexing that is assumed for the
3929 // arguments. NI - non indexed, SI - single indexed, MI - multi indexed
3932 /*! Merge geometry \a srcGeo1 and \a srcGeo2 into \a dstGeo, assuming they have
3933 the same set of properties and both are unindexed.
3936 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
3938 FDEBUG(("mergeGeoNINI: srcGeo1 [%p] srcGeo2 [%p]\n",
3939 static_cast<const void *>(srcGeo1
),
3940 static_cast<const void *>(srcGeo2
)));
3942 mergeGeoTypes (dstGeo
, srcGeo1
, srcGeo2
);
3943 mergeGeoLengths(dstGeo
, srcGeo1
, srcGeo2
);
3945 // count number of _used_ property elements
3946 UInt32 src1Used
= 0;
3947 UInt32 src2Used
= 0;
3949 for(UInt32 i
= 0; i
< srcGeo1
->getSFLengths()->getValue()->size(); ++i
)
3950 src1Used
+= srcGeo1
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
3952 for(UInt32 i
= 0; i
< srcGeo2
->getSFLengths()->getValue()->size(); ++i
)
3953 src2Used
+= srcGeo2
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
3955 const Geometry::MFPropertiesType
*src1PropF
= srcGeo1
->getMFProperties ();
3956 const Geometry::MFPropertiesType
*src2PropF
= srcGeo2
->getMFProperties ();
3958 UInt32 szProp
= osgMin(src1PropF
->size32(), src2PropF
->size32());
3960 for(UInt32 i
= 0; i
< szProp
; ++i
)
3962 const GeoVectorProperty
*src1Prop
= (*src1PropF
)[i
];
3963 const GeoVectorProperty
*src2Prop
= (*src2PropF
)[i
];
3965 FFASSERT(!((src1Prop
!= NULL
) ^ (src2Prop
!= NULL
)), 1,
3966 ("mergeGeoNINI: Inconsistent properties!\n");)
3968 if(src1Prop
== NULL
|| src2Prop
== NULL
)
3976 calcMergePropertyType(src1Prop
, src2Prop
,
3977 dstFormat
, dstDim
, dstVecType
, dstNorm
);
3978 GeoVectorPropertyUnrecPtr dstProp
=
3979 GeoPropertyFactory::the()->create(dstFormat
, dstDim
,
3980 dstVecType
, dstNorm
!= 0);
3982 dstProp
->resize(src1Used
+ src2Used
);
3984 copyVector(dstProp
, src1Prop
, src1Used
, 0 );
3985 copyVector(dstProp
, src2Prop
, src2Used
, src1Used
);
3987 dstGeo
->setProperty(dstProp
, i
);
3992 /*! Merge geometry \a srcGeo1 and \a srcGeo2 into \a dstGeo, assuming they have
3993 the same set of properties and \a srcGeo1 is not indexed, \a srcGeo2 is
3994 single indexed. The result \a dstGeo will be single indexed.
3997 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
3999 FDEBUG(("mergeGeoNISI: srcGeo1 [%p] srcGeo2 [%p]\n",
4000 static_cast<const void *>(srcGeo1
),
4001 static_cast<const void *>(srcGeo2
)));
4003 // 1. merge types and lengths
4004 mergeGeoTypes (dstGeo
, srcGeo1
, srcGeo2
);
4005 mergeGeoLengths(dstGeo
, srcGeo1
, srcGeo2
);
4007 // 2. merge properties
4009 // find number of _used_ properties/indices in both geometries
4010 UInt32 src1Used
= 0;
4011 UInt32 src2Used
= 0;
4013 for(UInt32 i
= 0; i
< srcGeo1
->getSFLengths()->getValue()->size(); ++i
)
4014 src1Used
+= srcGeo1
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4016 for(UInt32 i
= 0; i
< srcGeo2
->getSFLengths()->getValue()->size(); ++i
)
4017 src2Used
+= srcGeo2
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4019 // get index bag for single indexed geo
4020 Geometry::IndexBag src2IBag
= srcGeo2
->getUniqueIndexBag();
4022 FFASSERT(src2IBag
.size() == 1, 1, ("mergeGeoNISI: Not single indexed!\n");)
4024 const GeoIntegralProperty
*src2Idx
= src2IBag
[0].first
;
4026 // create new index - be conservative and use UInt32 indices
4027 GeoIntegralPropertyUnrecPtr dstIdx
=
4028 GeoPropertyFactory::the()->create(GL_UNSIGNED_INT
);
4031 dstIdx
->resize(src1Used
+ src2Used
);
4033 // populate index with entries for srcGeo1
4034 for(UInt32 i
= 0; i
< src1Used
; ++i
)
4035 dstIdx
->setValue(i
, i
);
4038 UInt32 offset
= src1Used
;
4039 copyIndex(dstIdx
, src2Idx
, src2Used
, idxMap
, offset
, src1Used
);
4041 // copy each property
4042 for(UInt32 i
= 0; i
< src2IBag
[0].second
.size(); ++i
)
4044 const GeoVectorProperty
*src1Prop
=
4045 srcGeo1
->getProperty(src2IBag
[0].second
[i
]);
4046 const GeoVectorProperty
*src2Prop
=
4047 srcGeo2
->getProperty(src2IBag
[0].second
[i
]);
4049 FFASSERT(!((src1Prop
!= NULL
) ^ (src2Prop
!= NULL
)), 1,
4050 ("mergeGeoNISI: Inconsistent properties!\n");)
4052 if(src1Prop
== NULL
|| src2Prop
== NULL
)
4060 // create destination property
4061 calcMergePropertyType(src1Prop
, src2Prop
,
4062 dstFormat
, dstDim
, dstVecType
, dstNorm
);
4063 GeoVectorPropertyUnrecPtr dstProp
=
4064 GeoPropertyFactory::the()->create(dstFormat
, dstDim
,
4065 dstVecType
, dstNorm
!= 0);
4068 dstProp
->resize(offset
);
4070 copyVector (dstProp
, src1Prop
, src1Used
, 0 );
4071 copyVectorMapped(dstProp
, src2Prop
, src2Idx
, src2Used
, idxMap
);
4073 dstGeo
->setProperty(dstProp
, src2IBag
[0].second
[i
]);
4074 dstGeo
->setIndex (dstIdx
, src2IBag
[0].second
[i
]);
4080 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4082 mergeGeoNISI(dstGeo
, srcGeo2
, srcGeo1
);
4085 /*! Merge geometry \a srcGeo1 and \a srcGeo2 into \a dstGeo, assuming they
4086 have the same set of properties and \a srcGeo1 is not indexed, \a srcGeo2 is
4087 multi indexed. The result \a dstGeo will be multi indexed.
4090 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4092 FDEBUG(("mergeGeoNIMI: srcGeo1 [%p] srcGeo2 [%p]\n",
4093 static_cast<const void *>(srcGeo1
),
4094 static_cast<const void *>(srcGeo2
)));
4096 // 1. merge types and lengths
4097 mergeGeoTypes (dstGeo
, srcGeo1
, srcGeo2
);
4098 mergeGeoLengths(dstGeo
, srcGeo1
, srcGeo2
);
4100 // 2. merge properties
4102 // find number of _used_ properties/indices in both geometries
4103 UInt32 src1Used
= 0;
4104 UInt32 src2Used
= 0;
4106 for(UInt32 i
= 0; i
< srcGeo1
->getSFLengths()->getValue()->size(); ++i
)
4107 src1Used
+= srcGeo1
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4109 for(UInt32 i
= 0; i
< srcGeo2
->getSFLengths()->getValue()->size(); ++i
)
4110 src2Used
+= srcGeo2
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4112 // get index bag for multi indexed geo
4113 Geometry::IndexBag src2IBag
= srcGeo2
->getUniqueIndexBag();
4115 for(UInt32 i
= 0; i
< src2IBag
.size(); ++i
)
4117 const GeoIntegralProperty
*src2Idx
= src2IBag
[i
].first
;
4119 // create new index - be conservative and use UInt32 indices
4120 GeoIntegralPropertyUnrecPtr dstIdx
=
4121 GeoPropertyFactory::the()->create(GL_UNSIGNED_INT
);
4124 dstIdx
->resize(src1Used
+ src2Used
);
4126 // populate index with entries for srcGeo1
4127 for(UInt32 j
= 0; j
< src1Used
; ++j
)
4128 dstIdx
->setValue(j
, j
);
4131 UInt32 offset
= src1Used
;
4132 copyIndex(dstIdx
, src2Idx
, src2Used
, idxMap
, offset
, src1Used
);
4134 // copy properties indexed by this index
4135 for(UInt32 j
= 0; j
< src2IBag
[i
].second
.size(); ++j
)
4137 const GeoVectorProperty
*src1Prop
=
4138 srcGeo1
->getProperty(src2IBag
[i
].second
[j
]);
4139 const GeoVectorProperty
*src2Prop
=
4140 srcGeo2
->getProperty(src2IBag
[i
].second
[j
]);
4142 FFASSERT(!((src1Prop
!= NULL
) ^ (src2Prop
!= NULL
)), 1,
4143 ("mergeGeoNIMI: Inconsistent properties!\n");)
4145 if(src1Prop
== NULL
|| src2Prop
== NULL
)
4153 // create destination property
4154 calcMergePropertyType(src1Prop
, src2Prop
,
4155 dstFormat
, dstDim
, dstVecType
, dstNorm
);
4156 GeoVectorPropertyUnrecPtr dstProp
=
4157 GeoPropertyFactory::the()->create(dstFormat
, dstDim
,
4158 dstVecType
, dstNorm
!= 0);
4161 dstProp
->resize(offset
);
4163 copyVector (dstProp
, src1Prop
, src1Used
, 0 );
4164 copyVectorMapped(dstProp
, src2Prop
, src2Idx
, src2Used
, idxMap
);
4166 dstGeo
->setProperty(dstProp
, src2IBag
[i
].second
[j
]);
4167 dstGeo
->setIndex (dstIdx
, src2IBag
[i
].second
[j
]);
4174 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4176 mergeGeoNIMI(dstGeo
, srcGeo2
, srcGeo1
);
4179 /*! Merge geometry \a srcGeo1 and \a srcGeo2 into \a dstGeo, assuming they have
4180 the same set of properties and both are single indexed.
4183 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4185 FDEBUG(("mergeGeoSISI: srcGeo1 [%p] srcGeo2 [%p]\n",
4186 static_cast<const void *>(srcGeo1
),
4187 static_cast<const void *>(srcGeo2
)));
4189 // 1. merge types and lengths
4190 mergeGeoTypes (dstGeo
, srcGeo1
, srcGeo2
);
4191 mergeGeoLengths(dstGeo
, srcGeo1
, srcGeo2
);
4193 // 2. merge properties
4195 // find number of _used_ indices in both geometries
4196 UInt32 src1Used
= 0;
4197 UInt32 src2Used
= 0;
4199 for(UInt32 i
= 0; i
< srcGeo1
->getSFLengths()->getValue()->size(); ++i
)
4200 src1Used
+= srcGeo1
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4202 for(UInt32 i
= 0; i
< srcGeo2
->getSFLengths()->getValue()->size(); ++i
)
4203 src2Used
+= srcGeo2
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4205 const GeoIntegralProperty
*src1Idx
= NULL
;
4206 const GeoIntegralProperty
*src2Idx
= NULL
;
4208 for(UInt32 i
= 0; i
< srcGeo1
->getMFPropIndices()->size(); ++i
)
4210 if((*srcGeo1
->getMFPropIndices())[i
] != NULL
)
4212 src1Idx
= (*srcGeo1
->getMFPropIndices())[i
];
4217 for(UInt32 i
= 0; i
< srcGeo2
->getMFPropIndices()->size(); ++i
)
4219 if((*srcGeo2
->getMFPropIndices())[i
] != NULL
)
4221 src2Idx
= (*srcGeo2
->getMFPropIndices())[i
];
4227 UInt32 dstIdxFormat
;
4228 calcMergePropertyType(src1Idx
, src2Idx
, true, dstIdxFormat
);
4229 GeoIntegralPropertyUnrecPtr dstIdx
=
4230 GeoPropertyFactory::the()->create(dstIdxFormat
);
4232 dstIdx
->resize(src1Used
+ src2Used
);
4234 // copy index values to destination
4238 copyIndex(dstIdx
, src1Idx
, src1Used
, idxMap1
, offset
, 0 );
4239 copyIndex(dstIdx
, src2Idx
, src2Used
, idxMap2
, offset
, src1Used
);
4241 // copy each property
4242 UInt32 minPropSz
= osgMin(srcGeo1
->getMFProperties()->size32(),
4243 srcGeo2
->getMFProperties()->size32() );
4245 for(UInt32 i
= 0; i
< minPropSz
; ++i
)
4247 const GeoVectorProperty
*src1Prop
= srcGeo1
->getProperty(i
);
4248 const GeoVectorProperty
*src2Prop
= srcGeo2
->getProperty(i
);
4250 // skip missing properties
4251 if(src1Prop
== NULL
|| src2Prop
== NULL
)
4259 // create destination property
4260 calcMergePropertyType(src1Prop
, src2Prop
,
4261 dstFormat
, dstDim
, dstVecType
, dstNorm
);
4262 GeoVectorPropertyUnrecPtr dstProp
=
4263 GeoPropertyFactory::the()->create(dstFormat
, dstDim
,
4264 dstVecType
, dstNorm
!= 0);
4267 dstProp
->resize(offset
);
4269 // copy property values - only those referenced by an index are copied
4270 // and stored to the new position indicated by idxMap
4271 copyVectorMapped(dstProp
, src1Prop
, src1Idx
, src1Used
, idxMap1
);
4272 copyVectorMapped(dstProp
, src2Prop
, src2Idx
, src2Used
, idxMap2
);
4274 dstGeo
->setProperty(dstProp
, i
);
4275 dstGeo
->setIndex (dstIdx
, i
);
4279 /*! Merge geometry \a srcGeo1 and \a srcGeo2 into \a dstGeo, assuming they have
4280 the same set of properties and \a srcGeo1 is single indexed, \a srcGeo2 is
4281 multi indexed. The result \a dstGeo will be multi indexed.
4284 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4286 FDEBUG(("mergeGeoSIMI: srcGeo1 [%p] srcGeo2 [%p]\n",
4287 static_cast<const void *>(srcGeo1
),
4288 static_cast<const void *>(srcGeo2
)));
4290 // 1. merge types and lengths
4291 mergeGeoTypes (dstGeo
, srcGeo1
, srcGeo2
);
4292 mergeGeoLengths(dstGeo
, srcGeo1
, srcGeo2
);
4294 // 2. merge properties
4296 // find number of _used_ indices in both geometries
4297 UInt32 src1Used
= 0;
4298 UInt32 src2Used
= 0;
4300 for(UInt32 i
= 0; i
< srcGeo1
->getSFLengths()->getValue()->size(); ++i
)
4301 src1Used
+= srcGeo1
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4303 for(UInt32 i
= 0; i
< srcGeo2
->getSFLengths()->getValue()->size(); ++i
)
4304 src2Used
+= srcGeo2
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4306 // get indices sorted by the properties they index
4307 Geometry::IndexBag src1IBag
= srcGeo1
->getUniqueIndexBag();
4308 Geometry::IndexBag src2IBag
= srcGeo2
->getUniqueIndexBag();
4310 for(UInt32 i
= 0; i
< src2IBag
.size(); ++i
)
4312 const GeoIntegralProperty
*src1Idx
= src1IBag
[0].first
;
4313 const GeoIntegralProperty
*src2Idx
= src2IBag
[i
].first
;
4316 UInt32 dstIdxFormat
;
4317 calcMergePropertyType(src1Idx
, src2Idx
, true, dstIdxFormat
);
4318 GeoIntegralPropertyUnrecPtr dstIdx
=
4319 GeoPropertyFactory::the()->create(dstIdxFormat
);
4322 dstIdx
->resize(src1Used
+ src2Used
);
4324 // copy index values to destination
4328 copyIndex(dstIdx
, src1Idx
, src1Used
, idxMap1
, offset
, 0 );
4329 copyIndex(dstIdx
, src2Idx
, src2Used
, idxMap2
, offset
, src1Used
);
4331 // copy properties indexed by this index
4332 for(UInt32 j
= 0; j
< src2IBag
[i
].second
.size(); ++j
)
4334 const GeoVectorProperty
*src1Prop
=
4335 srcGeo1
->getProperty(src2IBag
[i
].second
[j
]);
4336 const GeoVectorProperty
*src2Prop
=
4337 srcGeo2
->getProperty(src2IBag
[i
].second
[j
]);
4339 FFASSERT(!((src1Prop
!= NULL
) ^ (src2Prop
!= NULL
)), 1,
4340 ("mergeGeoSIMI: Inconsistent properties!");)
4342 if(src1Prop
== NULL
|| src2Prop
== NULL
)
4350 // create destination property
4351 calcMergePropertyType(src1Prop
, src2Prop
,
4352 dstFormat
, dstDim
, dstVecType
, dstNorm
);
4353 GeoVectorPropertyUnrecPtr dstProp
=
4354 GeoPropertyFactory::the()->create(dstFormat
, dstDim
,
4355 dstVecType
, dstNorm
!= 0);
4358 dstProp
->resize(offset
);
4360 copyVectorMapped(dstProp
, src1Prop
, src1Idx
, src1Used
, idxMap1
);
4361 copyVectorMapped(dstProp
, src2Prop
, src2Idx
, src2Used
, idxMap2
);
4363 dstGeo
->setProperty(dstProp
, src2IBag
[i
].second
[j
]);
4364 dstGeo
->setIndex (dstIdx
, src2IBag
[i
].second
[j
]);
4371 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4373 mergeGeoSIMI(dstGeo
, srcGeo2
, srcGeo1
);
4376 /*! Merge geometry \a srcGeo1 and \a srcGeo2 into \a dstGeo, assuming they have
4377 the same set of properties and both are multi indexed.
4380 Geometry
*dstGeo
, const Geometry
*srcGeo1
, const Geometry
*srcGeo2
)
4382 FDEBUG(("mergeGeoMIMI: srcGeo1 [%p] srcGeo2 [%p]\n",
4383 static_cast<const void *>(srcGeo1
),
4384 static_cast<const void *>(srcGeo2
)));
4386 // 1. merge types and lengths
4387 mergeGeoTypes (dstGeo
, srcGeo1
, srcGeo2
);
4388 mergeGeoLengths(dstGeo
, srcGeo1
, srcGeo2
);
4390 // 2. merge properties
4392 // find number of _used_ indices in both geometries
4393 UInt32 src1Used
= 0;
4394 UInt32 src2Used
= 0;
4396 for(UInt32 i
= 0; i
< srcGeo1
->getSFLengths()->getValue()->size(); ++i
)
4397 src1Used
+= srcGeo1
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4399 for(UInt32 i
= 0; i
< srcGeo2
->getSFLengths()->getValue()->size(); ++i
)
4400 src2Used
+= srcGeo2
->getSFLengths()->getValue()->getValue
<UInt32
>(i
);
4402 // get indices sorted by the properties they index
4403 Geometry::IndexBag src1IBag
= srcGeo1
->getUniqueIndexBag();
4404 Geometry::IndexBag src2IBag
= srcGeo2
->getUniqueIndexBag();
4406 // Property N may be indexed by different indices in both geometries.
4407 // We build a 2D map (mipMap) that is indexed by i1, i2 and gives the list
4408 // of properties that is indexed by the concatenation of indices
4409 // src1IBag[i1].first and src2IBag[i2].first
4411 typedef std::vector
<std::vector
< std::vector
<UInt32
> > > MergedIndexPropMap
;
4413 MergedIndexPropMap mipMap
;
4414 mipMap
.resize(src1IBag
.size());
4416 // find indices that index the same property
4417 for(UInt32 i1
= 0; i1
< src1IBag
.size(); ++i1
)
4419 mipMap
[i1
].resize(src2IBag
.size());
4421 for(UInt32 j1
= 0; j1
< src1IBag
[i1
].second
.size(); ++j1
)
4423 for(UInt32 i2
= 0; i2
< src2IBag
.size(); ++i2
)
4425 for(UInt32 j2
= 0; j2
< src2IBag
[i2
].second
.size(); ++j2
)
4427 if(src1IBag
[i1
].second
[j1
] == src2IBag
[i2
].second
[j2
])
4429 mipMap
[i1
][i2
].push_back(src1IBag
[i1
].second
[j1
]);
4436 // iterate over mipMap concatenating corresponding indices and copy
4437 // the indexed properties.
4439 for(UInt32 i1
= 0; i1
< mipMap
.size(); ++i1
)
4441 for(UInt32 i2
= 0; i2
< mipMap
[i1
].size(); ++i2
)
4443 if(mipMap
[i1
][i2
].empty())
4446 const GeoIntegralProperty
*src1Idx
= src1IBag
[i1
].first
;
4447 const GeoIntegralProperty
*src2Idx
= src2IBag
[i2
].first
;
4450 UInt32 dstIdxFormat
;
4451 calcMergePropertyType(src1Idx
, src2Idx
, true, dstIdxFormat
);
4452 GeoIntegralPropertyUnrecPtr dstIdx
=
4453 GeoPropertyFactory::the()->create(dstIdxFormat
);
4456 dstIdx
->resize(src1Used
+ src2Used
);
4458 // copy index values to destination
4462 copyIndex(dstIdx
, src1Idx
, src1Used
, idxMap1
, offset
, 0 );
4463 copyIndex(dstIdx
, src2Idx
, src2Used
, idxMap2
, offset
, src1Used
);
4465 for(UInt32 j
= 0; j
< mipMap
[i1
][i2
].size(); ++j
)
4467 const GeoVectorProperty
*src1Prop
=
4468 srcGeo1
->getProperty(mipMap
[i1
][i2
][j
]);
4469 const GeoVectorProperty
*src2Prop
=
4470 srcGeo2
->getProperty(mipMap
[i1
][i2
][j
]);
4472 if(src1Prop
== NULL
|| src2Prop
== NULL
)
4480 // create destination property
4481 calcMergePropertyType(src1Prop
, src2Prop
,
4482 dstFormat
, dstDim
, dstVecType
, dstNorm
);
4483 GeoVectorPropertyUnrecPtr dstProp
=
4484 GeoPropertyFactory::the()->create(dstFormat
, dstDim
,
4485 dstVecType
, dstNorm
!= 0);
4488 dstProp
->resize(offset
);
4490 copyVectorMapped(dstProp
, src1Prop
, src1Idx
, src1Used
, idxMap1
);
4491 copyVectorMapped(dstProp
, src2Prop
, src2Idx
, src2Used
, idxMap2
);
4493 dstGeo
->setProperty(dstProp
, mipMap
[i1
][i2
][j
]);
4494 dstGeo
->setIndex (dstIdx
, mipMap
[i1
][i2
][j
]);
4503 /*! Returns whether the two geometries \a geo1 and \a geo2 can be merged, based
4504 on the properties and indexing they use.
4505 Geometries are mergeable if they have the same set of properties.
4507 \warning Materials are not considered in this function!
4509 \ingroup GrpDrawablesGeometryUtils
4511 bool mergeableGeo(const Geometry
*geo1
, const Geometry
*geo2
)
4513 if(geo1
->getTypes() == NULL
|| geo2
->getTypes() == NULL
)
4515 SWARNING
<< "mergeableGeo: Geometry without types, can not merge."
4521 if(geo1
->getLengths() == NULL
|| geo2
->getLengths() == NULL
)
4523 SWARNING
<< "mergeableGeo: Geometry without lengths, can not merge."
4529 const Geometry::MFPropertiesType
&prop1
= *(geo1
->getMFProperties());
4530 const Geometry::MFPropertiesType
&prop2
= *(geo2
->getMFProperties());
4532 // number of properties may differ, but additional entries must be NULL.
4533 // first compare common entries
4534 UInt32 minSize
= osgMin(prop1
.size32(), prop2
.size32());
4535 UInt32 maxSize
= osgMax(prop1
.size32(), prop2
.size32());
4538 // common entries must either be both present or both absent
4539 for(i
= 0; i
< minSize
; ++i
)
4541 if((prop1
[i
] != NULL
) ^ (prop2
[i
] != NULL
))
4545 // additional entries must be NULL
4546 for(; i
< maxSize
; ++i
)
4548 if(i
< prop1
.size() && prop1
[i
] != NULL
)
4551 if(i
< prop2
.size() && prop2
[i
] != NULL
)
4555 // geometries have the same properties, now check indexing
4557 UInt32 szIBag1
= UInt32(geo1
->getUniqueIndexBag().size());
4558 UInt32 szIBag2
= UInt32(geo2
->getUniqueIndexBag().size());
4560 if(szIBag1
== 0 && szIBag2
== 0)
4562 // no index + no index -> no index
4565 else if(szIBag1
== 1 && szIBag2
== 1)
4567 // single + single -> single
4570 else if(szIBag1
> 1 && szIBag2
> 1)
4572 // multi + multi -> multi
4575 else if(szIBag1
== 0 && szIBag2
== 1)
4577 // no index + single -> single
4580 else if(szIBag1
== 1 && szIBag2
== 0)
4582 // single + no index -> single
4585 else if(szIBag1
> 1 && szIBag2
== 0)
4587 // multi + no index -> multi
4590 else if(szIBag1
== 0 && szIBag2
> 1)
4592 // no index + multi -> multi
4595 else if(szIBag1
== 1 && szIBag2
> 1)
4597 // single + multi -> multi
4600 else if(szIBag1
> 1 && szIBag2
== 1)
4602 // multi + single -> multi
4606 // should not happen
4608 ("mergeableGeo: Unrecognized indexing. Geometry may be invalid.\n"));
4613 /*! Attempts to merge \a geo1 and \a geo2 and returns the merged geometry or a
4614 NULL pointer if merging is not possible.
4616 \warning Materials are not considered in this function!
4618 \ingroup GrpDrawablesGeometryUtils
4620 GeometryTransitPtr
mergeGeo(const Geometry
*geo1
, const Geometry
*geo2
)
4622 GeometryUnrecPtr returnValue
;
4624 if(geo1
->getTypes() == NULL
|| geo2
->getTypes() == NULL
)
4626 SWARNING
<< "mergeGeo: Geometry without types, can not merge."
4629 return GeometryTransitPtr();
4632 if(geo1
->getLengths() == NULL
|| geo2
->getLengths() == NULL
)
4634 SWARNING
<< "mergeGeo: Geometry without lengths, can not merge."
4637 return GeometryTransitPtr();
4640 const Geometry::MFPropertiesType
&prop1
= *(geo1
->getMFProperties());
4641 const Geometry::MFPropertiesType
&prop2
= *(geo2
->getMFProperties());
4643 // number of properties may differ, but additional entries must be NULL.
4644 // first compare common entries
4645 UInt32 minSize
= osgMin(prop1
.size32(), prop2
.size32());
4646 UInt32 maxSize
= osgMax(prop1
.size32(), prop2
.size32());
4649 // common entries must either be both present or both absent
4650 for(i
= 0; i
< minSize
; ++i
)
4652 if((prop1
[i
] != NULL
) ^ (prop2
[i
] != NULL
))
4654 FWARNING(("mergeGeo: Geometries have different properties, "
4655 "can not merge.\n"));
4657 return GeometryTransitPtr();
4661 // additional entries must be NULL
4662 for(; i
< maxSize
; ++i
)
4664 if(i
< prop1
.size() && prop1
[i
] != NULL
)
4666 FWARNING(("mergeGeo: Geometries have different properties, "
4667 "can not merge.\n"));
4669 return GeometryTransitPtr();
4672 if(i
< prop2
.size() && prop2
[i
] != NULL
)
4674 FWARNING(("mergeGeo: Geometries have different properties, "
4675 "can not merge.\n"));
4677 return GeometryTransitPtr();
4681 // geometries have the same properties, now check indexing
4683 UInt32 szIBag1
= UInt32(geo1
->getUniqueIndexBag().size());
4684 UInt32 szIBag2
= UInt32(geo2
->getUniqueIndexBag().size());
4686 if(szIBag1
== 0 && szIBag2
== 0)
4688 // no index + no index -> no index
4689 returnValue
= Geometry::create();
4690 mergeGeoNINI(returnValue
, geo1
, geo2
);
4692 else if(szIBag1
== 1 && szIBag2
== 1)
4694 // single + single -> single
4695 returnValue
= Geometry::create();
4696 mergeGeoSISI(returnValue
, geo1
, geo2
);
4698 else if(szIBag1
> 1 && szIBag2
> 1)
4700 // multi + multi -> multi
4701 returnValue
= Geometry::create();
4702 mergeGeoMIMI(returnValue
, geo1
, geo2
);
4704 else if(szIBag1
== 0 && szIBag2
== 1)
4706 // no index + single -> single
4707 returnValue
= Geometry::create();
4708 mergeGeoNISI(returnValue
, geo1
, geo2
);
4710 else if(szIBag1
== 1 && szIBag2
== 0)
4712 // single + no index -> single
4713 returnValue
= Geometry::create();
4714 mergeGeoSINI(returnValue
, geo1
, geo2
);
4716 else if(szIBag1
> 1 && szIBag2
== 0)
4718 // multi + no index -> multi
4719 returnValue
= Geometry::create();
4720 mergeGeoMINI(returnValue
, geo1
, geo2
);
4722 else if(szIBag1
== 0 && szIBag2
> 1)
4724 // no index + multi -> multi
4725 returnValue
= Geometry::create();
4726 mergeGeoNIMI(returnValue
, geo1
, geo2
);
4728 else if(szIBag1
== 1 && szIBag2
> 1)
4730 // single + multi -> multi
4731 returnValue
= Geometry::create();
4732 mergeGeoSIMI(returnValue
, geo1
, geo2
);
4734 else if(szIBag1
> 1 && szIBag2
== 1)
4736 // multi + single -> multi
4737 returnValue
= Geometry::create();
4738 mergeGeoMISI(returnValue
, geo1
, geo2
);
4741 return GeometryTransitPtr(returnValue
);
4744 /*! \ingroup GrpDrawablesGeometryUtils
4747 void setVBOUsageOnPropertyProtos(bool bVal
)
4749 DerivedFieldContainerTypeIterator dtIt
=
4750 FieldContainerFactory::the()->begin(GeoProperty::getClassType());
4752 DerivedFieldContainerTypeIterator dtEnd
=
4753 FieldContainerFactory::the()->end();
4755 while(dtIt
!= dtEnd
)
4757 FieldContainer
*pProto
= dtIt
->getPrototype();
4761 GeoProperty
*pProp
= dynamic_cast<GeoProperty
*>(pProto
);
4763 OSG_ASSERT(pProp
!= NULL
);
4765 pProp
->setUseVBO(bVal
);