Changeset 5698 for nanovis


Ignore:
Timestamp:
Jun 15, 2015, 6:04:15 PM (4 years ago)
Author:
ldelgass
Message:

Merge camera changes from trunk

Location:
nanovis/branches/1.2
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • nanovis/branches/1.2/Camera.cpp

    r4904 r5698  
    3939Camera::Camera(int x, int y, int width, int height) :
    4040    _updir(Y_POS),
     41    _zoomRatio(1),
    4142    _position(0, 0, 2.5),
     43    _focalPoint(0, 0, 0),
     44    _mvDirty(true),
    4245    _fov(30.0),
    4346    _near(0.1),
     
    4851    _viewport[2] = width;
    4952    _viewport[3] = height;
     53    _pan[0] = 0;
     54    _pan[1] = 0;
     55}
     56
     57void
     58Camera::pan(float x, float y, bool absolute)
     59{
     60    y = -y;
     61    if (absolute) {
     62        double panAbs[2];
     63        panAbs[0] = x;
     64        panAbs[1] = y;
     65        x -= _pan[0];
     66        y -= _pan[1];
     67        _pan[0] = panAbs[0];
     68        _pan[1] = panAbs[1];
     69    } else {
     70        _pan[0] += x;
     71        _pan[1] += y;
     72    }
     73
     74    if (x != 0.0 || y != 0.0) {
     75        Vector3f worldFocalPoint;
     76        worldToWindowCoords(_focalPoint.x, _focalPoint.y, _focalPoint.z,
     77                            worldFocalPoint);
     78        float focalDepth = worldFocalPoint.z;
     79
     80        Vector3f newPickPoint, oldPickPoint, motionVector;
     81        windowToWorldCoords((x * 2. + 1.) * (float)_viewport[2] / 2.0,
     82                            (y * 2. + 1.) * (float)_viewport[3] / 2.0,
     83                            focalDepth,
     84                            newPickPoint);
     85
     86        windowToWorldCoords((float)_viewport[2] / 2.0,
     87                            (float)_viewport[3] / 2.0,
     88                            focalDepth,
     89                            oldPickPoint);
     90
     91        // Camera motion is reversed
     92        motionVector = oldPickPoint - newPickPoint;
     93
     94        _focalPoint += motionVector;
     95        _position += motionVector;
     96
     97        _mvDirty = true;
     98    }
     99}
     100
     101void
     102Camera::zoom(float z, bool absolute)
     103{
     104    if (absolute) {
     105        // Compute relative zoom
     106        float zAbs = z;
     107        z *= 1.0/_zoomRatio;
     108        _zoomRatio = zAbs;
     109    } else {
     110        _zoomRatio *= z;
     111    }
     112    float distance = getDistance() / z;
     113    Vector3f dir = getViewPlaneNormal();
     114    dir = dir.scale(distance);
     115    _position = _focalPoint + dir;
     116    _mvDirty = true;
    50117}
    51118
     
    109176    }
    110177
    111     Vector3f center(bboxMin + bboxMax);
    112     center.scale(0.5);
    113 
    114     Matrix4x4d mat, upMat;
    115     upMat = getUpDirMatrix();
    116     mat.makeTranslation(-center);
    117     mat.multiply(_rotationMatrix, mat);
    118     mat.multiply(upMat);
    119 
    120     Vector3f emin(FLT_MAX, FLT_MAX, FLT_MAX), emax(-FLT_MAX, -FLT_MAX, -FLT_MAX);
    121 
    122     // Transform bounds by camera matrix
    123     Vector4f bboxEye[8];
    124     bboxEye[0] = Vector4f(bboxMin.x, bboxMin.y, bboxMin.z, 1);
    125     bboxEye[1] = Vector4f(bboxMax.x, bboxMin.y, bboxMin.z, 1);
    126     bboxEye[2] = Vector4f(bboxMin.x, bboxMax.y, bboxMin.z, 1);
    127     bboxEye[3] = Vector4f(bboxMin.x, bboxMin.y, bboxMax.z, 1);
    128     bboxEye[4] = Vector4f(bboxMax.x, bboxMax.y, bboxMin.z, 1);
    129     bboxEye[5] = Vector4f(bboxMax.x, bboxMin.y, bboxMax.z, 1);
    130     bboxEye[6] = Vector4f(bboxMin.x, bboxMax.y, bboxMax.z, 1);
    131     bboxEye[7] = Vector4f(bboxMax.x, bboxMax.y, bboxMax.z, 1);
    132 
    133     for (int i = 0; i < 8; i++) {
    134         Vector4f eyeVert = mat.transform(bboxEye[i]);
    135         if (eyeVert.x < emin.x) emin.x = eyeVert.x;
    136         if (eyeVert.x > emax.x) emax.x = eyeVert.x;
    137         if (eyeVert.y < emin.y) emin.y = eyeVert.y;
    138         if (eyeVert.y > emax.y) emax.y = eyeVert.y;
    139         if (eyeVert.z < emin.z) emin.z = eyeVert.z;
    140         if (eyeVert.z > emax.z) emax.z = eyeVert.z;
    141     }
     178    BBox bbox(bboxMin, bboxMax);
     179    Vector3f center = bbox.getCenter();
     180    _focalPoint.set(center.x, center.y, center.z);
     181
     182    Matrix4x4d mat;
     183    mat.makeTranslation(-_focalPoint);
     184    mat.multiply(_updirMatrix, mat); // premult
     185    mat.multiply(_rotationMatrix, mat); // premult
     186
     187    bbox.transform(bbox, mat);
     188
     189    Vector3f emin = bbox.min;
     190    Vector3f emax = bbox.max;
    142191
    143192    TRACE("Eye bounds: (%g,%g,%g) - (%g,%g,%g)",
     
    156205    // Deal with vertical aspect window
    157206    double winAspect = (double)_viewport[2]/(double)_viewport[3];
    158     double sceneAspect = 1.0;;
     207    double sceneAspect = 1.0;
    159208    if (bheight > 0.0)
    160209        sceneAspect = bwidth / bheight;
     
    170219    _far = _near + bdepth;
    171220
    172     _position.set(center.x, center.y, center.z + distance);
     221    Vector3f viewPlaneNormal(0, 0, 1);
     222    mat.transpose();
     223    viewPlaneNormal = mat.transformVec(viewPlaneNormal);
     224    _position = _focalPoint + viewPlaneNormal * distance;
    173225
    174226    TRACE("win aspect: %g scene aspect: %g", winAspect, sceneAspect);
     227    TRACE("vpn: %g, %g, %g", viewPlaneNormal.x, viewPlaneNormal.y, viewPlaneNormal.z);
    175228    TRACE("c: %g,%g,%g, d: %g", center.x, center.y, center.z, distance);
    176229    TRACE("pos: %g, %g, %g", _position.x, _position.y, _position.z);
    177230    TRACE("near: %g, far: %g", _near, _far);
    178231
     232    _zoomRatio = 1.0;
     233    _pan[0] = 0;
     234    _pan[1] = 0;
     235    _mvDirty = true;
     236
    179237    initialize();
    180238    resetClippingRange(bboxMin, bboxMax);
     
    184242 * \brief Reset near and far planes based on given world space
    185243 * bounding box
     244 *
     245 * This method is based on VTK's renderer class implementation
     246 * The idea is to plug the bounding box corners into the view
     247 * plane equation to find the min and max distance of the scene
     248 * to the view plane.
    186249 */
    187250void
    188251Camera::resetClippingRange(const Vector3f& bboxMin, const Vector3f& bboxMax)
    189252{
    190     Vector3f emin(bboxMin.x, bboxMin.y, bboxMin.z), emax(bboxMax.x, bboxMax.y, bboxMax.z);
    191 
    192     Vector3f center(emin + emax);
    193     center.scale(0.5);
    194 
    195     // Compute the radius of the enclosing sphere,
    196     // which is half the bounding box diagonal
    197     Vector3f diagonal(emax - emin);
    198     double radius = diagonal.length() * 0.5;
    199 
    200     // If we have just a single point, pick a radius of 1.0
    201     radius = (radius == 0) ? 1.0 : radius;
    202 
    203     TRACE("c: %g,%g,%g, r: %g cam z: %g", center.x, center.y, center.z, radius, _position.z);
    204 
    205     _near = _position.z - radius;
    206     _far = _position.z + radius;
    207 
    208     if (_near < 0.0) {
    209         _near = 0.001;
    210     }
    211     if (_far < 0.0) {
    212         _far = 1.0;
    213     }
     253    BBox bbox(bboxMin, bboxMax);
     254
     255    // Set up view plane equation at camera position
     256    Vector3f vpn = getViewPlaneNormal();
     257    double a, b, c, d, dist;
     258    a = -vpn.x;
     259    b = -vpn.y;
     260    c = -vpn.z;
     261    d = -(a*_position.x + b*_position.y + c*_position.z);
     262
     263    // Now compute distance of bounding box corners to view plane
     264
     265    // Set starting limits
     266    _near = a * bbox.min.x + b * bbox.min.y + c * bbox.min.z + d;
     267    _far = 1e-18;
     268
     269    // Iterate over the 8 bbox corners
     270    for (int k = 0; k < 2; k++) {
     271        for (int j = 0; j < 2; j++) {
     272            for (int i = 0; i < 2; i++) {
     273                dist =
     274                    (a * ((i == 0) ? bbox.min.x : bbox.max.x)) +
     275                    (b * ((j == 0) ? bbox.min.y : bbox.max.y)) +
     276                    (c * ((k == 0) ? bbox.min.z : bbox.max.z)) + d;
     277                _near = (dist < _near) ? dist : _near;
     278                _far =  (dist > _far)  ? dist : _far;
     279            }
     280        }
     281    }
     282
     283    // Check for near plane behind the camera
     284    if (_near < 0) {
     285        _near = 0;
     286    }
     287
     288    TRACE("near: %g far: %g", _near, _far);
     289
     290    // Extend the bounds a bit
     291    _near = 0.99 * _near - (_far - _near) * 0.5;
     292    _far  = 1.01 * _far  + (_far - _near) * 0.5;
     293
     294    TRACE("after extend: near: %g far: %g", _near, _far);
     295
     296    // Ensure near is closer than far
     297    _near = (_near >= _far) ? (0.01 * _far) : _near;
     298
     299    // Limit clip range to make best use of z buffer precision
     300    if (_near < .001 * _far)
     301        _near = .001 * _far;
    214302
    215303    TRACE("Resetting camera clipping range to: near: %g, far: %g", _near, _far);
     
    239327
    240328    glMatrixMode(GL_MODELVIEW);
    241     glLoadIdentity();
    242 
    243     glTranslatef(-_position.x, -_position.y, -_position.z);
    244     glMultMatrixd((const GLdouble *)_rotationMatrix.get());
     329
     330    computeModelViewMatrix();
     331    glLoadMatrixd((const GLdouble *)_modelViewMatrix.get());
     332}
     333
     334void Camera::windowToWorldCoords(double x, double y, double z, Vector3f& objPos)
     335{
     336    Matrix4x4d proj;
     337    getProjectionMatrix(proj);
     338    GLdouble outX, outY, outZ;
     339    gluUnProject(x, y, z,
     340                 (GLdouble *)getModelViewMatrix().get(),
     341                 (GLdouble *)proj.get(),
     342                 (GLint *)_viewport,
     343                 &outX, &outY, &outZ);
     344    objPos.set(outX, outY, outZ);
     345}
     346
     347void Camera::worldToWindowCoords(double x, double y, double z, Vector3f& winPos)
     348{
     349    Matrix4x4d proj;
     350    getProjectionMatrix(proj);
     351    GLdouble outX, outY, outZ;
     352    gluProject(x, y, z,
     353               (GLdouble *)getModelViewMatrix().get(),
     354               (GLdouble *)proj.get(),
     355               (GLint *)_viewport,
     356               &outX, &outY, &outZ);
     357    winPos.set(outX, outY, outZ);
     358}
     359
     360void Camera::computeModelViewMatrix()
     361{
     362    if (_mvDirty) {
     363        _modelViewMatrix.makeTranslation(0, 0, -getDistance());
     364        _modelViewMatrix.multiply(_rotationMatrix);
     365        _modelViewMatrix.multiply(_updirMatrix);
     366        Matrix4x4d mat;
     367        mat.makeTranslation(-_focalPoint);
     368        _modelViewMatrix.multiply(mat);
     369        _mvDirty = false;
     370    }
    245371}
    246372
     
    265391    _rotationMatrix.makeRotation(rot);
    266392    _rotationMatrix.transpose();
     393    _mvDirty = true;
     394    computeModelViewMatrix();
     395
     396    Vector3f viewPlaneNormal(0, 0, 1);
     397    Matrix4x4d mat = getModelViewMatrix();
     398    mat.transpose();
     399    viewPlaneNormal = mat.transformVec(viewPlaneNormal);
     400    TRACE("vpn: %g %g %g", viewPlaneNormal.x, viewPlaneNormal.y, viewPlaneNormal.z);
     401    _position = _focalPoint + viewPlaneNormal * getDistance();
    267402
    268403    TRACE("Set rotation to quat: %g %g %g %g",
     
    281416    mat.makeRotation(0, 0, 1, deg2rad(angleZ));
    282417    _rotationMatrix.multiply(mat);
     418    _mvDirty = true;
     419    computeModelViewMatrix();
     420
     421    Vector3f viewPlaneNormal(0, 0, 1);
     422    mat = getModelViewMatrix();
     423    mat.transpose();
     424    viewPlaneNormal = mat.transformVec(viewPlaneNormal);
     425    TRACE("vpn: %g %g %g", viewPlaneNormal.x, viewPlaneNormal.y, viewPlaneNormal.z);
     426    _position = _focalPoint + viewPlaneNormal * getDistance();
    283427
    284428    TRACE("Set rotation to angles: %g %g %g",
     
    291435          _viewport[0], _viewport[1], _viewport[2], _viewport[3]);
    292436    TRACE("fov: %g near: %g far: %g", _fov, _near, _far);
    293     TRACE("pos: %g %g %g",
     437    TRACE("fp: %g, %g, %g",
     438          _focalPoint.x, _focalPoint.y, _focalPoint.z);
     439    TRACE("pos: %g, %g, %g",
    294440          _position.x, _position.y, _position.z);
    295441    TRACE("Rotation matrix: ");
    296442    _rotationMatrix.print();
    297 }
     443    TRACE("Modelview matrix: ");
     444    _modelViewMatrix.print();
     445}
  • nanovis/branches/1.2/Camera.h

    r4904 r5698  
    3636    {
    3737        setUpDirMatrix(dir);
    38     }
    39 
    40     AxisDirection getUpdir()
    41     {
    42         return _updir;
     38        _mvDirty = true;
    4339    }
    4440
     
    4642    {
    4743        _position = pos;
     44        _mvDirty = true;
    4845    }
    4946
     
    5350    }
    5451
    55     void x(float loc_x)
     52    const vrmath::Vector3f& getFocalPoint() const
    5653    {
    57         _position.x = loc_x;
     54        return _focalPoint;
    5855    }
    5956
    60     float x() const
     57    double getDistance() const
    6158    {
    62         return _position.x;
     59        return vrmath::Vector3f(_focalPoint - _position).length();
    6360    }
    6461
    65     void y(float loc_y)
     62    vrmath::Vector3f getDirectionOfProjection() const
    6663    {
    67         _position.y = loc_y;
     64        vrmath::Vector3f dir = _focalPoint - _position;
     65        dir = dir.normalize();
     66        return dir;
    6867    }
    6968
    70     float y() const
     69    vrmath::Vector3f getViewPlaneNormal() const
    7170    {
    72         return _position.y;
     71        vrmath::Vector3f dir = _position - _focalPoint;
     72        dir = dir.normalize();
     73        return dir;
    7374    }
    7475
    75     void z(float loc_z)
    76     {
    77         _position.z = loc_z;
    78     }
     76    void pan(float x, float y, bool absolute = true);
    7977
    80     float z() const
    81     {
    82         return _position.z;
    83     }
     78    void zoom(float z, bool absolute = true);
    8479
    8580    void orient(double *quat);
     
    120115    void print() const;
    121116
     117    vrmath::Matrix4x4d& getModelViewMatrix()
     118    {
     119        computeModelViewMatrix();
     120        return _modelViewMatrix;
     121    }
     122
    122123    void getProjectionMatrix(vrmath::Matrix4x4d& mat);
    123124
    124125    const vrmath::Matrix4x4d& getUpDirMatrix() const;
    125126
     127    void windowToWorldCoords(double x, double y, double z, vrmath::Vector3f& objPos);
     128
     129    void worldToWindowCoords(double x, double y, double z, vrmath::Vector3f& winPos);
     130
    126131private:
    127     void setClippingRange(float near, float far)
    128     {
    129         _near = near;
    130         _far = far;
    131     }
     132    void computeModelViewMatrix();
    132133
    133134    void setUpDirMatrix(AxisDirection dir);
     
    135136    AxisDirection _updir;
    136137
     138    double _zoomRatio;
     139    float _pan[2];
    137140    /// Position of the camera in the scene
    138141    vrmath::Vector3f _position;
     142    vrmath::Vector3f _focalPoint;
    139143
    140144    /// Model transform for z-up scene
     
    142146    /// Camera orientation
    143147    vrmath::Matrix4x4d _rotationMatrix;
     148    /// Full camera matrix
     149    bool _mvDirty;
     150    vrmath::Matrix4x4d _modelViewMatrix;
    144151
    145152    /// Field of view (vertical angle in degrees)
  • nanovis/branches/1.2/Command.cpp

    r5603 r5698  
    597597        return TCL_ERROR;
    598598    }
    599     NanoVis::rotateCamera(phi, theta, psi);
    600     return TCL_OK;
     599    //NanoVis::orientCamera(phi, theta, psi);
     600    //return TCL_OK;
     601    Tcl_AppendResult(interp, "The 'camera angle' command is deprecated, use 'camera orient'", (char*)NULL);
     602    return TCL_ERROR;
    601603}
    602604
  • nanovis/branches/1.2/nanovis.cpp

    r5588 r5698  
    103103GLuint NanoVis::_finalDepthRb = 0;
    104104
    105 // Default camera location.
    106 Vector3f def_eye(0.0f, 0.0f, 2.5f);
    107 
    108105void
    109106NanoVis::removeAllData()
     
    169166NanoVis::panCamera(float dx, float dy)
    170167{
    171     /* Move the camera and its target by equal amounts along the x and y
    172      * axes. */
    173     TRACE("pan: x=%f, y=%f", dx, dy);
    174 
    175     _camera->x(def_eye.x - dx);
    176     _camera->y(def_eye.y + dy);
    177     TRACE("set eye to %f %f", _camera->x(), _camera->y());
     168    _camera->pan(dx, dy);
    178169
    179170    collectBounds();
     
    184175NanoVis::zoomCamera(float z)
    185176{
    186     /* Move the camera and its target by equal amounts along the x and y
    187      * axes. */
    188     TRACE("zoom: z=%f", z);
    189 
    190     _camera->z(def_eye.z / z);
    191     TRACE("set camera z to %f", _camera->z());
     177    _camera->zoom(z);
    192178
    193179    collectBounds();
     
    196182
    197183void
    198 NanoVis::rotateCamera(float phi, float theta, float psi)
    199 {
    200     _camera->orient(phi, theta, psi);
     184NanoVis::orientCamera(double *quat)
     185{
     186    _camera->orient(quat);
    201187
    202188    collectBounds();
     
    205191
    206192void
    207 NanoVis::orientCamera(double *quat)
    208 {
    209     _camera->orient(quat);
     193NanoVis::setCameraPosition(Vector3f pos)
     194{
     195    _camera->setPosition(pos);
    210196
    211197    collectBounds();
     
    214200
    215201void
    216 NanoVis::setCameraPosition(Vector3f pos)
    217 {
    218     _camera->setPosition(pos);
     202NanoVis::setCameraUpdir(Camera::AxisDirection dir)
     203{
     204    _camera->setUpdir(dir);
    219205
    220206    collectBounds();
     
    223209
    224210void
    225 NanoVis::setCameraUpdir(Camera::AxisDirection dir)
    226 {
    227     _camera->setUpdir(dir);
    228 
    229     collectBounds();
    230     _camera->resetClippingRange(sceneBounds.min, sceneBounds.max);
    231 }
    232 
    233 void
    234211NanoVis::resetCamera(bool resetOrientation)
    235212{
     
    238215    collectBounds();
    239216    _camera->reset(sceneBounds.min, sceneBounds.max, resetOrientation);
    240 
    241     def_eye = _camera->getPosition();
    242217}
    243218
     
    569544    //create the camera with default setting
    570545    _camera = new Camera(0, 0, winWidth, winHeight);
    571     _camera->setPosition(def_eye);
    572546
    573547    glEnable(GL_TEXTURE_2D);
     
    10381012    _camera->initialize();
    10391013
    1040     // Rotate for updir if required
    1041     glPushMatrix();
    1042 
    1043     switch (_camera->getUpdir()) {
    1044     case Camera::X_POS:
    1045         glRotatef(90, 0, 0, 1);
    1046         glRotatef(90, 1, 0, 0);
    1047         break;
    1048     case Camera::Y_POS:
    1049         // this is the default
    1050         break;
    1051     case Camera::Z_POS:
    1052         glRotatef(-90, 1, 0, 0);
    1053         glRotatef(-90, 0, 0, 1);
    1054         break;
    1055     case Camera::X_NEG:
    1056         glRotatef(-90, 0, 0, 1);
    1057         break;
    1058     case Camera::Y_NEG:
    1059         glRotatef(180, 0, 0, 1);
    1060         glRotatef(-90, 0, 1, 0);
    1061         break;
    1062     case Camera::Z_NEG:
    1063         glRotatef(90, 1, 0, 0);
    1064         break;
    1065     }
    1066 
    10671014    // Now render things in the scene
    10681015    orientationIndicator->setPosition(sceneBounds.getCenter());
     
    10841031        itr->second->render(renderContext);
    10851032    }
    1086     glPopMatrix();
    10871033
    10881034    CHECK_FRAMEBUFFER_STATUS();
  • nanovis/branches/1.2/nanovis.h

    r5588 r5698  
    8282    static void panCamera(float dx, float dy);
    8383    static void zoomCamera(float z);
    84     static void rotateCamera(float phi, float theta, float psi);
    8584    static void orientCamera(double *quat);
    8685    static void setCameraPosition(vrmath::Vector3f pos);
Note: See TracChangeset for help on using the changeset viewer.