Changeset 2349 for trunk/packages/vizservers
- Timestamp:
- Aug 12, 2011 1:05:54 PM (13 years ago)
- Location:
- trunk/packages/vizservers/vtkvis
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/packages/vizservers/vtkvis/RpStreamlines.cpp
r2332 r2349 9 9 #include <ctime> 10 10 #include <cfloat> 11 #include <cmath> 12 13 #include <vtkMath.h> 11 14 #include <vtkActor.h> 12 15 #include <vtkProperty.h> … … 21 24 #include <vtkTubeFilter.h> 22 25 #include <vtkRibbonFilter.h> 26 #include <vtkTransform.h> 27 #include <vtkTransformPolyDataFilter.h> 23 28 24 29 #include "RpStreamlines.h" … … 36 41 _seedColor[1] = 1.0f; 37 42 _seedColor[2] = 1.0f; 43 vtkMath::RandomSeed((int)time(NULL)); 44 srand((unsigned int)time(NULL)); 38 45 } 39 46 … … 92 99 } 93 100 101 /** 102 * \brief Get a pseudo-random number in range [min,max] 103 */ 104 double Streamlines::getRandomNum(double min, double max) 105 { 106 #if 1 107 return vtkMath::Random(min, max); 108 #else 109 int r = rand(); 110 return (min + ((double)r / RAND_MAX) * (max - min)); 111 #endif 112 } 113 114 /** 115 * \brief Get a random 3D point within an AABB 116 * 117 * \param[out] pt The random point 118 * \param[in] bounds The bounds of the AABB 119 */ 94 120 void Streamlines::getRandomPoint(double pt[3], const double bounds[6]) 95 121 { 96 int r = rand(); 97 pt[0] = bounds[0] + ((double)r / RAND_MAX) * (bounds[1] - bounds[0]); 98 r = rand(); 99 pt[1] = bounds[2] + ((double)r / RAND_MAX) * (bounds[3] - bounds[2]); 100 r = rand(); 101 pt[2] = bounds[4] + ((double)r / RAND_MAX) * (bounds[5] - bounds[4]); 102 } 103 104 void Streamlines::getRandomCellPt(vtkDataSet *ds, double pt[3]) 122 pt[0] = getRandomNum(bounds[0], bounds[1]); 123 pt[1] = getRandomNum(bounds[2], bounds[3]); 124 pt[2] = getRandomNum(bounds[4], bounds[5]); 125 } 126 127 /** 128 * \brief Get a random point within a triangle (including edges) 129 * 130 * \param[out] pt The random point 131 * \param[in] v1 Triangle vertex 1 132 * \param[in] v2 Triangle vertex 2 133 * \param[in] v3 Triangle vertex 3 134 */ 135 void Streamlines::getRandomPointInTriangle(double pt[3], 136 const double v1[3], 137 const double v2[3], 138 const double v3[3]) 139 { 140 // Choose random barycentric coordinates 141 double bary[3]; 142 bary[0] = getRandomNum(0, 1); 143 bary[1] = getRandomNum(0, 1); 144 if (bary[0] + bary[1] > 1.0) { 145 bary[0] = 1.0 - bary[0]; 146 bary[1] = 1.0 - bary[1]; 147 } 148 bary[2] = 1.0 - bary[0] - bary[1]; 149 150 TRACE("bary %g %g %g", bary[0], bary[1], bary[2]); 151 // Convert to cartesian coords 152 for (int i = 0; i < 3; i++) { 153 pt[i] = v1[i] * bary[0] + v2[i] * bary[1] + v3[i] * bary[2]; 154 } 155 } 156 157 /** 158 * \brief Get a random point on a line segment (including endpoints) 159 */ 160 void Streamlines::getRandomPointOnLineSegment(double pt[3], 161 const double endpt[3], 162 const double endpt2[3]) 163 { 164 double ratio = getRandomNum(0, 1); 165 pt[0] = endpt[0] + ratio * (endpt2[0] - endpt[0]); 166 pt[1] = endpt[1] + ratio * (endpt2[1] - endpt[1]); 167 pt[2] = endpt[2] + ratio * (endpt2[2] - endpt[2]); 168 } 169 170 /** 171 * \brief Get a random point within a vtkDataSet's mesh 172 * 173 * Note: This currently doesn't give a uniform distribution of 174 * points in space and can generate points outside the mesh 175 */ 176 void Streamlines::getRandomCellPt(double pt[3], vtkDataSet *ds) 105 177 { 106 178 int numCells = (int)ds->GetNumberOfCells(); 179 // XXX: Not uniform distribution (shouldn't use mod, and assumes 180 // all cells are equal area/volume) 107 181 int cell = rand() % numCells; 108 182 double bounds[6]; 109 183 ds->GetCellBounds(cell, bounds); 110 int r = rand(); 111 pt[0] = bounds[0] + ((double)r / RAND_MAX) * (bounds[1] - bounds[0]); 112 r = rand(); 113 pt[1] = bounds[2] + ((double)r / RAND_MAX) * (bounds[3] - bounds[2]); 114 r = rand(); 115 pt[2] = bounds[4] + ((double)r / RAND_MAX) * (bounds[5] - bounds[4]); 184 // Note: point is inside AABB of cell, but may be outside the cell 185 getRandomPoint(pt, bounds); 116 186 } 117 187 … … 164 234 165 235 _streamTracer->SetInput(ds); 166 167 // Set up seed source object168 vtkSmartPointer<vtkPolyData> seed = vtkSmartPointer<vtkPolyData>::New();169 vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New();170 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();171 172 int numPoints = 200;173 srand((unsigned int)time(NULL));174 for (int i = 0; i < numPoints; i++) {175 double pt[3];176 getRandomCellPt(ds, pt);177 TRACE("Seed pt: %g %g %g", pt[0], pt[1], pt[2]);178 pts->InsertNextPoint(pt);179 cells->InsertNextCell(1);180 cells->InsertCellPoint(i);181 }182 183 seed->SetPoints(pts);184 seed->SetVerts(cells);185 186 TRACE("Seed points: %d", seed->GetNumberOfPoints());187 188 236 _streamTracer->SetMaximumPropagation(maxBound); 189 _streamTracer->SetSource(seed);190 237 191 238 if (_pdMapper == NULL) { … … 193 240 _pdMapper->SetResolveCoincidentTopologyToPolygonOffset(); 194 241 _pdMapper->ScalarVisibilityOn(); 195 // _pdMapper->ScalarVisibilityOff();196 242 } 197 243 if (_seedMapper == NULL) { 198 244 _seedMapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 199 245 _seedMapper->SetResolveCoincidentTopologyToPolygonOffset(); 200 _seedMapper->SetInput(seed); 201 } 246 } 247 248 // Set up seed source object 249 setSeedToRandomPoints(200); 202 250 203 251 switch (_lineType) { … … 262 310 * \brief Use randomly distributed seed points 263 311 * 312 * Note: The current implementation doesn't give a uniform 313 * distribution of points, and points outside the mesh bounds 314 * may be generated 315 * 264 316 * \param[in] numPoints Number of random seed points to generate 265 317 */ … … 272 324 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New(); 273 325 274 srand((unsigned int)time(NULL));275 326 for (int i = 0; i < numPoints; i++) { 276 327 double pt[3]; 277 getRandomCellPt( _dataSet->getVtkDataSet(), pt);328 getRandomCellPt(pt, _dataSet->getVtkDataSet()); 278 329 TRACE("Seed pt: %g %g %g", pt[0], pt[1], pt[2]); 279 330 pts->InsertNextPoint(pt); … … 354 405 355 406 /** 407 * \brief Create seed points inside a disk with an optional hole 408 * 409 * \param[in] center Center point of disk 410 * \param[in] normal Normal vector to orient disk 411 * \param[in] radius Radius of disk 412 * \param[in] innerRadius Radius of hole at center of disk 413 * \param[in] numPoints Number of random points to generate 414 */ 415 void Streamlines::setSeedToDisk(double center[3], 416 double normal[3], 417 double radius, 418 double innerRadius, 419 int numPoints) 420 { 421 if (_streamTracer != NULL) { 422 // Set up seed source object 423 vtkSmartPointer<vtkPolyData> seed = vtkSmartPointer<vtkPolyData>::New(); 424 vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New(); 425 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New(); 426 427 // The following code is based on vtkRegularPolygonSource::RequestData 428 429 double px[3]; 430 double py[3]; 431 double axis[3] = {1., 0., 0.}; 432 433 if (vtkMath::Normalize(normal) == 0.0) { 434 normal[0] = 0.0; 435 normal[1] = 0.0; 436 normal[2] = 1.0; 437 } 438 439 // Find axis in plane (orthogonal to normal) 440 bool done = false; 441 vtkMath::Cross(normal, axis, px); 442 if (vtkMath::Normalize(px) > 1.0e-3) { 443 done = true; 444 } 445 if (!done) { 446 axis[0] = 0.0; 447 axis[1] = 1.0; 448 axis[2] = 0.0; 449 vtkMath::Cross(normal, axis, px); 450 if (vtkMath::Normalize(px) > 1.0e-3) { 451 done = true; 452 } 453 } 454 if (!done) { 455 axis[0] = 0.0; 456 axis[1] = 0.0; 457 axis[2] = 1.0; 458 vtkMath::Cross(normal, axis, px); 459 vtkMath::Normalize(px); 460 } 461 // Create third orthogonal basis vector 462 vtkMath::Cross(px, normal, py); 463 464 double minSquared = (innerRadius*innerRadius)/(radius*radius); 465 for (int j = 0; j < numPoints; j++) { 466 // Get random sweep angle and radius 467 double angle = getRandomNum(0, 2.0 * vtkMath::DoublePi()); 468 // Need sqrt to get uniform distribution 469 double r = sqrt(getRandomNum(minSquared, 1)) * radius; 470 double pt[3]; 471 for (int i = 0; i < 3; i++) { 472 pt[i] = center[i] + r * (px[i] * cos(angle) + py[i] * sin(angle)); 473 } 474 TRACE("Seed pt: %g %g %g", pt[0], pt[1], pt[2]); 475 pts->InsertNextPoint(pt); 476 cells->InsertNextCell(1); 477 cells->InsertCellPoint(j); 478 } 479 480 seed->SetPoints(pts); 481 seed->SetVerts(cells); 482 483 TRACE("Seed points: %d", seed->GetNumberOfPoints()); 484 vtkSmartPointer<vtkDataSet> oldSeed; 485 if (_streamTracer->GetSource() != NULL) { 486 oldSeed = _streamTracer->GetSource(); 487 } 488 489 _streamTracer->SetSource(seed); 490 if (oldSeed != NULL) { 491 oldSeed->SetPipelineInformation(NULL); 492 } 493 494 _seedMapper->SetInput(seed); 495 } 496 } 497 498 /** 356 499 * \brief Use seed points from an n-sided polygon 357 500 * 358 501 * \param[in] center Center point of polygon 359 502 * \param[in] normal Normal vector to orient polygon 503 * \param[in] angle Angle in degrees to rotate about normal 360 504 * \param[in] radius Radius of circumscribing circle 361 505 * \param[in] numSides Number of polygon sides (and points) to generate … … 363 507 void Streamlines::setSeedToPolygon(double center[3], 364 508 double normal[3], 509 double angle, 365 510 double radius, 366 511 int numSides) … … 376 521 seed->GeneratePolygonOn(); 377 522 523 if (angle != 0.0) { 524 vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New(); 525 trans->RotateWXYZ(angle, normal); 526 vtkSmartPointer<vtkTransformPolyDataFilter> transFilt = 527 vtkSmartPointer<vtkTransformPolyDataFilter>::New(); 528 transFilt->SetInputConnection(seed->GetOutputPort()); 529 transFilt->SetTransform(trans); 530 } 531 378 532 TRACE("Seed points: %d", numSides); 379 533 vtkSmartPointer<vtkDataSet> oldSeed; … … 382 536 } 383 537 384 _streamTracer->SetSourceConnection(seed->GetOutputPort()); 538 if (angle != 0.0) { 539 vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New(); 540 trans->Translate(+center[0], +center[1], +center[2]); 541 trans->RotateWXYZ(angle, normal); 542 trans->Translate(-center[0], -center[1], -center[2]); 543 vtkSmartPointer<vtkTransformPolyDataFilter> transFilt = 544 vtkSmartPointer<vtkTransformPolyDataFilter>::New(); 545 transFilt->SetInputConnection(seed->GetOutputPort()); 546 transFilt->SetTransform(trans); 547 _streamTracer->SetSourceConnection(transFilt->GetOutputPort()); 548 _seedMapper->SetInputConnection(transFilt->GetOutputPort()); 549 } else { 550 _streamTracer->SetSourceConnection(seed->GetOutputPort()); 551 _seedMapper->SetInputConnection(seed->GetOutputPort()); 552 } 553 385 554 if (oldSeed != NULL) { 386 555 oldSeed->SetPipelineInformation(NULL); 387 556 } 388 389 _seedMapper->SetInputConnection(seed->GetOutputPort()); 557 } 558 } 559 560 /** 561 * \brief Use seed points from an n-sided polygon 562 * 563 * \param[in] center Center point of polygon 564 * \param[in] normal Normal vector to orient polygon 565 * \param[in] angle Angle in degrees to rotate about normal 566 * \param[in] radius Radius of circumscribing circle 567 * \param[in] numSides Number of polygon sides (and points) to generate 568 * \param[in] numPoints Number of random points to generate 569 */ 570 void Streamlines::setSeedToFilledPolygon(double center[3], 571 double normal[3], 572 double angle, 573 double radius, 574 int numSides, 575 int numPoints) 576 { 577 if (_streamTracer != NULL) { 578 // Set up seed source object 579 vtkSmartPointer<vtkPolyData> seed = vtkSmartPointer<vtkPolyData>::New(); 580 vtkSmartPointer<vtkPoints> pts = vtkSmartPointer<vtkPoints>::New(); 581 vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New(); 582 583 // The following code is based on vtkRegularPolygonSource::RequestData 584 585 double px[3]; 586 double py[3]; 587 double axis[3] = {1., 0., 0.}; 588 589 if (vtkMath::Normalize(normal) == 0.0) { 590 normal[0] = 0.0; 591 normal[1] = 0.0; 592 normal[2] = 1.0; 593 } 594 595 // Find axis in plane (orthogonal to normal) 596 bool done = false; 597 vtkMath::Cross(normal, axis, px); 598 if (vtkMath::Normalize(px) > 1.0e-3) { 599 done = true; 600 } 601 if (!done) { 602 axis[0] = 0.0; 603 axis[1] = 1.0; 604 axis[2] = 0.0; 605 vtkMath::Cross(normal, axis, px); 606 if (vtkMath::Normalize(px) > 1.0e-3) { 607 done = true; 608 } 609 } 610 if (!done) { 611 axis[0] = 0.0; 612 axis[1] = 0.0; 613 axis[2] = 1.0; 614 vtkMath::Cross(normal, axis, px); 615 vtkMath::Normalize(px); 616 } 617 // Create third orthogonal basis vector 618 vtkMath::Cross(px, normal, py); 619 620 double verts[numSides][3]; 621 double sliceTheta = 2.0 * vtkMath::DoublePi() / (double)numSides; 622 angle = vtkMath::RadiansFromDegrees(angle); 623 for (int j = 0; j < numSides; j++) { 624 for (int i = 0; i < 3; i++) { 625 double theta = sliceTheta * (double)j - angle; 626 verts[j][i] = center[i] + radius * (px[i] * cos(theta) + 627 py[i] * sin(theta)); 628 } 629 TRACE("Vert %d: %g %g %g", j, verts[j][0], verts[j][1], verts[j][2]); 630 } 631 632 // Note: this gives a uniform distribution because the polygon is regular and 633 // the triangular sections have equal area 634 if (numSides == 3) { 635 for (int j = 0; j < numPoints; j++) { 636 double pt[3]; 637 getRandomPointInTriangle(pt, verts[0], verts[1], verts[2]); 638 TRACE("Seed pt: %g %g %g", pt[0], pt[1], pt[2]); 639 pts->InsertNextPoint(pt); 640 cells->InsertNextCell(1); 641 cells->InsertCellPoint(j); 642 } 643 } else { 644 for (int j = 0; j < numPoints; j++) { 645 // Get random triangle section 646 int tri = rand() % numSides; 647 double pt[3]; 648 getRandomPointInTriangle(pt, center, verts[tri], verts[(tri+1) % numSides]); 649 TRACE("Seed pt: %g %g %g", pt[0], pt[1], pt[2]); 650 pts->InsertNextPoint(pt); 651 cells->InsertNextCell(1); 652 cells->InsertCellPoint(j); 653 } 654 } 655 656 seed->SetPoints(pts); 657 seed->SetVerts(cells); 658 659 TRACE("Seed points: %d", seed->GetNumberOfPoints()); 660 vtkSmartPointer<vtkDataSet> oldSeed; 661 if (_streamTracer->GetSource() != NULL) { 662 oldSeed = _streamTracer->GetSource(); 663 } 664 665 _streamTracer->SetSource(seed); 666 if (oldSeed != NULL) { 667 oldSeed->SetPipelineInformation(NULL); 668 } 669 670 _seedMapper->SetInput(seed); 390 671 } 391 672 } -
trunk/packages/vizservers/vtkvis/RpStreamlines.h
r2332 r2349 64 64 void setSeedToRake(double start[3], double end[3], int numPoints); 65 65 66 void setSeedToDisk(double center[3], double normal[3], 67 double radius, double innerRadius, int numPoints); 68 66 69 void setSeedToPolygon(double center[3], double normal[3], 67 double radius, int numSides); 70 double angle, double radius, 71 int numSides); 72 73 void setSeedToFilledPolygon(double center[3], double normal[3], 74 double angle, double radius, 75 int numSides, int numPoints); 68 76 69 77 void setMaxPropagation(double length); … … 87 95 virtual void update(); 88 96 97 static double getRandomNum(double min, double max); 89 98 static void getRandomPoint(double pt[3], const double bounds[6]); 90 static void getRandomCellPt(vtkDataSet *ds, double pt[3]); 99 static void getRandomPointInTriangle(double pt[3], 100 const double v1[3], 101 const double v2[3], 102 const double v3[3]); 103 static void getRandomPointOnLineSegment(double pt[3], 104 const double endpt[3], 105 const double endpt2[3]); 106 static void getRandomCellPt(double pt[3], vtkDataSet *ds); 91 107 92 108 LineType _lineType; -
trunk/packages/vizservers/vtkvis/RpVtkRenderer.cpp
r2335 r2349 5442 5442 * \brief Set the streamlines seed to points along a line 5443 5443 */ 5444 void Renderer::setStreamlinesSeedToRake(const DataSetId& id, double start[3], double end[3], int numPoints) 5444 void Renderer::setStreamlinesSeedToRake(const DataSetId& id, 5445 double start[3], double end[3], 5446 int numPoints) 5445 5447 { 5446 5448 StreamlinesHashmap::iterator itr; … … 5467 5469 5468 5470 /** 5471 * \brief Set the streamlines seed to points inside a disk, with optional 5472 * hole 5473 */ 5474 void Renderer::setStreamlinesSeedToDisk(const DataSetId& id, 5475 double center[3], double normal[3], 5476 double radius, double innerRadius, 5477 int numPoints) 5478 { 5479 StreamlinesHashmap::iterator itr; 5480 5481 bool doAll = false; 5482 5483 if (id.compare("all") == 0) { 5484 itr = _streamlines.begin(); 5485 doAll = true; 5486 } else { 5487 itr = _streamlines.find(id); 5488 } 5489 if (itr == _streamlines.end()) { 5490 ERROR("Streamlines not found: %s", id.c_str()); 5491 return; 5492 } 5493 5494 do { 5495 itr->second->setSeedToDisk(center, normal, radius, innerRadius, numPoints); 5496 } while (doAll && ++itr != _streamlines.end()); 5497 5498 _needsRedraw = true; 5499 } 5500 5501 /** 5469 5502 * \brief Set the streamlines seed to vertices of an n-sided polygon 5470 5503 */ 5471 5504 void Renderer::setStreamlinesSeedToPolygon(const DataSetId& id, 5472 5505 double center[3], double normal[3], 5473 double radius, int numSides) 5506 double angle, double radius, 5507 int numSides) 5474 5508 { 5475 5509 StreamlinesHashmap::iterator itr; … … 5489 5523 5490 5524 do { 5491 itr->second->setSeedToPolygon(center, normal, radius, numSides); 5525 itr->second->setSeedToPolygon(center, normal, angle, radius, numSides); 5526 } while (doAll && ++itr != _streamlines.end()); 5527 5528 _needsRedraw = true; 5529 } 5530 5531 /** 5532 * \brief Set the streamlines seed to vertices of an n-sided polygon 5533 */ 5534 void Renderer::setStreamlinesSeedToFilledPolygon(const DataSetId& id, 5535 double center[3], 5536 double normal[3], 5537 double angle, double radius, 5538 int numSides, int numPoints) 5539 { 5540 StreamlinesHashmap::iterator itr; 5541 5542 bool doAll = false; 5543 5544 if (id.compare("all") == 0) { 5545 itr = _streamlines.begin(); 5546 doAll = true; 5547 } else { 5548 itr = _streamlines.find(id); 5549 } 5550 if (itr == _streamlines.end()) { 5551 ERROR("Streamlines not found: %s", id.c_str()); 5552 return; 5553 } 5554 5555 do { 5556 itr->second->setSeedToFilledPolygon(center, normal, angle, 5557 radius, numSides, numPoints); 5492 5558 } while (doAll && ++itr != _streamlines.end()); 5493 5559 … … 6388 6454 6389 6455 /** 6456 * \brief Set the VTK camera parameters based on a 4x4 view matrix 6457 */ 6458 void Renderer::setCameraFromMatrix(vtkCamera *camera, vtkMatrix4x4& mat) 6459 { 6460 double d = camera->GetDistance(); 6461 double vu[3]; 6462 vu[0] = mat[1][0]; 6463 vu[1] = mat[1][1]; 6464 vu[2] = mat[1][2]; 6465 double trans[3]; 6466 trans[0] = mat[0][3]; 6467 trans[1] = mat[1][3]; 6468 trans[2] = mat[2][3]; 6469 mat[0][3] = 0; 6470 mat[1][3] = 0; 6471 mat[2][3] = 0; 6472 double vpn[3] = {mat[2][0], mat[2][1], mat[2][2]}; 6473 double pos[3]; 6474 // With translation removed, we have an orthogonal matrix, 6475 // so the inverse is the transpose 6476 mat.Transpose(); 6477 mat.MultiplyPoint(trans, pos); 6478 pos[0] = -pos[0]; 6479 pos[1] = -pos[1]; 6480 pos[2] = -pos[2]; 6481 double fp[3]; 6482 fp[0] = pos[0] - vpn[0] * d; 6483 fp[1] = pos[1] - vpn[1] * d; 6484 fp[2] = pos[2] - vpn[2] * d; 6485 camera->SetPosition(pos); 6486 camera->SetFocalPoint(fp); 6487 camera->SetViewUp(vu); 6488 } 6489 6490 inline void quaternionToMatrix4x4(double quat[4], vtkMatrix4x4& mat) 6491 { 6492 double ww = quat[0]*quat[0]; 6493 double wx = quat[0]*quat[1]; 6494 double wy = quat[0]*quat[2]; 6495 double wz = quat[0]*quat[3]; 6496 6497 double xx = quat[1]*quat[1]; 6498 double yy = quat[2]*quat[2]; 6499 double zz = quat[3]*quat[3]; 6500 6501 double xy = quat[1]*quat[2]; 6502 double xz = quat[1]*quat[3]; 6503 double yz = quat[2]*quat[3]; 6504 6505 double rr = xx + yy + zz; 6506 // normalization factor, just in case quaternion was not normalized 6507 double f = double(1)/double(sqrt(ww + rr)); 6508 double s = (ww - rr)*f; 6509 f *= 2; 6510 6511 mat[0][0] = xx*f + s; 6512 mat[1][0] = (xy + wz)*f; 6513 mat[2][0] = (xz - wy)*f; 6514 6515 mat[0][1] = (xy - wz)*f; 6516 mat[1][1] = yy*f + s; 6517 mat[2][1] = (yz + wx)*f; 6518 6519 mat[0][2] = (xz + wy)*f; 6520 mat[1][2] = (yz - wx)*f; 6521 mat[2][2] = zz*f + s; 6522 } 6523 6524 inline void quaternionToTransposeMatrix4x4(double quat[4], vtkMatrix4x4& mat) 6525 { 6526 double ww = quat[0]*quat[0]; 6527 double wx = quat[0]*quat[1]; 6528 double wy = quat[0]*quat[2]; 6529 double wz = quat[0]*quat[3]; 6530 6531 double xx = quat[1]*quat[1]; 6532 double yy = quat[2]*quat[2]; 6533 double zz = quat[3]*quat[3]; 6534 6535 double xy = quat[1]*quat[2]; 6536 double xz = quat[1]*quat[3]; 6537 double yz = quat[2]*quat[3]; 6538 6539 double rr = xx + yy + zz; 6540 // normalization factor, just in case quaternion was not normalized 6541 double f = double(1)/double(sqrt(ww + rr)); 6542 double s = (ww - rr)*f; 6543 f *= 2; 6544 6545 mat[0][0] = xx*f + s; 6546 mat[0][1] = (xy + wz)*f; 6547 mat[0][2] = (xz - wy)*f; 6548 6549 mat[1][0] = (xy - wz)*f; 6550 mat[1][1] = yy*f + s; 6551 mat[1][2] = (yz + wx)*f; 6552 6553 mat[2][0] = (xz + wy)*f; 6554 mat[2][1] = (yz - wx)*f; 6555 mat[2][2] = zz*f + s; 6556 } 6557 6558 /** 6390 6559 * \brief Set the orientation of the camera from a quaternion 6391 6560 * 6392 6561 * \param[in] quat A quaternion with scalar part first: w,x,y,z 6393 */ 6394 void Renderer::setCameraOrientation(double quat[4]) 6562 * \param[in] absolute Is rotation absolute or relative? 6563 */ 6564 void Renderer::setCameraOrientation(double quat[4], bool absolute) 6395 6565 { 6396 6566 if (_cameraMode == IMAGE) … … 6398 6568 vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera(); 6399 6569 vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New(); 6400 double mat3[3][3];6401 vtkMath::QuaternionToMatrix3x3(quat, mat3);6402 6570 vtkSmartPointer<vtkMatrix4x4> mat4 = vtkSmartPointer<vtkMatrix4x4>::New(); 6403 for (int r = 0; r < 3; r++) { 6404 memcpy((*mat4)[r], mat3[r], sizeof(double)*3); 6405 } 6406 TRACE("Arcball camera matrix: %g %g %g %g %g %g %g %g %g", 6407 (*mat4)[0][0], (*mat4)[0][1], (*mat4)[0][2], 6408 (*mat4)[1][0], (*mat4)[1][1], (*mat4)[1][2], 6409 (*mat4)[2][0], (*mat4)[2][1], (*mat4)[2][2]); 6410 camera->SetPosition(0, 0, 1); 6411 camera->SetFocalPoint(0, 0, 0); 6412 camera->SetViewUp(0, 1, 0); 6413 setViewAngle(_windowHeight); 6414 double bounds[6]; 6415 collectBounds(bounds, false); 6416 _renderer->ResetCamera(bounds); 6417 camera->GetFocalPoint(_cameraFocalPoint); 6418 trans->Translate(+_cameraFocalPoint[0], +_cameraFocalPoint[1], +_cameraFocalPoint[2]); 6419 trans->Concatenate(mat4); 6420 trans->Translate(-_cameraFocalPoint[0], -_cameraFocalPoint[1], -_cameraFocalPoint[2]); 6421 camera->ApplyTransform(trans); 6571 6572 if (absolute) { 6573 quaternionToMatrix4x4(quat, *mat4); 6574 #ifdef DEBUG 6575 TRACE("Arcball camera matrix:\n %g %g %g\n %g %g %g\n %g %g %g", 6576 (*mat4)[0][0], (*mat4)[0][1], (*mat4)[0][2], 6577 (*mat4)[1][0], (*mat4)[1][1], (*mat4)[1][2], 6578 (*mat4)[2][0], (*mat4)[2][1], (*mat4)[2][2]); 6579 #endif 6580 camera->SetPosition(0, 0, 1); 6581 camera->SetFocalPoint(0, 0, 0); 6582 camera->SetViewUp(0, 1, 0); 6583 double bounds[6]; 6584 collectBounds(bounds, false); 6585 _renderer->ResetCamera(bounds); 6586 camera->GetFocalPoint(_cameraFocalPoint); 6587 trans->Translate(+_cameraFocalPoint[0], +_cameraFocalPoint[1], +_cameraFocalPoint[2]); 6588 trans->Concatenate(mat4); 6589 trans->Translate(-_cameraFocalPoint[0], -_cameraFocalPoint[1], -_cameraFocalPoint[2]); 6590 camera->ApplyTransform(trans); 6591 } else { 6592 quaternionToTransposeMatrix4x4(quat, *mat4); 6593 #ifdef DEBUG 6594 vtkSmartPointer<vtkMatrix4x4> mat2 = vtkSmartPointer<vtkMatrix4x4>::New(); 6595 mat2->DeepCopy(camera->GetViewTransformMatrix()); 6596 TRACE("camera matrix:\n %g %g %g %g\n %g %g %g %g\n %g %g %g %g\n %g %g %g %g", 6597 (*mat2)[0][0], (*mat2)[0][1], (*mat2)[0][2], (*mat2)[0][3], 6598 (*mat2)[1][0], (*mat2)[1][1], (*mat2)[1][2], (*mat2)[1][3], 6599 (*mat2)[2][0], (*mat2)[2][1], (*mat2)[2][2], (*mat2)[2][3], 6600 (*mat2)[3][0], (*mat2)[3][1], (*mat2)[3][2], (*mat2)[3][3]); 6601 printCameraInfo(camera); 6602 #endif 6603 trans->Translate(0, 0, -camera->GetDistance()); 6604 trans->Concatenate(mat4); 6605 trans->Translate(0, 0, camera->GetDistance()); 6606 trans->Concatenate(camera->GetViewTransformMatrix()); 6607 setCameraFromMatrix(camera, *trans->GetMatrix()); 6608 } 6422 6609 storeCameraOrientation(); 6423 if (_cameraZoomRatio != 1.0) { 6424 double z = _cameraZoomRatio; 6425 _cameraZoomRatio = 1.0; 6426 zoomCamera(z, true); 6427 } 6428 if (_cameraPan[0] != 0.0 || _cameraPan[1] != 0.0) { 6429 double panx = _cameraPan[0]; 6430 double pany = -_cameraPan[1]; 6431 _cameraPan[0] = 0; 6432 _cameraPan[1] = 0; 6433 panCamera(panx, pany, true); 6610 if (absolute) { 6611 if (_cameraZoomRatio != 1.0) { 6612 double z = _cameraZoomRatio; 6613 _cameraZoomRatio = 1.0; 6614 zoomCamera(z, true); 6615 } 6616 if (_cameraPan[0] != 0.0 || _cameraPan[1] != 0.0) { 6617 double panx = _cameraPan[0]; 6618 double pany = -_cameraPan[1]; 6619 _cameraPan[0] = 0; 6620 _cameraPan[1] = 0; 6621 panCamera(panx, pany, true); 6622 } 6434 6623 } 6435 6624 _renderer->ResetCameraClippingRange(); … … 6521 6710 _renderer->ResetCamera(bounds); 6522 6711 _renderer->ResetCameraClippingRange(); 6523 computeScreenWorldCoords();6712 //computeScreenWorldCoords(); 6524 6713 } 6525 6714 … … 6550 6739 _renderer->ResetCameraClippingRange(); 6551 6740 storeCameraOrientation(); 6552 computeScreenWorldCoords();6741 //computeScreenWorldCoords(); 6553 6742 _needsRedraw = true; 6554 6743 } … … 7193 7382 resetAxes(); 7194 7383 _renderer->ResetCamera(bounds); 7195 computeScreenWorldCoords();7384 //computeScreenWorldCoords(); 7196 7385 break; 7197 7386 case PERSPECTIVE: … … 7199 7388 resetAxes(); 7200 7389 _renderer->ResetCamera(bounds); 7201 computeScreenWorldCoords();7390 //computeScreenWorldCoords(); 7202 7391 break; 7203 7392 default: -
trunk/packages/vizservers/vtkvis/RpVtkRenderer.h
r2335 r2349 150 150 void rotateCamera(double yaw, double pitch, double roll); 151 151 152 void setCameraOrientation(double quat[4]); 152 void setCameraOrientation(double quat[4], bool absolute = true); 153 154 void panCamera(double x, double y, bool absolute = true); 155 156 void zoomCamera(double z, bool absolute = true); 153 157 154 158 void setCameraOrientationAndPosition(double position[3], … … 159 163 double focalPoint[3], 160 164 double viewUp[3]); 161 162 void panCamera(double x, double y, bool absolute = true);163 164 void zoomCamera(double z, bool absolute = true);165 165 166 166 // Rendering an image … … 559 559 void setStreamlinesSeedToRandomPoints(const DataSetId& id, int numPoints); 560 560 561 void setStreamlinesSeedToRake(const DataSetId& id, double start[3], double end[3], int numPoints); 562 563 void setStreamlinesSeedToPolygon(const DataSetId& id, double center[3], double normal[3], 564 double radius, int numSides); 561 void setStreamlinesSeedToRake(const DataSetId& id, 562 double start[3], double end[3], 563 int numPoints); 564 565 void setStreamlinesSeedToDisk(const DataSetId& id, 566 double center[3], double normal[3], 567 double radius, double innerRadius, 568 int numPoints); 569 570 void setStreamlinesSeedToPolygon(const DataSetId& id, 571 double center[3], double normal[3], 572 double angle, double radius, 573 int numSides); 574 575 void setStreamlinesSeedToFilledPolygon(const DataSetId& id, 576 double center[3], double normal[3], 577 double angle, double radius, 578 int numSides, int numPoints); 565 579 566 580 void setStreamlinesLength(const DataSetId& id, double length); … … 627 641 628 642 void updateRanges(bool useCumulative); 643 644 void setCameraFromMatrix(vtkCamera *camera, vtkMatrix4x4 &mat); 629 645 630 646 void computeDisplayToWorld(double x, double y, double z, double worldPt[4]); -
trunk/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp
r2335 r2349 3720 3720 3721 3721 static int 3722 StreamlinesSeedDiskOp(ClientData clientData, Tcl_Interp *interp, int objc, 3723 Tcl_Obj *const *objv) 3724 { 3725 double center[3], normal[3], radius, innerRadius; 3726 int numPoints; 3727 for (int i = 0; i < 3; i++) { 3728 if (Tcl_GetDoubleFromObj(interp, objv[3+i], ¢er[i]) != TCL_OK) { 3729 return TCL_ERROR; 3730 } 3731 if (Tcl_GetDoubleFromObj(interp, objv[6+i], &normal[i]) != TCL_OK) { 3732 return TCL_ERROR; 3733 } 3734 } 3735 if (Tcl_GetDoubleFromObj(interp, objv[9], &radius) != TCL_OK) { 3736 return TCL_ERROR; 3737 } 3738 if (Tcl_GetDoubleFromObj(interp, objv[10], &innerRadius) != TCL_OK) { 3739 return TCL_ERROR; 3740 } 3741 if (Tcl_GetIntFromObj(interp, objv[11], &numPoints) != TCL_OK) { 3742 return TCL_ERROR; 3743 } 3744 if (objc == 13) { 3745 const char *name = Tcl_GetString(objv[12]); 3746 g_renderer->setStreamlinesSeedToDisk(name, center, normal, radius, innerRadius, numPoints); 3747 } else { 3748 g_renderer->setStreamlinesSeedToDisk("all", center, normal, radius, innerRadius, numPoints); 3749 } 3750 return TCL_OK; 3751 } 3752 3753 static int 3722 3754 StreamlinesSeedPolygonOp(ClientData clientData, Tcl_Interp *interp, int objc, 3723 3755 Tcl_Obj *const *objv) 3724 3756 { 3725 double center[3], normal[3], radius;3757 double center[3], normal[3], angle, radius; 3726 3758 int numSides; 3727 3759 for (int i = 0; i < 3; i++) { … … 3733 3765 } 3734 3766 } 3735 if (Tcl_GetDoubleFromObj(interp, objv[9], &radius) != TCL_OK) { 3736 return TCL_ERROR; 3737 } 3738 if (Tcl_GetIntFromObj(interp, objv[10], &numSides) != TCL_OK) { 3739 return TCL_ERROR; 3740 } 3741 if (objc == 12) { 3742 const char *name = Tcl_GetString(objv[11]); 3743 g_renderer->setStreamlinesSeedToPolygon(name, center, normal, radius, numSides); 3744 } else { 3745 g_renderer->setStreamlinesSeedToPolygon("all", center, normal, radius, numSides); 3767 if (Tcl_GetDoubleFromObj(interp, objv[9], &angle) != TCL_OK) { 3768 return TCL_ERROR; 3769 } 3770 if (Tcl_GetDoubleFromObj(interp, objv[10], &radius) != TCL_OK) { 3771 return TCL_ERROR; 3772 } 3773 if (Tcl_GetIntFromObj(interp, objv[11], &numSides) != TCL_OK) { 3774 return TCL_ERROR; 3775 } 3776 if (numSides < 3) { 3777 Tcl_AppendResult(interp, "numSides must be 3 or greater", (char*)NULL); 3778 return TCL_ERROR; 3779 } 3780 if (objc == 13) { 3781 const char *name = Tcl_GetString(objv[12]); 3782 g_renderer->setStreamlinesSeedToPolygon(name, center, normal, angle, radius, numSides); 3783 } else { 3784 g_renderer->setStreamlinesSeedToPolygon("all", center, normal, angle, radius, numSides); 3785 } 3786 return TCL_OK; 3787 } 3788 3789 static int 3790 StreamlinesSeedFilledPolygonOp(ClientData clientData, Tcl_Interp *interp, int objc, 3791 Tcl_Obj *const *objv) 3792 { 3793 double center[3], normal[3], angle, radius; 3794 int numSides, numPoints; 3795 for (int i = 0; i < 3; i++) { 3796 if (Tcl_GetDoubleFromObj(interp, objv[3+i], ¢er[i]) != TCL_OK) { 3797 return TCL_ERROR; 3798 } 3799 if (Tcl_GetDoubleFromObj(interp, objv[6+i], &normal[i]) != TCL_OK) { 3800 return TCL_ERROR; 3801 } 3802 } 3803 if (Tcl_GetDoubleFromObj(interp, objv[9], &angle) != TCL_OK) { 3804 return TCL_ERROR; 3805 } 3806 if (Tcl_GetDoubleFromObj(interp, objv[10], &radius) != TCL_OK) { 3807 return TCL_ERROR; 3808 } 3809 if (Tcl_GetIntFromObj(interp, objv[11], &numSides) != TCL_OK) { 3810 return TCL_ERROR; 3811 } 3812 if (numSides < 3) { 3813 Tcl_AppendResult(interp, "numSides must be 3 or greater", (char*)NULL); 3814 return TCL_ERROR; 3815 } 3816 if (Tcl_GetIntFromObj(interp, objv[12], &numPoints) != TCL_OK) { 3817 return TCL_ERROR; 3818 } 3819 if (objc == 14) { 3820 const char *name = Tcl_GetString(objv[13]); 3821 g_renderer->setStreamlinesSeedToFilledPolygon(name, center, normal, angle, 3822 radius, numSides, numPoints); 3823 } else { 3824 g_renderer->setStreamlinesSeedToFilledPolygon("all", center, normal, angle, 3825 radius, numSides, numPoints); 3746 3826 } 3747 3827 return TCL_OK; … … 3810 3890 static Rappture::CmdSpec streamlinesSeedOps[] = { 3811 3891 {"color", 1, StreamlinesSeedColorOp, 6, 7, "r g b ?dataSetName?"}, 3812 {"polygon", 1, StreamlinesSeedPolygonOp, 11, 12, "centerX centerY centerZ normalX normalY normalZ radius numSides ?dataSetName?"}, 3892 {"disk", 1, StreamlinesSeedDiskOp, 12, 13, "centerX centerY centerZ normalX normalY normalZ radius innerRadius numPoints ?dataSetName?"}, 3893 {"fpoly", 1, StreamlinesSeedFilledPolygonOp, 13, 14, "centerX centerY centerZ normalX normalY normalZ angle radius numSides numPoints ?dataSetName?"}, 3894 {"polygon", 1, StreamlinesSeedPolygonOp, 12, 13, "centerX centerY centerZ normalX normalY normalZ angle radius numSides ?dataSetName?"}, 3813 3895 {"rake", 3, StreamlinesSeedRakeOp, 10, 11, "startX startY startZ endX endY endZ numPoints ?dataSetName?"}, 3814 3896 {"random", 3, StreamlinesSeedRandomOp, 4, 5, "numPoints ?dataSetName?"}, … … 3884 3966 {"ribbons", 1, StreamlinesRibbonsOp, 4, 5, "width angle ?dataSetName?"}, 3885 3967 {"scale", 2, StreamlinesScaleOp, 5, 6, "sx sy sz ?dataSetName?"}, 3886 {"seed", 2, StreamlinesSeedOp, 4, 1 1, "op params... ?dataSetName?"},3968 {"seed", 2, StreamlinesSeedOp, 4, 14, "op params... ?dataSetName?"}, 3887 3969 {"tubes", 1, StreamlinesTubesOp, 4, 5, "numSides radius ?dataSetName?"}, 3888 3970 {"visible", 1, StreamlinesVisibleOp, 3, 4, "bool ?dataSetName?"} -
trunk/packages/vizservers/vtkvis/protocol.txt
r2335 r2349 55 55 Option all resets orientation/rotation as well as pan/zoom/clip range 56 56 camera rotate <yaw> <pitch> <roll> 57 Specify relative rotation in Euler angles (FIXME)57 Specify relative rotation in Euler angles 58 58 camera set <posX> <posY> <posZ> <focalPtX> <focalPtY> <focalPtZ> <viewUpX> <viewUpY> <viewUpZ> 59 59 Set camera orientation using camera position, focal point and view up … … 250 250 streamlines scale <sx> <sy> <sz> <?dataSetName?> 251 251 streamlines seed color <r> <g> <b> <?datasetName?> 252 streamlines seed polygon <centerX> <centerY> <centerZ> <normalX> <normalY> <normalZ> <radius> <numSides> <?dataSetName?> 252 streamlines seed disk <centerX> <centerY> <centerZ> <normalX> <normalY> <normalZ> <radius> <innerRadius> <numPoints> <?dataSetName?> 253 Create a disk seed area with optional hole, filled with randomly placed points 254 streamlines seed fpoly <centerX> <centerY> <centerZ> <normalX> <normalY> <normalZ> <angle> <radius> <numSides> <numPoints> <?dataSetName?> 255 Create a regular n-sided polygonal seed area filled with randomly placed points 256 streamlines seed polygon <centerX> <centerY> <centerZ> <normalX> <normalY> <normalZ> <angle> <radius> <numSides> <?dataSetName?> 257 Create seed points from vertices of a regular n-sided polygon 253 258 streamlines seed rake <startX> <startY> <startZ> <endX> <endY> <endZ> <numPoints> <?datasetName?> 254 259 streamlines seed random <numPoints> <?datasetName?>
Note: See TracChangeset
for help on using the changeset viewer.