00001
00002 #include <OSGDVRClipObjects.h>
00003 #include <OSGDVRTriangle.h>
00004 #include <OSGDVRClipper.h>
00005 #include <OSGDVRVolume.h>
00006 #include <OSGDVRRenderSlice.h>
00007
00008 #if !defined(darwin)
00009 #include <malloc.h>
00010 #endif
00011
00012 #include <stdlib.h>
00013
00014 OSG_USING_NAMESPACE
00015
00016 static void OSG_APIENTRY errorCallback (GLenum errorCode);
00017 static void OSG_APIENTRY beginCallback (GLenum which,
00018 void *data);
00019 static void OSG_APIENTRY endCallback (void *data);
00020 static void OSG_APIENTRY vertexCallback (GLvoid *vertexData,
00021 void *data);
00022 static void OSG_APIENTRY vertexCombineCallback(GLdouble *,
00023 GLdouble **,
00024 GLfloat *,
00025 GLdouble **,
00026 void *data);
00027
00028 DVRClipper::DVRClipper(void)
00029 {
00030 myTess = NULL;
00031
00032 sliceVertexData = (GLdouble*)malloc(6*6*sizeof(GLdouble));
00033
00034 numAddPerVertexAttr = 0;
00035 hasTesselatorSupport = false;
00036 }
00037
00038 DVRClipper::~DVRClipper(void)
00039 {
00040 if(myTess)
00041 gluDeleteTess(myTess);
00042
00043 free(sliceVertexData);
00044 }
00045
00046 void DVRClipper::setReferencePlane(const Plane &rP)
00047 {
00048 FDEBUG(("pre DVRVolume::setRefPlane - %f %f %f : %f\n",
00049 rP.getNormal()[0],
00050 rP.getNormal()[1],
00051 rP.getNormal()[2],
00052 rP.getDistanceFromOrigin()));
00053
00054 refPlane.set(rP.getNormal(), rP.getDistanceFromOrigin());
00055
00056 FDEBUG(("post DVRVolume::setRefPlane - %f %f %f : %f\n",
00057 refPlane.getNormal()[0],
00058 refPlane.getNormal()[1],
00059 refPlane.getNormal()[2],
00060 refPlane.getDistanceFromOrigin()));
00061 }
00062
00063 const Plane &DVRClipper::getReferencePlane() const
00064 {
00065 return refPlane;
00066 }
00067
00068
00069 bool DVRClipper::setNumAddPerVertexAttr(
00070 DVRVolume *volume,
00071 UInt32 additionalPerVertexAttributes)
00072 {
00073 numAddPerVertexAttr = additionalPerVertexAttributes;
00074
00075 sliceVertexData = (GLdouble*) realloc(
00076 sliceVertexData,
00077 6 * (6 + additionalPerVertexAttributes) * sizeof(GLdouble));
00078
00079 if(!sliceVertexData)
00080 return false;
00081
00082
00083 DVRClipObjectsPtr clipObjects = DVRVOLUME_PARAMETER(volume,
00084 DVRClipObjects);
00085
00086 if(clipObjects == NullFC)
00087 return true;
00088
00089 for(UInt32 i = 0; i < clipObjects->count(); i++)
00090 {
00091 DVRClipGeometryPtr clipObject = clipObjects->get(i);
00092
00093 if(!clipObject->setNumAddPerVertexAttr(additionalPerVertexAttributes))
00094 return false;
00095 }
00096 return true;
00097 }
00098
00099
00100 void DVRClipper::initialize(DVRVolume *volume)
00101 {
00102 if(volume == NULL)
00103 return;
00104
00105
00106 DVRClipObjectsPtr clipObjects = DVRVOLUME_PARAMETER(volume,
00107 DVRClipObjects);
00108
00109 if(clipObjects == NullFC)
00110 return;
00111
00112 if(!hasTesselatorSupport)
00113 {
00114
00115 hasTesselatorSupport = (atof((char*)gluGetString(GLU_VERSION)) >= 1.2);
00116
00117 if(!hasTesselatorSupport)
00118 return;
00119 }
00120
00121 if(myTess == NULL)
00122 {
00123 myTess = gluNewTess();
00124
00125
00126 gluTessCallback(myTess,
00127 GLU_TESS_COMBINE_DATA,
00128 reinterpret_cast<OSGGLUfuncptr>(vertexCombineCallback));
00129
00130 gluTessCallback(myTess,
00131 GLU_TESS_VERTEX_DATA,
00132 reinterpret_cast<OSGGLUfuncptr>(vertexCallback));
00133
00134 gluTessCallback(myTess,
00135 GLU_TESS_BEGIN_DATA,
00136 reinterpret_cast<OSGGLUfuncptr>(beginCallback));
00137
00138 gluTessCallback(myTess,
00139 GLU_TESS_END_DATA,
00140 reinterpret_cast<OSGGLUfuncptr>(endCallback));
00141
00142 gluTessCallback(myTess,
00143 GLU_TESS_ERROR,
00144 reinterpret_cast<OSGGLUfuncptr>(errorCallback));
00145
00146 }
00147
00148 }
00149
00150 void DVRClipper::reset(DVRVolume *volume)
00151 {
00152 if(volume == NULL || !hasTesselatorSupport)
00153 return;
00154
00155
00156 DVRClipObjectsPtr clipObjects = DVRVOLUME_PARAMETER(volume,
00157 DVRClipObjects);
00158
00159 if(clipObjects == NullFC)
00160 return;
00161
00162
00163 if(clipObjects->getClipMode() == DVRClipObjects::Intersection)
00164 {
00165 gluTessProperty(myTess,
00166 GLU_TESS_WINDING_RULE,
00167 GLU_TESS_WINDING_ABS_GEQ_TWO);
00168 }
00169 else
00170 {
00171 gluTessProperty(myTess,
00172 GLU_TESS_WINDING_RULE,
00173 GLU_TESS_WINDING_POSITIVE);
00174 }
00175
00176
00177 for(UInt32 i = 0; i < clipObjects->count(); i++)
00178 {
00179
00180 DVRClipGeometryPtr clipObject = clipObjects->get(i);
00181
00182 clipObject->resetLocalData ();
00183 clipObject->computeSeedVertices();
00184 }
00185 }
00186
00187 void DVRClipper::clipSlice( DVRVolume *volume,
00188 DVRSlice &unclippedSlice,
00189 const Vec3f &slicingNormal,
00190 Real32 dist2RefPlane,
00191 DVRRenderSlice &clippedSlice)
00192 {
00193 const Vec3f &texScale = unclippedSlice.getTextureScale ();
00194 const Vec3f &texTranslate = unclippedSlice.getTextureTranslate();
00195
00196
00197 DVRClipObjectsPtr clipObjects = DVRVOLUME_PARAMETER(volume,
00198 DVRClipObjects);
00199
00200
00201 if(clipObjects == NullFC)
00202 {
00203 DVRRenderSlicePrimitive *newPrimitive = new DVRRenderSlicePrimitive();
00204
00205 newPrimitive->type = GL_TRIANGLE_FAN;
00206
00207 for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
00208 {
00209 UInt32 idx = (6+numAddPerVertexAttr)*i;
00210 sliceVertexData[idx ] =
00211 unclippedSlice.getVertex(i).getValues()[0];
00212
00213 sliceVertexData[idx + 1] =
00214 unclippedSlice.getVertex(i).getValues()[1];
00215
00216 sliceVertexData[idx + 2] =
00217 unclippedSlice.getVertex(i).getValues()[2];
00218
00219
00220
00221 sliceVertexData[idx + 3] =
00222 texScale[0] *
00223 unclippedSlice.getVertex(i).getValues()[0] +
00224 texTranslate[0];
00225
00226 sliceVertexData[idx + 4] =
00227 texScale[1] *
00228 unclippedSlice.getVertex(i).getValues()[1] +
00229 texTranslate[1];
00230
00231 sliceVertexData[idx + 5] =
00232 texScale[2] *
00233 unclippedSlice.getVertex(i).getValues()[2] +
00234 texTranslate[2];
00235
00236 newPrimitive->vertices.push_back(&sliceVertexData[idx]);
00237 }
00238
00239 clippedSlice.push_back(newPrimitive);
00240
00241 return;
00242 }
00243
00244 if(!hasTesselatorSupport)
00245 return;
00246
00247
00248 if(clipObjects->getDoContours())
00249 {
00250 glDisable(GL_TEXTURE );
00251 glDisable(GL_LIGHTING );
00252
00253 glBegin (GL_LINE_STRIP);
00254 {
00255 int col = 0;
00256
00257 for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
00258 {
00259 glColor3f(col % 3 == 0 ? 1.0f : 0.0f,
00260 col % 3 == 1 ? 1.0f : 0.0f,
00261 col % 3 == 2 ? 1.0f : 0.0f);
00262
00263 col++;
00264
00265 glVertex3fv(unclippedSlice.getVertex(i).getValues());
00266 }
00267 }
00268 glEnd();
00269
00270 bool clipAwayOutside =
00271 clipObjects->getClipMode() == DVRClipObjects::Difference;
00272
00273 for(UInt32 i = 0; i < clipObjects->count(); i++)
00274 {
00275
00276 DVRClipGeometryPtr clipObject = clipObjects->get(i);
00277
00278
00279
00280
00281 const DVRTriangleList &contours =
00282 clipObject->getContours(dist2RefPlane,
00283 !clipAwayOutside,
00284 slicingNormal);
00285
00286 if(!contours.empty())
00287 {
00288 DVRTriangle *current;
00289 DVRTriangle *contourStart;
00290
00291
00292 DVRTriangleList::const_iterator contoursIt;
00293
00294 for(contoursIt = contours.begin();
00295 contoursIt != contours.end ();
00296 contoursIt++)
00297 {
00298 contourStart = current = *contoursIt;
00299
00300 glBegin(GL_LINE_STRIP);
00301 {
00302 int col = 0;
00303
00304
00305 do
00306 {
00307 glColor3f(col % 3 == 0 ? 1.0f : 0.0f,
00308 col % 3 == 1 ? 1.0f : 0.0f,
00309 col % 3 == 2 ? 1.0f : 0.0f);
00310
00311 col++;
00312
00313 glVertex3dv(current->cutPoint);
00314
00315 current = current->contourNeighbour;
00316
00317 } while(current!= contourStart);
00318 }
00319 glEnd();
00320 }
00321 }
00322 }
00323
00324 glEnable(GL_TEXTURE );
00325 glEnable(GL_LIGHTING);
00326
00327 }
00328 else
00329 {
00330
00331
00332
00333 gluTessNormal(myTess,
00334 slicingNormal[0],
00335 slicingNormal[1],
00336 slicingNormal[2]);
00337
00338 clippedSlice.clear();
00339
00340 gluTessBeginPolygon(myTess, &clippedSlice);
00341
00342
00343 gluTessBeginContour(myTess);
00344
00345 for(UInt32 i = 0; i < unclippedSlice.getVertexCount(); i++)
00346 {
00347 UInt32 idx = (6 + numAddPerVertexAttr) * i;
00348
00349 sliceVertexData[idx ] =
00350 unclippedSlice.getVertex(i).getValues()[0];
00351
00352 sliceVertexData[idx + 1] =
00353 unclippedSlice.getVertex(i).getValues()[1];
00354
00355 sliceVertexData[idx + 2] =
00356 unclippedSlice.getVertex(i).getValues()[2];
00357
00358
00359 sliceVertexData[idx + 3] =
00360 texScale[0] *
00361 unclippedSlice.getVertex(i).getValues()[0] +
00362 texTranslate[0];
00363
00364 sliceVertexData[idx + 4] =
00365 texScale[1] *
00366 unclippedSlice.getVertex(i).getValues()[1] +
00367 texTranslate[1];
00368
00369 sliceVertexData[idx + 5] =
00370 texScale[2] *
00371 unclippedSlice.getVertex(i).getValues()[2] +
00372 texTranslate[2];
00373
00374 gluTessVertex(myTess,
00375 &sliceVertexData[idx],
00376 &sliceVertexData[idx]);
00377 }
00378
00379 gluTessEndContour(myTess);
00380
00381
00382 if(clipObjects->getClipMode() != DVRClipObjects::Off)
00383 {
00384
00385 bool clipAwayOutside =
00386 clipObjects->getClipMode() == DVRClipObjects::Difference;
00387
00388
00389
00390 for(UInt32 i = 0; i < clipObjects->count(); i++)
00391 {
00392
00393 DVRClipGeometryPtr clipObject = clipObjects->get(i);
00394
00395
00396
00397
00398 const DVRTriangleList &contours =
00399 clipObject->getContours( dist2RefPlane,
00400 !clipAwayOutside,
00401 slicingNormal);
00402
00403 if(!contours.empty())
00404 {
00405 DVRTriangle *current;
00406 DVRTriangle *contourStart;
00407
00408
00409 DVRTriangleList::const_iterator contoursIt;
00410
00411 for(contoursIt = contours.begin();
00412 contoursIt != contours.end ();
00413 contoursIt++)
00414 {
00415 contourStart = current = *contoursIt;
00416
00417
00418 gluTessBeginContour(myTess);
00419
00420
00421 do
00422 {
00423
00424 current->cutPoint[3] =
00425 texScale[0] *
00426 current->cutPoint[0] +
00427 texTranslate[0];
00428
00429 current->cutPoint[4] =
00430 texScale[1] *
00431 current->cutPoint[1] +
00432 texTranslate[1];
00433
00434 current->cutPoint[5] =
00435 texScale[2] *
00436 current->cutPoint[2] +
00437 texTranslate[2];
00438
00439 if(!current->cutPoint)
00440 std::cerr << "WTF: cutPoint is NULL"
00441 << std::endl;
00442
00443 gluTessVertex(myTess,
00444 current->cutPoint,
00445 current->cutPoint);
00446
00447 current = current->contourNeighbour;
00448
00449 } while(current != contourStart);
00450
00451 gluTessEndContour(myTess);
00452 }
00453 }
00454 }
00455 }
00456
00457 gluTessEndPolygon(myTess);
00458 }
00459 }
00460
00461 void OSG_APIENTRY errorCallback(GLenum errorCode)
00462 {
00463 SFATAL << "Error "
00464 << gluErrorString(errorCode)
00465 << " occured during tesselation!"
00466 << std::endl;
00467 }
00468
00469 void OSG_APIENTRY beginCallback(GLenum which, void *data)
00470 {
00471 DVRRenderSlice *sliceData = (DVRRenderSlice *) data;
00472
00473 if(sliceData->directRender)
00474 {
00475 glBegin(which);
00476 }
00477 else
00478 {
00479 DVRRenderSlicePrimitive *newPrimitive = new DVRRenderSlicePrimitive();
00480
00481 newPrimitive->vertices.reserve(3);
00482
00483 newPrimitive->type = which;
00484
00485 sliceData->push_back(newPrimitive);
00486 }
00487 }
00488
00489 void OSG_APIENTRY endCallback(void *data)
00490 {
00491 DVRRenderSlice *sliceData = (DVRRenderSlice *) data;
00492
00493 if(sliceData->directRender)
00494 {
00495 glEnd();
00496 }
00497 }
00498
00499 void OSG_APIENTRY vertexCallback(GLvoid *vertexData, void *data)
00500 {
00501 GLdouble *v = (GLdouble *) vertexData;
00502
00503 DVRRenderSlice *sliceData = (DVRRenderSlice *) data;
00504
00505 if(sliceData->directRender)
00506 {
00507 switch(sliceData->orientation)
00508 {
00509 case DVRRenderSlice::UNDEFINED:
00510 glTexCoord3dv(&v[3]);
00511 break;
00512
00513 case DVRRenderSlice::XY:
00514 glTexCoord2d(v[3], v[4]);
00515 break;
00516
00517 case DVRRenderSlice::XZ:
00518 glTexCoord2d(v[3], v[5]);
00519 break;
00520
00521 case DVRRenderSlice::YZ:
00522 glTexCoord2d(v[4], v[5]);
00523 break;
00524
00525 default:
00526 break;
00527 }
00528 glVertex3dv(v);
00529 }
00530 else
00531 {
00532 sliceData->back()->vertices.push_back(v);
00533 }
00534 }
00535
00536 void OSG_APIENTRY vertexCombineCallback(GLdouble *coords,
00537 GLdouble *vertexData[4],
00538 GLfloat weight [4],
00539 GLdouble **dataOut,
00540 void *data )
00541 {
00542 DVRRenderSlice *sliceData = (DVRRenderSlice *) data;
00543
00544
00545 if(sliceData->maxVertexCombineData <= sliceData->numVertexCombineData)
00546 {
00547 if(sliceData->maxVertexCombineData == 0)
00548 sliceData->maxVertexCombineData = 2;
00549 else
00550 sliceData->maxVertexCombineData *= 2;
00551
00552 sliceData->vertexCombineData =
00553 (GLdouble *) realloc(sliceData->vertexCombineData,
00554 (6 +
00555 sliceData->numPerVertexData) *
00556 sliceData->maxVertexCombineData *
00557 sizeof(GLdouble));
00558
00559 FDEBUG(("realloc vd %i\n",sliceData->numVertexCombineData));
00560 }
00561
00562 GLdouble *vertex =
00563 &(sliceData->vertexCombineData[
00564 (6 + sliceData->numPerVertexData) *
00565 sliceData->numVertexCombineData ]);
00566
00567 sliceData->numVertexCombineData++;
00568
00569 vertex[0] = coords[0];
00570 vertex[1] = coords[1];
00571 vertex[2] = coords[2];
00572
00573
00574
00575
00576
00577 for(UInt32 i = 0; i < 3+sliceData->numPerVertexData; i++)
00578 {
00579 vertex[i+3] = 0.0;
00580 }
00581
00582 for(UInt32 j = 0; j < 4; j++)
00583 {
00584
00585 if(vertexData[j] == NULL)
00586 continue;
00587
00588 for(UInt32 i = 0; i < 3+sliceData->numPerVertexData; i++)
00589 {
00590 vertex[i + 3] += weight[j] * vertexData[j][i + 3];
00591 }
00592 }
00593
00594 *dataOut = vertex;
00595 }