Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

OSGSlices.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *             Copyright (C) 2000-2002 by the OpenSG Forum                   *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038 
00039 //---------------------------------------------------------------------------
00040 //  Includes
00041 //---------------------------------------------------------------------------
00042 
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 
00046 #include <OSGGL.h>
00047 
00048 #include <OSGConfig.h>
00049 #include <OSGAction.h>
00050 #include <OSGTypedFunctors.h>
00051 
00052 #include <OSGCamera.h>
00053 
00054 #include <OSGDrawAction.h>
00055 #include <OSGRenderAction.h>
00056 #include <OSGIntersectAction.h>
00057 #include <OSGWindow.h>
00058 #include <OSGGLEXT.h>
00059 
00060 #include "OSGSlices.h"
00061 
00062 OSG_USING_NAMESPACE
00063 
00067 UInt32 Slices::_arbMultitexture = Window::invalidFunctionID;
00068 UInt32 Slices::_funcMultiTexCoord3fARB = Window::invalidFunctionID;
00069 
00070 typedef void (OSG_APIENTRY * PFNGLMULTITEXCOORD3FARBPROC)(GLenum target,
00071                                                           GLfloat s,
00072                                                           GLfloat t,
00073                                                           GLfloat r);
00074 
00075 /*----------------------- constructors & destructors ----------------------*/
00076 
00078 
00079 Slices::Slices(void) :
00080     Inherited()
00081 {
00082     _arbMultitexture = 
00083        Window::registerExtension("GL_ARB_multitexture");
00084 
00085     _funcMultiTexCoord3fARB =
00086         Window::registerFunction(OSG_DLSYM_UNDERSCORE"glMultiTexCoord3fARB", 
00087                                  _arbMultitexture);
00088 }
00089 
00091 
00092 Slices::Slices(const Slices &source) :
00093     Inherited(source)
00094 {
00095 }
00096 
00098 
00099 Slices::~Slices(void)
00100 {
00101     subRefCP(_sfMaterial.getValue());
00102 }
00103 
00104 /*----------------------------- class specific ----------------------------*/
00105 
00107 
00108 void Slices::initMethod (void)
00109 {
00110     DrawAction::registerEnterDefault( getClassType(),
00111                                     osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00112                                           MaterialDrawablePtr  ,
00113                                     CNodePtr      ,
00114                                     Action       *>(&MaterialDrawable::drawActionHandler));
00115   
00116     RenderAction::registerEnterDefault( getClassType(),
00117                                       osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00118                                       MaterialDrawablePtr  ,
00119                                       CNodePtr      ,
00120                                       Action       *>(&MaterialDrawable::renderActionHandler));
00121   
00122     IntersectAction::registerEnterDefault( getClassType(),
00123         osgTypedMethodFunctor2BaseCPtrRef<Action::ResultE,
00124                                          SlicesPtr  ,
00125                                          CNodePtr      ,
00126                                          Action       *>(&Slices::intersect));
00127   
00128 
00129 }
00130 
00132 
00133 void Slices::changed(BitVector  whichField, 
00134                      UInt32     origin     )
00135 {
00136     if(whichField & MaterialFieldMask)
00137     {
00138         if(origin & ChangedOrigin::Abstract)
00139         {
00140             if(origin & ChangedOrigin::AbstrIncRefCount)
00141             {
00142                 addRefCP(_sfMaterial.getValue());
00143             }
00144             else
00145             {
00146                 MaterialPtr pMat = _sfMaterial.getValue();
00147 
00148                 _sfMaterial.setValue(NullFC);
00149 
00150                 setMaterial(pMat);
00151             }
00152         }
00153     }
00154 
00155     // TODO; only reinit on _size change
00156     initEdgeVec();
00157 }
00158 
00160 
00161 void Slices::dump(      UInt32    , 
00162                          const BitVector ) const
00163 {
00164     SLOG << "Dump Slices NI" << std::endl;
00165 }
00166 
00167 Action::ResultE Slices::intersect(Action * OSG_CHECK_ARG(action) )
00168 {
00169   /*
00170     IntersectAction     * ia = dynamic_cast<IntersectAction*>(action);
00171     const DynamicVolume  &dv = ia->getActNode()->getVolume();
00172 
00173     if( dv.isValid() && !dv.intersect(ia->getLine()) )
00174     {
00175         return Action::Skip; //bv missed -> can not hit children
00176     }
00177 
00178     TriangleIterator it;
00179     Real32 t;
00180     Vec3f norm;
00181 
00182     for( it = this->beginTriangles(); it != this->endTriangles(); ++it )
00183     {
00184         if( ia->getLine().intersect( it.getPosition(0),
00185                                      it.getPosition(1),
00186                                      it.getPosition(2), t, &norm) )
00187         {
00188             ia->setHit( t, ia->getActNode(), it.getIndex(), norm );
00189         }
00190     }
00191     
00192   */
00193 
00194     return Action::Continue;
00195 }
00196 
00197 Action::ResultE Slices::drawPrimitives(DrawActionBase *action)
00198 {
00199     Matrix camera,toworld;
00200     UInt32 triCount, vertexCount;
00201     Vec3f planeNormal;
00202     StatCollector *coll = action->getStatistics();
00203     StatIntElem   *el   = 0;
00204     
00205     RenderAction *ra = dynamic_cast<RenderAction *>(action);
00206     
00207     camera = action->getCameraToWorld();
00208     
00209     if(ra != NULL)
00210     {
00211       toworld = ra->top_matrix();
00212     }
00213     else
00214     {
00215       action->getActNode()->getToWorld(toworld);
00216     }
00217 
00218     // normalize them, we don't want to neutralize scales in toworld
00219     toworld[0].normalize();
00220     toworld[1].normalize();
00221     toworld[2].normalize();
00222     toworld.invert();
00223     camera.multLeft(toworld);
00224   
00225     // Viewer direction  
00226     planeNormal.setValues(camera[3][0],camera[3][1],camera[3][2]);
00227     planeNormal.normalize();
00228 
00229     drawSlices(action->getWindow(), planeNormal,triCount,vertexCount);
00230 
00231     if (coll) 
00232     {
00233         if((el = coll->getElem(Drawable::statNTriangles,false)))
00234             el->add(triCount);
00235         if((el = coll->getElem(Drawable::statNVertices,false)))
00236             el->add(vertexCount);
00237     }
00238 
00239     /* TODO; bbox draw code; just for debuggging; drawBBox opt ?
00240     glPushAttrib ( GL_ENABLE_BIT );
00241     glDisable (GL_LIGHTING);
00242     glDisable (GL_TEXTURE_1D);
00243     glDisable (GL_TEXTURE_2D);
00244     glDisable (GL_TEXTURE_3D);
00245     
00246     glBegin( GL_LINES );    
00247     {
00248         for (int i = 0; i < 12; i++) 
00249         {
00250             glVertex3fv (_pointVec[_edgeVec[i].pointIndexA].getValues());
00251             glVertex3fv (_pointVec[_edgeVec[i].pointIndexB].getValues());
00252         }
00253     }  
00254     glEnd();
00255     glPopAttrib();
00256     */
00257 
00258     return Action::Continue;
00259 }
00260 
00261 void Slices::adjustVolume( Volume & volume )
00262 {   
00263     Vec3f v(_sfSize.getValue());
00264     Pnt3f p(v[0],v[1],v[2]);
00265     
00266     volume.setValid();
00267     volume.setEmpty();
00268     
00269     p /= 2;
00270     volume.extendBy ( p );
00271     
00272     p.negate();
00273     volume.extendBy ( p );
00274 }
00275 
00276 /*-------------------------------------------------------------------------*\
00277  -  protected                                                              -
00278 \*-------------------------------------------------------------------------*/
00279 
00280 /*-------------------------------------------------------------------------*\
00281  -  private                                                                -
00282 \*-------------------------------------------------------------------------*/
00283 
00284 void Slices::initEdgeVec( void )
00285 {
00286     // create the corner points
00287     
00288     //     4--------5    
00289     //    /|       /|   
00290     //   / |      / |  
00291     //  /  |     /  | 
00292     // 7--------6   | 
00293     // |   0----|---1 
00294     // |  /     |  /  
00295     // | /      | /   
00296     // |/       |/   
00297     // 3--------2 
00298 
00299     UInt32 i;
00300     std::vector<Pnt3f> & p(_pointVec);
00301     const Vec3f size(getSize());
00302     
00303     _pointVec.resize(8);
00304     
00305     p[0][0] = p[3][0] = p[4][0] = p[7][0] = -0.5f * size.x();
00306     p[1][0] = p[2][0] = p[5][0] = p[6][0] =  0.5f * size.x();
00307     p[0][1] = p[1][1] = p[2][1] = p[3][1] = -0.5f * size.y();
00308     p[4][1] = p[5][1] = p[6][1] = p[7][1] =  0.5f * size.y();
00309     p[0][2] = p[1][2] = p[4][2] = p[5][2] = -0.5f * size.z();
00310     p[2][2] = p[3][2] = p[6][2] = p[7][2] =  0.5f * size.z();
00311 
00312     // create the edge description       
00313     //     4--------5      *---4----*     0: - - - 
00314     //    /|       /|     /|       /|     1: + - - 
00315     //   / |      / |    7 |      5 |     2: + - + 
00316     //  /  |     /  |   /  8     /  9     3: - - +
00317     // 7--------6   |  *----6---*   |     4: - + -
00318     // |   0----|---1  |   *---0|---*     5: + + -
00319     // |  /     |  /   11 /     10 /      6: + + +
00320     // | /      | /    | 3      | 1       7: - + + 
00321     // |/       |/     |/       |/        
00322     // 3--------2      *---2----*
00323     //
00324     // cubeCorners     edges
00325 
00326     _edgeVec.resize(12);
00327 
00328     _edgeVec[0].pointIndexA = 0;     // 1 : positiv   0: negativ   00: parallel
00329     _edgeVec[0].pointIndexB = 1;     // xmax xmin ymax ymin zmax zmin
00330     _edgeVec[0].edgeTag = 5;         //  0    0    0    1    0    1  
00331     
00332     _edgeVec[1].pointIndexA = 1;
00333     _edgeVec[1].pointIndexB = 2;    // xmax xmin ymax ymin zmax zmin
00334     _edgeVec[1].edgeTag = 36;       //  1    0    0    1    0    0   
00335     
00336     _edgeVec[2].pointIndexA = 2;
00337     _edgeVec[2].pointIndexB = 3;    // xmax xmin ymax ymin zmax zmin
00338     _edgeVec[2].edgeTag = 6;        //  0    0    0    1    1    0
00339     
00340     _edgeVec[3].pointIndexA = 3;
00341     _edgeVec[3].pointIndexB = 0;    // xmax xmin ymax ymin zmax zmin
00342     _edgeVec[3].edgeTag = 20;       //  0    1    0    1    0    0
00343     
00344     _edgeVec[4].pointIndexA = 4;
00345     _edgeVec[4].pointIndexB = 5;    // xmax xmin ymax ymin zmax zmin
00346     _edgeVec[4].edgeTag = 9;        //   0   0    1    0    0    1
00347           
00348     _edgeVec[5].pointIndexA = 5;
00349     _edgeVec[5].pointIndexB = 6;    // xmax xmin ymax ymin zmax zmin
00350     _edgeVec[5].edgeTag = 40;       //   1   0    1    0    0    0
00351     
00352     _edgeVec[6].pointIndexA = 6;
00353     _edgeVec[6].pointIndexB = 7;    // xmax xmin ymax ymin zmax zmin
00354     _edgeVec[6].edgeTag = 10;       //  0    0    1    0    1    0
00355     
00356     _edgeVec[7].pointIndexA = 7;
00357     _edgeVec[7].pointIndexB = 4;    // xmax xmin ymax ymin zmax zmin
00358     _edgeVec[7].edgeTag = 24;       //  0    1    1    0    0    0
00359     
00360     _edgeVec[8].pointIndexA = 0;
00361     _edgeVec[8].pointIndexB = 4;    // xmax xmin ymax ymin zmax zmin
00362     _edgeVec[8].edgeTag = 17;       //  0    1    0    0    0    1
00363     
00364     _edgeVec[9].pointIndexA = 1;
00365     _edgeVec[9].pointIndexB = 5;    // xmax xmin ymax ymin zmax zmin
00366     _edgeVec[9].edgeTag = 33;       //  1    0    0    0    0    1
00367     
00368     _edgeVec[10].pointIndexA = 2;
00369     _edgeVec[10].pointIndexB = 6;   // xmax xmin ymax ymin zmax zmin
00370     _edgeVec[10].edgeTag = 34;      //  1    0    0    0     1   0
00371     
00372     _edgeVec[11].pointIndexA = 3;
00373     _edgeVec[11].pointIndexB = 7;   // xmax xmin ymax ymin zmax zmin
00374     _edgeVec[11].edgeTag = 18;      //  0    1    0    0    1   0 
00375 
00376     // create one line for every edge
00377     for (i = 0; i < 12; i++) 
00378       _edgeVec[i].line.setValue( _pointVec[_edgeVec[i].pointIndexA],
00379                                _pointVec[_edgeVec[i].pointIndexB]);
00380 }
00381 
00382 UInt32 Slices::createSlice ( const OSG::Plane &plane, Slice &slice )
00383 {
00384     UInt32 i,j,k, lastButOne;
00385     Vec3f v1, v2, winding;
00386     bool pointInHalfSpace[8];
00387     unsigned swapCount = 0;
00388     
00389     // clip the plane with the corner points
00390     for(i = 0; i < 8; i++) 
00391         pointInHalfSpace[i] = plane.isInHalfSpace(_pointVec[i]);
00392   
00393     // calculate the intersection points
00394     for(slice.numOfIntersection = i = 0; i < 12; i++)
00395     {
00396         if((pointInHalfSpace[_edgeVec[i].pointIndexA] !=
00397             pointInHalfSpace[_edgeVec[i].pointIndexB] )) 
00398         {
00399             plane.intersect(_edgeVec[i].line, 
00400                             slice.pointVec[slice.numOfIntersection] );
00401             slice.edgeVec[slice.numOfIntersection] = i;
00402             slice.numOfIntersection++;
00403         }
00404     }
00405 
00406     if (slice.numOfIntersection > 2) 
00407     {
00408         lastButOne = slice.numOfIntersection - 2;
00409         i=j=k=0;
00410 
00411         // edge sort
00412         for (; j++ <= lastButOne; i++)
00413         {
00414             // find first invalid edgeTag -> j 
00415             while((j <= lastButOne) && 
00416                   ((_edgeVec[slice.edgeVec[i]].edgeTag &
00417                   _edgeVec[slice.edgeVec[j]].edgeTag ) != 0)) 
00418             {
00419                 i++;  
00420                 j++;
00421             }
00422 
00423             // check whether edgeTags are disordered
00424             if (j <= lastButOne) 
00425             { 
00426                 // find first valid edgeTag -> k
00427                 k = j+1;
00428                 while((k <= lastButOne) &&
00429                       ((_edgeVec[slice.edgeVec[i]].edgeTag &
00430                       _edgeVec[slice.edgeVec[k]].edgeTag ) == 0))
00431                 {
00432                     k++;
00433                 }
00434 
00435                 // swap edge (j,k)
00436                 osgSwap (slice.edgeVec[j],  slice.edgeVec[k]);
00437                 osgSwap (slice.pointVec[j], slice.pointVec[k]);
00438                 swapCount++;
00439             }
00440         }
00441 
00442         // TODO; find a better/faster way to check the winding
00443         // check winding
00444         v1 =  slice.pointVec[1];
00445         v1 -= slice.pointVec[0];
00446         v2 =  slice.pointVec[2];
00447         v2 -= slice.pointVec[0];
00448         winding = v1.cross(v2);
00449     
00450         slice.ccw = ( fabs (winding.x() + plane.getNormal().x())
00451                       >= fabs(plane.getNormal().x()) );
00452     }
00453 
00454     return slice.numOfIntersection;
00455 }
00456 
00457 void Slices::drawSlices(Window *win, const Vec3f &planeNormal,
00458                         UInt32 & triCount, UInt32 & vertexCount)
00459 {
00460     bool has_multitexture = win->hasExtension(_arbMultitexture);
00461 
00462     PFNGLMULTITEXCOORD3FARBPROC multiTexCoord3f = NULL;
00463     if(has_multitexture)
00464         multiTexCoord3f = (PFNGLMULTITEXCOORD3FARBPROC)
00465                           win->getFunction(_funcMultiTexCoord3fARB);
00466 
00467     Real32 hsx = getSize().x()/2, hsy = getSize().y()/2, hsz = getSize().z()/2;
00468     Real32 ssx = 1/getSize().x(), ssy = 1/getSize().y(), ssz = 1/getSize().z();
00469     Slice slice;
00470     Plane plane;
00471     Real32 distance, sliceDistance, volumeDiagonal = getSize().length();
00472     Int32 i, si, numOfSlices;
00473     Vec3f texPos0, texPos1, texPos2, texOff, texSliceNormal;
00474     
00475     if(_edgeVec.empty())
00476         initEdgeVec();
00477     
00478     sliceDistance = getSliceDistance();
00479     numOfSlices = int (volumeDiagonal / sliceDistance) + 1;
00480     distance = - volumeDiagonal / 2;
00481     texOff = planeNormal;
00482     texOff.normalize();
00483     texOff *= sliceDistance * 0.5;
00484     
00485     texSliceNormal.setValues(planeNormal.x() * sliceDistance * ssx,
00486                              planeNormal.y() * sliceDistance * ssy,
00487                              planeNormal.z() * sliceDistance * ssz );
00488     
00489     triCount = 0;
00490     vertexCount = 0;
00491     
00492     if (numOfSlices) 
00493     {
00494         glNormal3fv ( texSliceNormal.getValues() );
00495     
00496         for(si = 0; si < numOfSlices; si++) 
00497         {
00498             plane.set   ( planeNormal, distance += sliceDistance );
00499     
00500             if(createSlice(plane,slice) > 2) 
00501             {
00502                 triCount    += slice.numOfIntersection - 2;
00503                 vertexCount += slice.numOfIntersection;
00504         
00505                 ::glBegin(GL_POLYGON);
00506                 if(slice.ccw)
00507                 {
00508                     for(i = 0; i < slice.numOfIntersection; i++) 
00509                     {
00510                         texPos0 = texPos1 = texPos2 = slice.pointVec[i];
00511                         texPos1 += texOff;
00512                         texPos2 -= texOff;
00513 
00514                         texSliceNormal = texPos1;
00515                         texSliceNormal -= texPos2;
00516               
00517                         glTexCoord3f((hsx + texPos0.x()) * ssx,
00518                                     (hsy + texPos0.y()) * ssy,
00519                                     (hsz + texPos0.z()) * ssz );
00520 
00521                         if(has_multitexture)
00522                         {
00523                             multiTexCoord3f(GL_TEXTURE1_ARB,
00524                                             (hsx + texPos1.x()) * ssx,
00525                                             (hsy + texPos1.y()) * ssy,
00526                                             (hsz + texPos1.z()) * ssz );
00527     
00528                             multiTexCoord3f(GL_TEXTURE2_ARB,
00529                                             (hsx + texPos2.x()) * ssx,
00530                                             (hsy + texPos2.y()) * ssy,
00531                                             (hsz + texPos2.z()) * ssz );
00532                         }
00533                         glVertex3fv  ( slice.pointVec[i].getValues() );
00534                     }
00535                 }
00536                 else
00537                 {
00538                     for(i = slice.numOfIntersection - 1; i >= 0; i--) 
00539                     {
00540                         texPos0 = texPos1 = texPos2 = slice.pointVec[i];
00541                         texPos1 += texOff;
00542                         texPos2 -= texOff;
00543                             
00544                         glTexCoord3f ((hsx + texPos0.x()) * ssx,
00545                                       (hsy + texPos0.y()) * ssy,
00546                                       (hsz + texPos0.z()) * ssz );
00547 
00548                         if(has_multitexture)
00549                         {
00550                             multiTexCoord3f(GL_TEXTURE1_ARB,
00551                                             (hsx + texPos1.x()) * ssx,
00552                                             (hsy + texPos1.y()) * ssy,
00553                                             (hsz + texPos1.z()) * ssz );
00554     
00555                             multiTexCoord3f(GL_TEXTURE2_ARB,
00556                                             (hsx + texPos2.x()) * ssx,
00557                                             (hsy + texPos2.y()) * ssy,
00558                                             (hsz + texPos2.z()) * ssz );
00559                         }
00560                         glVertex3fv  ( slice.pointVec[i].getValues() );
00561                     }
00562                 }
00563                 ::glEnd();
00564             }
00565         } 
00566     }
00567 }
00568 
00569 /*------------------------------------------------------------------------*/
00570 /*                              cvs id's                                  */
00571 
00572 #ifdef OSG_SGI_CC
00573 #pragma set woff 1174
00574 #endif
00575 
00576 #ifdef OSG_LINUX_ICC
00577 #pragma warning( disable : 177 )
00578 #endif
00579 
00580 namespace
00581 {
00582     static Char8 cvsid_cpp       [] = "@(#)$Id: FCTemplate_cpp.h,v 1.12 2002/04/30 09:29:13 vossg Exp $";
00583     static Char8 cvsid_hpp       [] = OSGSLICESBASE_HEADER_CVSID;
00584     static Char8 cvsid_inl       [] = OSGSLICESBASE_INLINE_CVSID;
00585 
00586     static Char8 cvsid_fields_hpp[] = OSGSLICESFIELDS_HEADER_CVSID;
00587 }
00588 
00589 #ifdef __sgi
00590 #pragma reset woff 1174
00591 #endif
00592 
00593 

Generated on Thu Aug 25 04:10:22 2005 for OpenSG by  doxygen 1.4.3