00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
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
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
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
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
00219 toworld[0].normalize();
00220 toworld[1].normalize();
00221 toworld[2].normalize();
00222 toworld.invert();
00223 camera.multLeft(toworld);
00224
00225
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
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
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
00278
00279
00280
00281
00282
00283
00284 void Slices::initEdgeVec( void )
00285 {
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
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
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326 _edgeVec.resize(12);
00327
00328 _edgeVec[0].pointIndexA = 0;
00329 _edgeVec[0].pointIndexB = 1;
00330 _edgeVec[0].edgeTag = 5;
00331
00332 _edgeVec[1].pointIndexA = 1;
00333 _edgeVec[1].pointIndexB = 2;
00334 _edgeVec[1].edgeTag = 36;
00335
00336 _edgeVec[2].pointIndexA = 2;
00337 _edgeVec[2].pointIndexB = 3;
00338 _edgeVec[2].edgeTag = 6;
00339
00340 _edgeVec[3].pointIndexA = 3;
00341 _edgeVec[3].pointIndexB = 0;
00342 _edgeVec[3].edgeTag = 20;
00343
00344 _edgeVec[4].pointIndexA = 4;
00345 _edgeVec[4].pointIndexB = 5;
00346 _edgeVec[4].edgeTag = 9;
00347
00348 _edgeVec[5].pointIndexA = 5;
00349 _edgeVec[5].pointIndexB = 6;
00350 _edgeVec[5].edgeTag = 40;
00351
00352 _edgeVec[6].pointIndexA = 6;
00353 _edgeVec[6].pointIndexB = 7;
00354 _edgeVec[6].edgeTag = 10;
00355
00356 _edgeVec[7].pointIndexA = 7;
00357 _edgeVec[7].pointIndexB = 4;
00358 _edgeVec[7].edgeTag = 24;
00359
00360 _edgeVec[8].pointIndexA = 0;
00361 _edgeVec[8].pointIndexB = 4;
00362 _edgeVec[8].edgeTag = 17;
00363
00364 _edgeVec[9].pointIndexA = 1;
00365 _edgeVec[9].pointIndexB = 5;
00366 _edgeVec[9].edgeTag = 33;
00367
00368 _edgeVec[10].pointIndexA = 2;
00369 _edgeVec[10].pointIndexB = 6;
00370 _edgeVec[10].edgeTag = 34;
00371
00372 _edgeVec[11].pointIndexA = 3;
00373 _edgeVec[11].pointIndexB = 7;
00374 _edgeVec[11].edgeTag = 18;
00375
00376
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
00390 for(i = 0; i < 8; i++)
00391 pointInHalfSpace[i] = plane.isInHalfSpace(_pointVec[i]);
00392
00393
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
00412 for (; j++ <= lastButOne; i++)
00413 {
00414
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
00424 if (j <= lastButOne)
00425 {
00426
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
00436 osgSwap (slice.edgeVec[j], slice.edgeVec[k]);
00437 osgSwap (slice.pointVec[j], slice.pointVec[k]);
00438 swapCount++;
00439 }
00440 }
00441
00442
00443
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
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