Ignore:
Timestamp:
Aug 12, 2011 1:05:54 PM (13 years ago)
Author:
ldelgass
Message:

Add disk and filled regular polygon streamline seed sources, allow rotating
polygon seed about its normal. Also, add implementation of relative quat
rotations of camera and add flag to control relative v. absolute.

Location:
trunk/packages/vizservers/vtkvis
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/packages/vizservers/vtkvis/RpStreamlines.cpp

    r2332 r2349  
    99#include <ctime>
    1010#include <cfloat>
     11#include <cmath>
     12
     13#include <vtkMath.h>
    1114#include <vtkActor.h>
    1215#include <vtkProperty.h>
     
    2124#include <vtkTubeFilter.h>
    2225#include <vtkRibbonFilter.h>
     26#include <vtkTransform.h>
     27#include <vtkTransformPolyDataFilter.h>
    2328
    2429#include "RpStreamlines.h"
     
    3641    _seedColor[1] = 1.0f;
    3742    _seedColor[2] = 1.0f;
     43    vtkMath::RandomSeed((int)time(NULL));
     44    srand((unsigned int)time(NULL));
    3845}
    3946
     
    9299}
    93100
     101/**
     102 * \brief Get a pseudo-random number in range [min,max]
     103 */
     104double 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 */
    94120void Streamlines::getRandomPoint(double pt[3], const double bounds[6])
    95121{
    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 */
     135void 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 */
     160void 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 */
     176void Streamlines::getRandomCellPt(double pt[3], vtkDataSet *ds)
    105177{
    106178    int numCells = (int)ds->GetNumberOfCells();
     179    // XXX: Not uniform distribution (shouldn't use mod, and assumes
     180    // all cells are equal area/volume)
    107181    int cell = rand() % numCells;
    108182    double bounds[6];
    109183    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);
    116186}
    117187
     
    164234
    165235    _streamTracer->SetInput(ds);
    166 
    167     // Set up seed source object
    168     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 
    188236    _streamTracer->SetMaximumPropagation(maxBound);
    189     _streamTracer->SetSource(seed);
    190237
    191238    if (_pdMapper == NULL) {
     
    193240        _pdMapper->SetResolveCoincidentTopologyToPolygonOffset();
    194241        _pdMapper->ScalarVisibilityOn();
    195         // _pdMapper->ScalarVisibilityOff();
    196242    }
    197243    if (_seedMapper == NULL) {
    198244        _seedMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    199245        _seedMapper->SetResolveCoincidentTopologyToPolygonOffset();
    200         _seedMapper->SetInput(seed);
    201     }
     246    }
     247
     248    // Set up seed source object
     249    setSeedToRandomPoints(200);
    202250
    203251    switch (_lineType) {
     
    262310 * \brief Use randomly distributed seed points
    263311 *
     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 *
    264316 * \param[in] numPoints Number of random seed points to generate
    265317 */
     
    272324        vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
    273325
    274         srand((unsigned int)time(NULL));
    275326        for (int i = 0; i < numPoints; i++) {
    276327            double pt[3];
    277             getRandomCellPt(_dataSet->getVtkDataSet(), pt);
     328            getRandomCellPt(pt, _dataSet->getVtkDataSet());
    278329            TRACE("Seed pt: %g %g %g", pt[0], pt[1], pt[2]);
    279330            pts->InsertNextPoint(pt);
     
    354405
    355406/**
     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 */
     415void 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/**
    356499 * \brief Use seed points from an n-sided polygon
    357500 *
    358501 * \param[in] center Center point of polygon
    359502 * \param[in] normal Normal vector to orient polygon
     503 * \param[in] angle Angle in degrees to rotate about normal
    360504 * \param[in] radius Radius of circumscribing circle
    361505 * \param[in] numSides Number of polygon sides (and points) to generate
     
    363507void Streamlines::setSeedToPolygon(double center[3],
    364508                                   double normal[3],
     509                                   double angle,
    365510                                   double radius,
    366511                                   int numSides)
     
    376521        seed->GeneratePolygonOn();
    377522
     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
    378532        TRACE("Seed points: %d", numSides);
    379533        vtkSmartPointer<vtkDataSet> oldSeed;
     
    382536        }
    383537
    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
    385554        if (oldSeed != NULL) {
    386555            oldSeed->SetPipelineInformation(NULL);
    387556        }
    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 */
     570void 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);
    390671    }
    391672}
  • trunk/packages/vizservers/vtkvis/RpStreamlines.h

    r2332 r2349  
    6464    void setSeedToRake(double start[3], double end[3], int numPoints);
    6565
     66    void setSeedToDisk(double center[3], double normal[3],
     67                       double radius, double innerRadius, int numPoints);
     68
    6669    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);
    6876
    6977    void setMaxPropagation(double length);
     
    8795    virtual void update();
    8896
     97    static double getRandomNum(double min, double max);
    8998    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);
    91107
    92108    LineType _lineType;
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.cpp

    r2335 r2349  
    54425442 * \brief Set the streamlines seed to points along a line
    54435443 */
    5444 void Renderer::setStreamlinesSeedToRake(const DataSetId& id, double start[3], double end[3], int numPoints)
     5444void Renderer::setStreamlinesSeedToRake(const DataSetId& id,
     5445                                        double start[3], double end[3],
     5446                                        int numPoints)
    54455447{
    54465448    StreamlinesHashmap::iterator itr;
     
    54675469
    54685470/**
     5471 * \brief Set the streamlines seed to points inside a disk, with optional
     5472 * hole
     5473 */
     5474void 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/**
    54695502 * \brief Set the streamlines seed to vertices of an n-sided polygon
    54705503 */
    54715504void Renderer::setStreamlinesSeedToPolygon(const DataSetId& id,
    54725505                                           double center[3], double normal[3],
    5473                                            double radius, int numSides)
     5506                                           double angle, double radius,
     5507                                           int numSides)
    54745508{
    54755509    StreamlinesHashmap::iterator itr;
     
    54895523
    54905524    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 */
     5534void 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);
    54925558    } while (doAll && ++itr != _streamlines.end());
    54935559
     
    63886454
    63896455/**
     6456 * \brief Set the VTK camera parameters based on a 4x4 view matrix
     6457 */
     6458void 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
     6490inline 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
     6524inline 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/**
    63906559 * \brief Set the orientation of the camera from a quaternion
    63916560 *
    63926561 * \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 */
     6564void Renderer::setCameraOrientation(double quat[4], bool absolute)
    63956565{
    63966566    if (_cameraMode == IMAGE)
     
    63986568    vtkSmartPointer<vtkCamera> camera = _renderer->GetActiveCamera();
    63996569    vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
    6400     double mat3[3][3];
    6401     vtkMath::QuaternionToMatrix3x3(quat, mat3);
    64026570    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    }
    64226609    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        }
    64346623    }
    64356624    _renderer->ResetCameraClippingRange();
     
    65216710        _renderer->ResetCamera(bounds);
    65226711        _renderer->ResetCameraClippingRange();
    6523         computeScreenWorldCoords();
     6712        //computeScreenWorldCoords();
    65246713    }
    65256714
     
    65506739    _renderer->ResetCameraClippingRange();
    65516740    storeCameraOrientation();
    6552     computeScreenWorldCoords();
     6741    //computeScreenWorldCoords();
    65536742    _needsRedraw = true;
    65546743}
     
    71937382        resetAxes();
    71947383        _renderer->ResetCamera(bounds);
    7195         computeScreenWorldCoords();
     7384        //computeScreenWorldCoords();
    71967385        break;
    71977386    case PERSPECTIVE:
     
    71997388        resetAxes();
    72007389        _renderer->ResetCamera(bounds);
    7201         computeScreenWorldCoords();
     7390        //computeScreenWorldCoords();
    72027391        break;
    72037392    default:
  • trunk/packages/vizservers/vtkvis/RpVtkRenderer.h

    r2335 r2349  
    150150    void rotateCamera(double yaw, double pitch, double roll);
    151151
    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);
    153157
    154158    void setCameraOrientationAndPosition(double position[3],
     
    159163                                         double focalPoint[3],
    160164                                         double viewUp[3]);
    161 
    162     void panCamera(double x, double y, bool absolute = true);
    163 
    164     void zoomCamera(double z, bool absolute = true);
    165165
    166166    // Rendering an image
     
    559559    void setStreamlinesSeedToRandomPoints(const DataSetId& id, int numPoints);
    560560
    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);
    565579
    566580    void setStreamlinesLength(const DataSetId& id, double length);
     
    627641
    628642    void updateRanges(bool useCumulative);
     643
     644    void setCameraFromMatrix(vtkCamera *camera, vtkMatrix4x4 &mat);
    629645
    630646    void computeDisplayToWorld(double x, double y, double z, double worldPt[4]);
  • trunk/packages/vizservers/vtkvis/RpVtkRendererCmd.cpp

    r2335 r2349  
    37203720
    37213721static int
     3722StreamlinesSeedDiskOp(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], &center[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
     3753static int
    37223754StreamlinesSeedPolygonOp(ClientData clientData, Tcl_Interp *interp, int objc,
    37233755                         Tcl_Obj *const *objv)
    37243756{
    3725     double center[3], normal[3], radius;
     3757    double center[3], normal[3], angle, radius;
    37263758    int numSides;
    37273759    for (int i = 0; i < 3; i++) {
     
    37333765        }
    37343766    }
    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
     3789static int
     3790StreamlinesSeedFilledPolygonOp(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], &center[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);
    37463826    }
    37473827    return TCL_OK;
     
    38103890static Rappture::CmdSpec streamlinesSeedOps[] = {
    38113891    {"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?"},
    38133895    {"rake",    3, StreamlinesSeedRakeOp, 10, 11, "startX startY startZ endX endY endZ numPoints ?dataSetName?"},
    38143896    {"random",  3, StreamlinesSeedRandomOp, 4, 5, "numPoints ?dataSetName?"},
     
    38843966    {"ribbons",   1, StreamlinesRibbonsOp, 4, 5, "width angle ?dataSetName?"},
    38853967    {"scale",     2, StreamlinesScaleOp, 5, 6, "sx sy sz ?dataSetName?"},
    3886     {"seed",      2, StreamlinesSeedOp, 4, 11, "op params... ?dataSetName?"},
     3968    {"seed",      2, StreamlinesSeedOp, 4, 14, "op params... ?dataSetName?"},
    38873969    {"tubes",     1, StreamlinesTubesOp, 4, 5, "numSides radius ?dataSetName?"},
    38883970    {"visible",   1, StreamlinesVisibleOp, 3, 4, "bool ?dataSetName?"}
  • trunk/packages/vizservers/vtkvis/protocol.txt

    r2335 r2349  
    5555       Option all resets orientation/rotation as well as pan/zoom/clip range
    5656camera rotate <yaw> <pitch> <roll>
    57        Specify relative rotation in Euler angles (FIXME)
     57       Specify relative rotation in Euler angles
    5858camera set <posX> <posY> <posZ> <focalPtX> <focalPtY> <focalPtZ> <viewUpX> <viewUpY> <viewUpZ>
    5959       Set camera orientation using camera position, focal point and view up
     
    250250streamlines scale <sx> <sy> <sz> <?dataSetName?>
    251251streamlines seed color <r> <g> <b> <?datasetName?>
    252 streamlines seed polygon <centerX> <centerY> <centerZ> <normalX> <normalY> <normalZ> <radius> <numSides> <?dataSetName?>
     252streamlines 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
     254streamlines 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
     256streamlines seed polygon <centerX> <centerY> <centerZ> <normalX> <normalY> <normalZ> <angle> <radius> <numSides> <?dataSetName?>
     257            Create seed points from vertices of a regular n-sided polygon
    253258streamlines seed rake <startX> <startY> <startZ> <endX> <endY> <endZ> <numPoints> <?datasetName?>
    254259streamlines seed random <numPoints> <?datasetName?>
Note: See TracChangeset for help on using the changeset viewer.