SurfaceProjection.cpp

Go to the documentation of this file.
00001 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00002  *
00003  * VR Juggler is (C) Copyright 1998-2005 by Iowa State University
00004  *
00005  * Original Authors:
00006  *   Allen Bierbaum, Christopher Just,
00007  *   Patrick Hartling, Kevin Meinert,
00008  *   Carolina Cruz-Neira, Albert Baker
00009  *
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Library General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2 of the License, or (at your option) any later version.
00014  *
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Library General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU Library General Public
00021  * License along with this library; if not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00023  * Boston, MA 02111-1307, USA.
00024  *
00025  * -----------------------------------------------------------------
00026  * File:          $RCSfile$
00027  * Date modified: $Date: 2006-12-18 18:00:29 -0600 (Mon, 18 Dec 2006) $
00028  * Version:       $Revision: 19704 $
00029  * -----------------------------------------------------------------
00030  *
00031  *************** <auto-copyright.pl END do not edit this line> ***************/
00032 
00033 #include <vrj/vrjConfig.h>
00034 
00035 #include <iomanip>
00036 //#include <sys/types.h>
00037 #include <string>
00038 
00039 #include <gmtl/Vec.h>
00040 #include <gmtl/Matrix.h>
00041 #include <gmtl/MatrixOps.h>
00042 #include <gmtl/Generate.h>
00043 #include <gmtl/Output.h>
00044 #include <gmtl/Xforms.h>
00045 
00046 #include <jccl/Config/ConfigElement.h>
00047 #include <vrj/Kernel/Kernel.h>
00048 #include <vrj/Util/Debug.h>
00049 #include <vrj/Display/DisplayExceptions.h>
00050 #include <vrj/Display/SurfaceProjection.h>
00051 
00052 
00053 namespace vrj
00054 {
00055 
00056 void SurfaceProjection::validateCorners()
00057 {
00058    gmtl::Vec3f norm1, norm2;
00059    gmtl::Vec3f bot_side = mLRCorner-mLLCorner;
00060    gmtl::Vec3f diag = mULCorner-mLRCorner;
00061    gmtl::Vec3f right_side = mURCorner-mLRCorner;
00062    gmtl::cross(norm1, bot_side, diag);
00063    gmtl::cross(norm2, bot_side, right_side);
00064    gmtl::normalize( norm1 ); gmtl::normalize(norm2);
00065 
00066    if ( ! gmtl::isEqual(norm1, norm2, 1e-4f) )
00067    {
00068       std::ostringstream msg_stream;
00069       msg_stream << "The corners " << mLLCorner << ", " << mLRCorner << ", "
00070                  << mURCorner << ", " << mULCorner
00071                  << " do not form a valid surface";
00072       throw InvalidSurfaceException(msg_stream.str());
00073    }
00074 }
00075 
00076 // Just call the base class constructor
00077 void SurfaceProjection::config(jccl::ConfigElementPtr element)
00078 {
00079    vprASSERT( element->getID() == "surface_viewport" );
00080 
00081    Projection::config(element);        // Call base class config first
00082 }
00083 
00098 void SurfaceProjection::calcViewMatrix(const gmtl::Matrix44f& eyePos,
00099                                        const float scaleFactor)
00100 {
00101    calculateOffsets();
00102    calcViewFrustum(eyePos, scaleFactor);
00103 
00104    //Coord eye_coord(eyePos);
00105    const gmtl::Vec3f eye_pos(gmtl::makeTrans<gmtl::Vec3f>(eyePos));             // Non-xformed pos
00106 
00107    // Need to post translate to get the view matrix at the position of the eye
00108    mViewMat = m_surface_M_base * gmtl::makeTrans<gmtl::Matrix44f>( -eye_pos );
00109 }
00110 
00111 
00124 void SurfaceProjection::calcViewFrustum(const gmtl::Matrix44f& eyePos,
00125                                         const float scaleFactor)
00126 {
00127    const float near_dist = mNearDist;
00128    const float far_dist = mFarDist;
00129 
00130    // Distance measurements from eye to screen/edges
00131    // Distance to edges is from the point on the screen plane
00132    // where a normal line would go through the origin.
00133    float eye_to_screen, eye_to_right, eye_to_left, eye_to_top, eye_to_bottom;
00134 
00135    // Compute transformed eye position
00136    // - Converts eye coords into the surface's coord system
00137    // Xformed position of eyes
00138    const gmtl::Point3f eye_surface =
00139       m_surface_M_base * gmtl::makeTrans<gmtl::Point3f>(eyePos);
00140 
00141    vprDEBUG(vrjDBG_DISP_MGR, vprDBG_HEX_LVL)
00142       << "SurfaceProjection::calcviewFrustum:    Base eye:" << gmtl::makeTrans<gmtl::Point3f>(eyePos)
00143       << "  Xformed eye:" << eye_surface
00144       << std::endl << vprDEBUG_FLUSH;
00145 
00146    // Compute dist from eye to screen/edges
00147    // Take into account scale since all origin to anythings are in meters
00148    eye_to_screen = (scaleFactor * mOriginToScreen) + eye_surface[gmtl::Zelt];
00149    eye_to_right =  (scaleFactor * mOriginToRight) - eye_surface[gmtl::Xelt];
00150    eye_to_left =   (scaleFactor * mOriginToLeft) + eye_surface[gmtl::Xelt];
00151    eye_to_top =    (scaleFactor * mOriginToTop) - eye_surface[gmtl::Yelt];
00152    eye_to_bottom = (scaleFactor * mOriginToBottom) + eye_surface[gmtl::Yelt];
00153 
00154    // Distances in near plane, in near plane from origin.  (Similar to above)
00155    // Find dists on near plane using similar triangles
00156    const float near_distFront = near_dist/eye_to_screen; // constant factor
00157    const float n_eye_to_left = eye_to_left*near_distFront;
00158    const float n_eye_to_right = eye_to_right*near_distFront;
00159    const float n_eye_to_top = eye_to_top*near_distFront;
00160    const float n_eye_to_bottom = eye_to_bottom*near_distFront;
00161 
00162    // Set frustum and calulcate the matrix
00163    mFrustum.set(-n_eye_to_left, n_eye_to_right,
00164                 -n_eye_to_bottom, n_eye_to_top,
00165                 near_dist, far_dist);
00166 
00167    mFocusPlaneDist = eye_to_screen;    // Needed for drawing
00168 
00169    vprDEBUG(vrjDBG_DISP_MGR, vprDBG_HEX_LVL)
00170       << "SurfaceProjection::calcWallProjection: \n\tFrustum: " << mFrustum
00171       << std::endl << vprDEBUG_FLUSH;
00172 
00173 }
00174 
00175 std::ostream& SurfaceProjection::outStream(std::ostream& out,
00176                                         const unsigned int indentLevel)
00177 {
00178 //   const int pad_width_dot(20 - indentLevel);
00179    out.setf(std::ios::left);
00180 
00181    const std::string indent_text(indentLevel, ' ');
00182 
00183    out << indent_text << "vrj::SurfaceProjection:\n";
00184 
00185    return Projection::outStream(out, indentLevel);
00186 }
00187 
00188 void SurfaceProjection::calculateOffsets(){
00189       calculateSurfaceRotation();
00190 
00191       m_base_M_surface=mSurfaceRotation;
00192       gmtl::invert(m_surface_M_base,m_base_M_surface);
00193       
00194       calculateCornersInBaseFrame();
00195 
00196       mOriginToScreen=-mxLLCorner[gmtl::Zelt];
00197       mOriginToRight=mxLRCorner[gmtl::Xelt];
00198       mOriginToLeft=-mxLLCorner[gmtl::Xelt];
00199       mOriginToTop=mxURCorner[gmtl::Yelt];
00200       mOriginToBottom=-mxLRCorner[gmtl::Yelt];
00201 }
00202 
00203 void SurfaceProjection::calculateSurfaceRotation()
00204 {
00205    // Find the base vectors for the surface axiis (in terms of the base coord system)
00206    // With z out, x to the right, and y up
00207    gmtl::Vec3f x_base, y_base, z_base;
00208    x_base = (mLRCorner-mLLCorner);
00209    y_base = (mURCorner-mLRCorner);
00210    gmtl::cross( z_base, x_base, y_base);
00211 
00212    // They must be normalized
00213    gmtl::normalize(x_base); gmtl::normalize(y_base); gmtl::normalize(z_base);
00214 
00215    // Calculate the surfaceRotMat using law of cosines
00216    mSurfaceRotation = gmtl::makeDirCos<gmtl::Matrix44f>(x_base, y_base, z_base );
00217 }
00218 
00219 void SurfaceProjection::calculateCornersInBaseFrame()
00220 {
00221    mxLLCorner = m_surface_M_base * mLLCorner;
00222    mxLRCorner = m_surface_M_base * mLRCorner;
00223    mxURCorner = m_surface_M_base * mURCorner;
00224    mxULCorner = m_surface_M_base * mULCorner;
00225 
00226    // Verify that they are all in the same x,y plane
00227    vprDEBUG(vprDBG_ALL, vprDBG_HVERB_LVL) << std::setprecision(10)
00228                                           << mxLLCorner[gmtl::Zelt] << " "
00229                                           << mxLRCorner[gmtl::Zelt] << " "
00230                                           << mxURCorner[gmtl::Zelt] << " "
00231                                           << mxULCorner[gmtl::Zelt] << "\n"
00232                                           << vprDEBUG_FLUSH;
00233 
00234 #ifdef VJ_DEBUG
00235    // Use 1e-4f here, otherwise the floating point error can get big enough to mess this up for tracked surfaces
00236    vprASSERT(gmtl::Math::isEqual(mxLLCorner[gmtl::Zelt], mxLRCorner[gmtl::Zelt], 1e-4f) &&
00237              gmtl::Math::isEqual(mxURCorner[gmtl::Zelt], mxULCorner[gmtl::Zelt], 1e-4f) &&
00238              gmtl::Math::isEqual(mxLLCorner[gmtl::Zelt], mxULCorner[gmtl::Zelt], 1e-4f));
00239 #endif
00240 }
00241 
00242 }

Generated on Thu Jan 4 10:56:52 2007 for VR Juggler by  doxygen 1.5.1