Example #1
0
osg::Matrixd CameraController::calcMatrixBasedOnAxis( const Vec3d& origin, const Vec3d& axisY, const Vec3d& axisZ )
{
	Matrixd matTrans;
	matTrans.makeTranslate(origin);

	Vec3d oldY = Vec3d(0, 1, 0);
	Vec3d oldZ = Vec3d(0, 0, 1);

	Vec3d newY = axisY;
	Vec3d newZ = axisZ;
	newY.normalize();
	newZ.normalize();

	Matrixd mat1;
	mat1.makeRotate(oldZ, newZ);

	oldY = oldY * mat1;

	Matrixd mat2;
	mat2.makeRotate(oldY, newY);
	
	Matrixd matFinal = mat1 * mat2 * matTrans;

	return matFinal;
}
/***************************************************************
* Function: applyEditorInfo()
***************************************************************/
void CAVEGroupEditGeodeWireframe::applyEditorInfo(CAVEGeodeShape::EditorInfo **infoPtr)
{
    /* reset root offset only when the shape is moved */
    if ((*infoPtr)->getTypeMasking() == CAVEGeodeShape::EditorInfo::MOVE)
    {
	/* apply translations on 'mAccRootMat' */
	const Vec3 offset = (*infoPtr)->getMoveOffset();

	Matrixd transMat;
	transMat.makeTranslate(offset);
	mAccRootMat = mAccRootMat * transMat;
    }
    else if ((*infoPtr)->getTypeMasking() == CAVEGeodeShape::EditorInfo::ROTATE)
    {
	/* apply rotations on 'mAccRootMat' */
	const float angle = (*infoPtr)->getRotateAngle();
	const Vec3 axis = (*infoPtr)->getRotateAxis();

	Matrixf rotateMat;
	rotateMat.makeRotate(angle, axis);
	mAccRootMat = mAccRootMat * rotateMat;
    }
    else if ((*infoPtr)->getTypeMasking() == CAVEGeodeShape::EditorInfo::SCALE)
    {
	const Vec3f scaleVect = (*infoPtr)->getScaleVect();
	const Vec3f scaleCenter = (*infoPtr)->getScaleCenter();

	Matrixd scalingMat, transMat, revTransMat;
	scalingMat.makeScale(scaleVect);
	transMat.makeTranslate(scaleCenter);
	revTransMat.makeTranslate(-scaleCenter);

	mAccRootMat = mAccRootMat * scalingMat;
    }
}
Example #3
0
void CameraController::testSetCameraAtMatrix(const Matrixd& atToWorldMatrix, double distFromEyeToAt,
											 Vec3d& resEye, Vec3d& resAt, Vec3d& resBase)
{
	_testAtToWorldMatrix = atToWorldMatrix;

	Vec3d v1 = Vec3d(0, 0, distFromEyeToAt);
	Vec3d v2 = Vec3d(0, 0, 0);

	v1 = v1 * atToWorldMatrix;
	v2 = v2 * atToWorldMatrix;

	Matrixd trans;
	trans.makeTranslate(v1-v2);
	_testEyeToWorldMatrix = _testAtToWorldMatrix * trans;

	Matrixd upMatrix = _testEyeToWorldMatrix;
	upMatrix.setTrans(Vec3d(0, 0, 0));

	_testEye = v1;
	_testAt = v2;
	_testUp = _initUp * upMatrix;
	_testBase = _currBase;
	
	updateBaseToWorldMatrix();
}
Example #4
0
 void Camera::pushMatrix(const osg::Matrixd &mat)
 {
     const Matrixd m = mat * qMatrix.back();
     glLoadMatrixd(m.ptr());
     CHECK_GL();
     qMatrix.push_back(m);
 }
Example #5
0
void MyServerThread::sendMatrix(Matrixd transNode)
{
  float matrix1[16];
   
  Vec3 objTrans = transNode.getTrans();
  Quat objQuad = transNode.getRotate();
  
  //cout << "  Orientation  " << objQuad.x() << "," << objQuad.y() << "," << objQuad.z() << "," << objQuad.w() << endl; // orientation
  //cout << "  Postion  " << objTrans.x() << "," << objTrans.y() << "," << objTrans.z() << endl; // position
  
/*for (int i=0; i<4; ++i){
    for (int j=0; j<4; ++j)
       {
        cout << transNode(i,j) << "   " ; // position
       }
  cout << endl;
} */

cout << endl;

  for (int i=0; i<4; ++i)
    for (int j=0; j<4; ++j)
        matrix[i*4+j] = transNode(i,j);
        
 for(int i=0; i<16; i++)
        {
         cout <<"matrix:" << i << "   " << matrix1[i] << endl;
        }

  //memcpy(buf,matrix1,sizeof(float)*16);
  //sendMSG();
}
Example #6
0
void CameraController::updateEyeAndAtToWorldMatrix()
{
	_testEyeToWorldMatrix = calcMatrixBasedOnAxis(_testEye, _testUp, _testEye - _testAt);
	
	Matrixd mat;
	mat.makeTranslate(_testAt - _testEye);
	_testAtToWorldMatrix = _testEyeToWorldMatrix * mat;
}
void CAVEGeodeIconToolkitManipulate::setMatrixTrans(MatrixTransform *matTrans)
{
    Matrixd offsetMat;
    offsetMat.makeTranslate(Vec3(mScalingDir.x() * mBoundingVect.x(), 
				 mScalingDir.y() * mBoundingVect.y(), 
				 mScalingDir.z() * mBoundingVect.z()));
    matTrans->setMatrix(offsetMat);
}
void SceneGraphManipulator::setInteractionMode(int mode, Vec3f center, float imageZoom)
{ 
    if (_trackerMode == -1) _trackerMode = 0; // if ProjectionType is UNKNOWN treat it as VISION
    else _trackerMode = mode;
    Matrixd viewMat = getMatrix();
    float C = 1.5;
    _panRating = C * (viewMat.preMult(center)).length() / imageZoom; //(viewMat.preMult(center)).length() is the distance between the eye and the center of the viewed scene
}
Example #9
0
Vec3d CameraController::switchCoordinateSystem_point( const Vec3d& point, const Matrixd& from, const Matrixd& to )
{
	Matrixd mat;
	mat.invert(to);

	Vec3d v = point * from * mat;

	return v;
}
Example #10
0
 virtual void calcVertex64(Vector3Dd* vtx) {
   Matrixd matrix;
   matrix.translate(m_origin);
   matrix.rotate(m_direction, Vector3Dd(0.0f,0.0f,1.0f));
   matrix.scale(m_scale);
   for (size_t n = 0; n < VertexCount; ++n) {
     vtx[n] = matrix.mult(ts::gobj::Building3D::buildingVertex[n]);
   }
 }
/** Set the position of the manipulator using a 4x4 matrix.*/
void FirstPersonManipulator::setByMatrix( const Matrixd& matrix )
{
   // set variables
   _eye = matrix.getTrans();
   _rotation = matrix.getRotate();

   // fix current rotation
   if( getVerticalAxisFixed() )
      fixVerticalAxis( _eye, _rotation, true );
}
Example #12
0
Vec3d CameraController::calcUp(const Vec3d& oldSight, const Vec3d& newSight, const Vec3d& oldUp)
{
	Vec3d v1 = oldSight, v2 = newSight;
	v1.normalize();
	v2.normalize();

	Matrixd mat;
	mat.makeRotate(v1, v2);
	Vec3d newUp = oldUp * mat;

	return newUp;
}
/***************************************************************
* Function: setEquatorPos()
***************************************************************/
void DSVirtualEarth::setEquatorPos(const float &t)
{
    /* get virtual time based on longi/lati/date */
    float vtime = (mLongi + 180.f) / 15.f + 12 + (mDate - gDateOffset) * 24 + mTimeOffset;
    vtime = vtime - (int)(vtime / 24.f) * 24.f;

    mTimeOffset += (t - vtime);

    Matrixd rotMat;   
    rotMat.makeRotate(mTimeOffset / 12.f * M_PI, Vec3(0, 0, 1));
    mEquatorTrans->setMatrix(rotMat);
}
/***************************************************************
* Function: updateUnitGridSizeInfo()
***************************************************************/
void CAVEGroupReferenceAxis::updateUnitGridSizeInfo(const string &infoStr)
{
    if (mTextEnabledFlag)
    {
	mGridInfoText->setText("Unit size = " + infoStr);
	mGridInfoText->setPosition(Vec3(0, -gCharSize, -gCharSize));

	/* align the text to viewer's front direction */
	Matrixd rotMat;
	rotMat.makeRotate(Vec3(0, 1, 0), gPointerDir);
	mGridInfoTextTrans->setMatrix(Matrixd(rotMat)); 
    }
}
Example #15
0
Vec3d CameraController::switchCoordinateSystem_vector( const Vec3d& vec, const Matrixd& from, const Matrixd& to )
{
	Matrixd mat;
	mat.invert(to);

	Vec3d begin = Vec3d(0, 0, 0);
	Vec3d end = vec;

	Vec3d begin2 = begin * from * mat;
	Vec3d end2 = end * from * mat;

	Vec3d v = end2 - begin2;
	return v;
}
Example #16
0
/// hum. read the doc, then come back here. then try to figure.
void
dxfInsert::drawScene(scene* sc)
{
    // INSERTs can be nested. So pull the current matrix
    // and push it back after we fill our context
    // This is a snapshot in time. I will rewrite all this to be cleaner,
    // but for now, it seems working fine
    // (with the files I have, the results are equal to Voloview,
    // and better than Deep Exploration and Lightwave).

    // sanity check (useful when no block remains after all unsupported entities have been filtered out)
    if (!_block)
        return;

    Matrixd back = sc->backMatrix();
    Matrixd m;
    m.makeIdentity();
    sc->pushMatrix(m, true);
    Vec3d trans = _block->getPosition();
    sc->blockOffset(-trans);
    if (_rotation) {
        sc->pushMatrix(Matrixd::rotate(osg::DegreesToRadians(_rotation), 0,0,1));
    }
    sc->pushMatrix(Matrixd::scale(_scale.x(), _scale.y(), _scale.z()));
    sc->pushMatrix(Matrixd::translate(_point.x(), _point.y(), _point.z()));
    getOCSMatrix(_ocs, m);
    sc->pushMatrix(m);
    sc->pushMatrix(back);

    EntityList& l = _block->getEntityList();
    for (EntityList::iterator itr = l.begin(); itr != l.end(); ++itr) {
        dxfBasicEntity* e = (*itr)->getEntity();
        if (e) {
            e->drawScene(sc);
        }
    }

    sc->popMatrix(); // ocs
    sc->popMatrix(); // translate
    sc->popMatrix(); // scale
    if (_rotation) {
        sc->popMatrix(); // rotate
    }
    sc->popMatrix(); // identity
    sc->popMatrix(); // back
    sc->blockOffset(Vec3d(0,0,0));

}
void CAVEGeodeIconToolkitRotate::setMatrixTrans(osg::MatrixTransform *matTrans)
{
    Matrixd rotMat;

    if (mAxisAlignment == X_AXIS)
    {
	rotMat = Matrixd(Quat(M_PI * 0.5, Vec3(0, 1, 0)));
    }
    else if (mAxisAlignment == Y_AXIS)
    {
	rotMat = Matrixd(Quat(M_PI * 0.5, Vec3(1, 0, 0)));
    }
    else rotMat.makeIdentity();

    matTrans->setMatrix(rotMat);
}
void CAVEGeodeIconToolkitMove::setMatrixTrans(MatrixTransform *matTrans)
{
    Matrixd rotMat;

    if (mFaceOrient == FRONT_BACK)
    {
	rotMat = Matrixd(Quat(M_PI * 0.5, Vec3(1, 0, 0)));
    }
    else if (mFaceOrient == LEFT_RIGHT)
    {
	rotMat = Matrixd(Quat(M_PI * 0.5, Vec3(0, 1, 0)));
    }
    else rotMat.makeIdentity();

    matTrans->setMatrix(rotMat);
}
void SceneGraphManipulator::setByMatrix(const Matrixd& matrix)
{
    osg::Vec3d eye, center, up;
    matrix.getLookAt(eye, center, up);
    setHomePosition(eye, center, up);
    home(0.0);
}
//Constructor
DSVirtualEarth::DSVirtualEarth(): mState(SET_NULL), mLongi(-117.17f), mLati(32.75f), mTime(8.f), mDate(0.551f),
				  mTimeOffset(0.0f), mTimeLapseSpeed(0.0f)
{
    mEclipticTrans = new MatrixTransform();
    mTiltAxisTrans = new MatrixTransform();
    mEquatorTrans = new MatrixTransform();
    mEclipticSwitch = new Switch;
    mEquatorSwitch = new Switch;

    addChild(mEclipticTrans);
    mEclipticTrans->addChild(mEclipticSwitch);
    mEclipticTrans->addChild(mTiltAxisTrans);
    mTiltAxisTrans->addChild(mEquatorTrans);
    mEquatorTrans->addChild(mEquatorSwitch);

    Matrixd tiltaxisMat;
    float angle = 23.5f / 180.0f * M_PI;
    tiltaxisMat.makeRotate(Vec3(0, 0, 1), Vec3(sin(angle), 0, cos(angle)));
    mTiltAxisTrans->setMatrix(tiltaxisMat);

    /* Level 1: Seasons map and Ecliptic ruler */
    Switch *thisPtr = dynamic_cast <Switch*> (this);
    CAVEAnimationModeler::ANIMLoadVirtualEarthReferenceLevel(&thisPtr, &mSeasonsMapGeode);

    /* Level 2: Wired sphere, Meridian ruler, earth axis, equator ruler*/
    CAVEAnimationModeler::ANIMLoadVirtualEarthEclipticLevel(&mEclipticSwitch);

    /* Level 3: Wired sphere, fwd & bwd animation, pin indicator, fixed pin trans */
    CAVEAnimationModeler::ANIMLoadVirtualEarthEquatorLevel(&mEquatorSwitch, &mEarthGeode, 
	&mPATransFwd, &mPATransBwd, &mFixedPinIndicatorTrans, &mFixedPinTrans);

    /* set initial geographical info/ time / date */
    setFixedPinPos(mLongi, mLati);
    setEclipticPos(mDate);
    setEquatorPos(mTime);
    setPinIndicatorPos(mLongi);
    setAllChildrenOff();

    /* transform matrix that flip shader world plain to vertical earth model */
    mUnitspaceMat = Matrixd::inverse(Matrixd( 0,  0, -1,  0, -1,  0,  0,  0,		
			     		      0,  1,  0,  0,  0,  0,  0,  1));

    /* create instance of intersector */
    mDSIntersector = new DSIntersector();
    mTrackballController = new TrackballController();
    mVirtualScenicHandler = NULL; 
}
void SceneGraphManipulator::computeNodeCenterAndRotation(Vec3d& nodeCenter, Quat& nodeRotation) const
{
    Matrixd localToWorld;
    computeNodeLocalToWorld(localToWorld);

    if (validateNodePath())
        nodeCenter = Vec3d(_trackNodePath.back()->getBound().center())*localToWorld;
    else
        nodeCenter = Vec3d(0.0f,0.0f,0.0f)*localToWorld;

    // scale the matrix to get rid of any scales before we extract the rotation.
    double sx = 1.0/sqrt(localToWorld(0,0)*localToWorld(0,0) + localToWorld(1,0)*localToWorld(1,0) + localToWorld(2,0)*localToWorld(2,0));
    double sy = 1.0/sqrt(localToWorld(0,1)*localToWorld(0,1) + localToWorld(1,1)*localToWorld(1,1) + localToWorld(2,1)*localToWorld(2,1));
    double sz = 1.0/sqrt(localToWorld(0,2)*localToWorld(0,2) + localToWorld(1,2)*localToWorld(1,2) + localToWorld(2,2)*localToWorld(2,2));
    localToWorld = localToWorld*Matrixd::scale(sx,sy,sz);

    nodeRotation = localToWorld.getRotate();
}
/***************************************************************
* Function: updateVSParameters()
***************************************************************/
void DSVirtualEarth::updateVSParameters(const Vec3 &viewDir, const Vec3 &viewPos)
{
    if (!mVirtualScenicHandler) return;

    /*  compute sun direction in world space: apply transforms resulted by viewer's orientation change, 
	guarantee that from the viewer's position, the virtual earth is always half illuminated. */
    Matrixd baserotMat;
    baserotMat.makeRotate(Vec3(0, 1, 0), gDesignStateFrontVect);
    Vec3 sunDirWorld = (CAVEAnimationModeler::ANIMVirtualEarthLightDir()) * baserotMat;
    StateSet *stateset = mEarthGeode->getStateSet();
    if (stateset)
    {
	Uniform *lightposUniform = stateset->getOrCreateUniform("LightPos", Uniform::FLOAT_VEC4);
	lightposUniform->set(Vec4(sunDirWorld, 0.0));
    }

    /* compute matrix combination that transforms a vector from shader space into world space */
    Matrixd latiMat;
    latiMat.makeRotate(mLati / 180.f * M_PI, Vec3(0, 1, 0));
    Matrixd equatorMat;   
    equatorMat.makeRotate((mTimeOffset / 12.f + mLongi / 180.f) * M_PI, Vec3(0, 0, 1));  
    Matrixd tiltaxisMat = mTiltAxisTrans->getMatrix();
    Matrixd eclipticMat = mEclipticTrans->getMatrix();
    Matrixd transMat = mUnitspaceMat * latiMat * equatorMat * tiltaxisMat * eclipticMat * baserotMat;

    /* updata environment rendering by passing parameters to VirtualScenicHandler */
    mVirtualScenicHandler->updateVSParameters(transMat, sunDirWorld, viewDir, viewPos);
}
/***************************************************************
*  Constructor: CalibrationController()
***************************************************************/
CalibrationController::CalibrationController(Group *rootGroup, const string &datadir): mCaliFlag(false), mPlaybackFlag(false),
	mLeftRange(M_PI / 9), mRightRange(M_PI / 9), mUpwardRange(M_PI / 9), mDownwardRange(M_PI / 9), 
	mMinDepthRange(0.5), mMaxDepthRange(5), mHorFreq(1), mVerFreq(1), mDepFreq(1),
	mFieldRight(Vec3(1, 0, 0)), mFieldFront(Vec3(0, 1, 0)), mFieldUp(Vec3(0, 0, 1)), mFieldPos(Vec3(0, 0, 0))
{
    mTimer = 0.0;

    mViewerAlignmentTrans = new MatrixTransform();
    rootGroup->addChild(mViewerAlignmentTrans);

    /* apply downwards offset towards nose's position */
    mNoseOffsetTrans = new MatrixTransform();
    mViewerAlignmentTrans->addChild(mNoseOffsetTrans);
    Matrixd noseoffsetMat;
    noseoffsetMat.makeTranslate(Vec3(0, 0, gNoseOffset));
    mNoseOffsetTrans->setMatrix(noseoffsetMat);

	BallHandler::setDataDir(datadir);
    mCaliBallHandler = new CaliBallHandler(mNoseOffsetTrans);
	mPlaybackBallHandler = new PlaybackBallHandler(mNoseOffsetTrans);
    mCaliFieldHandler = new CaliFieldHandler(mNoseOffsetTrans);

    mDataDir = datadir;
}
void ArbitraryRotate(Vec3d U, Vec3d V, Vec3d W,
                     double degreeX, double degreeY,
                     Vec3d& point, Vec3d aim) {
  double cx = cos(Deg2Rad(degreeX));
  double sx = sin(Deg2Rad(degreeX));
  double cy = cos(Deg2Rad(degreeY));
  double sy = sin(Deg2Rad(degreeY));
  
  Matrixd trans = { {1, 0, 0, -aim[0]},
    {0, 1, 0, -aim[1]},
    {0, 0, 1, -aim[2]},
    {0, 0, 0, 1}};
  
  Matrixd mat = { {U[0], U[1], U[2], 0},
    {V[0], V[1], V[2], 0},
    {W[0], W[1], W[2], 0},
    {0, 0, 0, 1}};
  
  Matrixd rot(4, 4);
  Matrixd pos =  {{point[0]}, {point[1]}, {point[2]}, {1}};
  
  pos = trans * pos;
  
  pos = mat*pos;
  
  rot = {{1,   0,  0, 0},
    {0,  cx, sx, 0},
    {0, -sx, cx, 0},
    {0,   0,  0, 1}};
  
  pos = rot*pos;
  
  rot = {{ cy, 0, sy, 0},
    {0, 1,  0, 0},
    {-sy, 0, cy, 0},
    {0, 0,  0, 1}};
  
  pos = rot * pos;
  
  pos = mat.inv()*pos;
  
  pos = trans.inv()*pos;
  
  point = {pos.get(0, 0), pos.get(1, 0), pos.get(2, 0)};
}
/***************************************************************
*  Function: recordPathEntry()
*
*  Write current scale and xform matrix to file with time stamp
*
***************************************************************/
void PathRecordManager::recordPathEntry(const double &scale, const Matrixd &xMat)
{
    if (!mFilePtr) return;

    fwrite(&mTimer,sizeof(double),1,mFilePtr);

    double scaled = scale;

    fwrite(&scaled,sizeof(double),1,mFilePtr);
    fwrite(xMat.ptr(),16*sizeof(double),1,mFilePtr);
    /*fprintf(mFilePtr, "%f %f ", mTimer, scale);
    fprintf(mFilePtr, "%f %f %f %f ", xMat(0, 0), xMat(0, 1), xMat(0, 2), xMat(0, 3));
    fprintf(mFilePtr, "%f %f %f %f ", xMat(1, 0), xMat(1, 1), xMat(1, 2), xMat(1, 3));
    fprintf(mFilePtr, "%f %f %f %f ", xMat(2, 0), xMat(2, 1), xMat(2, 2), xMat(2, 3));
    fprintf(mFilePtr, "%f %f %f %f ", xMat(3, 0), xMat(3, 1), xMat(3, 2), xMat(3, 3));
    fprintf(mFilePtr, "\n");*/
}
Example #26
0
int main(int argc, char const* argv[]) {
  info(coda::version());
  info("testing matrix");
  Matrixd A(4, 4);
  A.fill(0.1);
  A.print("A:");
  A.randu();
  A.print("A:");
  info("testing matrix operations");
  A += 2;
  A.print("A+=2");
  Matrixd B;
  B = A;
  B.print("B=A");
  info("testing cwise_exp");
  Matrixd C;
  C = A + B;
  C.print("C=A+B");
  C = A % B;
  C.print("C=A%B");
  info("testing cwise_op");
  C = A + 2;
  C.print("C=A+2");
  info("testing vector");
  Vector<double> x(4);
  x.basis(2);
  x.at(0) = 10;
  x[1] = -10.0001;
  x.print("x:");
  x.randu();
  x.print("x:");
  info("testing operations");
  info("x+=2");
  x += 2;
  x.print("x+=2");
  Vector<double> y;
  y = x;
  y.print("y=x");
  y += x;
  y.print("y=+x");
  info("testing cwiseop");
  y = x + 2;
  y.print("y=x+2");
  y = abs(x);
  y.print("y=abs(x)");
  y = ramp(x);
  y.print("y=ramp(x)");
  info("testing cwiseop");
  Vector<double> z;
  x.print("x=");
  y.print("y=");
  z = x + y;
  z.print("z=x+y");
  z = x - y;
  z.print("z=x-y");
  z = 2.0 * x * (y - 1.0);
  z.print("z=2*x*(y-1)");
  z = 2.0 * (A + B) * x - C * y;
  z.print("2.0*(A+B)*x-C*y");
  z[0] = -100;
  info("norm1(z)    : %f", norm1(z));
  info("norm2(z)    : %f", norm2(z));
  info("norm_max(z) : %f", norm_max(z));
  y = A * x;
  for (uint i = 0; i < y.nelem; ++i) {
    y[i] += 1e-4 * randu<double>();
  }
  z = A * x;
  y.print("y :");
  z.print("Ax:");
  std::cout << "norm(Ax-y) = " << norm2(A * x - y) << std::endl;

  coda::warning("This is a warning");
  coda::error("This is an error");
  
  return 0;
}
/***************************************************************
* Function: updateGridUnits()
***************************************************************/
void CAVEGroupEditGeodeWireframe::updateGridUnits(const float &gridUnitLegnth, 
			const float &gridUnitAngle, const float &gridUnitScale)
{
    /* update 'Move' matrix transform wireframes */
    unsigned int numMoveChildren = mMoveSwitch->getNumChildren();
    if (numMoveChildren > 1)
    {
	Vec3 gridOffsetVect = Vec3(0, 0, 0);
	if (mMoveSVect.x() > 0) gridOffsetVect = Vec3(gridUnitLegnth, 0, 0);
	else if (mMoveSVect.x() < 0) gridOffsetVect = Vec3(-gridUnitLegnth, 0, 0);
	else if (mMoveSVect.y() > 0) gridOffsetVect = Vec3(0,  gridUnitLegnth, 0);
	else if (mMoveSVect.y() < 0) gridOffsetVect = Vec3(0, -gridUnitLegnth, 0);
	else if (mMoveSVect.z() > 0) gridOffsetVect = Vec3(0, 0,  gridUnitLegnth);
	else if (mMoveSVect.z() < 0) gridOffsetVect = Vec3(0, 0, -gridUnitLegnth);

	for (int i = 0; i < numMoveChildren; i++)
	{
	    Matrixd transMat;
	    transMat.makeTranslate(gridOffsetVect * i);
	    mMoveMatTransVector[i]->setMatrix(mBoundBoxScaleMat * mAccRootMat * transMat);
	}
	return;
    }

    /* update 'Rotate' matrix transform wireframes */
    unsigned int numRotateChildren = mRotateSwitch->getNumChildren();
    if (numRotateChildren > 1)
    {
	Vec3 gridRotationAxis = Vec3(0, 0, 1);
	if (mRotateSVect.x() > 0) gridRotationAxis = Vec3(1, 0, 0);
	else if (mRotateSVect.x() < 0) gridRotationAxis = Vec3(-1, 0, 0);
	else if (mRotateSVect.y() > 0) gridRotationAxis = Vec3(0, 1, 0);
	else if (mRotateSVect.y() < 0) gridRotationAxis = Vec3(0, -1, 0);
	else if (mRotateSVect.z() > 0) gridRotationAxis = Vec3(0, 0, 1);
	else if (mRotateSVect.z() < 0) gridRotationAxis = Vec3(0, 0, -1);

	for (int i = 0; i < numRotateChildren; i++)
	{
	    Matrixd rotMat;
	    rotMat.makeRotate(gridUnitAngle * i, gridRotationAxis);
	    mRotateMatTransVector[i]->setMatrix(mBoundSphereScaleMat * rotMat);
	}
	return;
    }

    /* update 'Scale' matrix transform wireframes */
    unsigned int numScaleChildren = mManipulateSwitch->getNumChildren();
    if (numScaleChildren > 1)
    {
	/* rewrite scaling vector */
	mScaleUnitVect.x() = mScaleUnitVect.x() > 0 ? 1:0;
	mScaleUnitVect.y() = mScaleUnitVect.y() > 0 ? 1:0;
	mScaleUnitVect.z() = mScaleUnitVect.z() > 0 ? 1:0;
	mScaleUnitVect *= gridUnitScale;

	for (int i = 0; i < numScaleChildren; i++)
	{
	    /* generate scaling vector with non-negative values */
	    Vec3 scaleVect = Vec3(1, 1, 1);
	    if (mScaleNumSegs > 0) scaleVect += mScaleUnitVect * i;
	    else scaleVect -= mScaleUnitVect * i;
	    scaleVect.x() = scaleVect.x() > 0 ? scaleVect.x() : 0;
	    scaleVect.y() = scaleVect.y() > 0 ? scaleVect.y() : 0;
	    scaleVect.z() = scaleVect.z() > 0 ? scaleVect.z() : 0;

	    Matrixd scaleMat;
	    scaleMat.makeScale(scaleVect);
	    mManipulateMatTransVector[i]->setMatrix(mBoundBoxScaleMat * mAccRootMat * scaleMat);
	}
	return;
    }
}
/***************************************************************
* Function: applyScaling()
*
* 'gridUnitScaleVect' is guranteed to be non-negative vector
*
***************************************************************/
void CAVEGroupEditGeodeWireframe::applyScaling( const short &nOffsetSegs, const Vec3 &gridUnitScaleVect, 
						const std::string &gridUnitScaleInfo)
{
    mManipulateSwitch->setAllChildrenOn();

    /* scale to other direction: clear all children of 'mManipulateSwitch' except child[0], rebuild offset tree */
    if (mScaleNumSegs * nOffsetSegs <= 0)
    {
	unsigned int numChildren = mManipulateSwitch->getNumChildren();
	if (numChildren > 1)
	{
	    mManipulateSwitch->removeChildren(1, numChildren - 1);
	    MatrixTransVector::iterator itrMatTrans = mManipulateMatTransVector.begin();
	    mManipulateMatTransVector.erase(itrMatTrans + 1, itrMatTrans + numChildren);
	}
	mScaleNumSegs = 0;
    }

    /* decide unit offset vector and start/end index of children under 'mManipulateSwitch' */
    short idxStart = 0, idxEnd = 0;
    if (nOffsetSegs != 0)
    {
	idxStart = mScaleNumSegs;
	idxEnd = nOffsetSegs;
    }
    idxStart = idxStart > 0 ? idxStart: -idxStart;
    idxEnd = idxEnd > 0 ? idxEnd : -idxEnd;

    /* update the first wireframe with global translation and rotation */
    if (idxStart == 0) mManipulateMatTransVector[0]->setMatrix(mBoundBoxScaleMat * mAccRootMat);

    /* create or remove a sequence of extra children under 'mMoveSwitch' */
    if (idxStart < idxEnd)
    {
	for (short i = idxStart + 1; i <= idxEnd; i++)
	{
	    /* generate scaling vector with non-negative values */
	    Vec3 scaleVect = Vec3(1, 1, 1);
	    if (nOffsetSegs > 0) scaleVect += gridUnitScaleVect * i;
	    else scaleVect -= gridUnitScaleVect * i;
	    scaleVect.x() = scaleVect.x() > 0 ? scaleVect.x() : 0;
	    scaleVect.y() = scaleVect.y() > 0 ? scaleVect.y() : 0;
	    scaleVect.z() = scaleVect.z() > 0 ? scaleVect.z() : 0;

	    Matrixd scaleMat;
	    scaleMat.makeScale(scaleVect);
	    MatrixTransform *scaleTrans = new MatrixTransform;
	    CAVEGeodeEditWireframeManipulate *manipulateGeode = new CAVEGeodeEditWireframeManipulate;
	    mManipulateSwitch->addChild(scaleTrans);
	    mManipulateMatTransVector.push_back(scaleTrans);
	    scaleTrans->addChild(manipulateGeode);
	    scaleTrans->setMatrix(mBoundBoxScaleMat * mAccRootMat * scaleMat);
	}
    }
    else if (idxStart > idxEnd)
    {
	mManipulateSwitch->removeChildren(idxEnd + 1, idxStart - idxEnd);
	MatrixTransVector::iterator itrMatTrans = mManipulateMatTransVector.begin();
	itrMatTrans += idxEnd + 1;
	mManipulateMatTransVector.erase(itrMatTrans, itrMatTrans + (idxStart - idxEnd));
    }

    mScaleNumSegs = nOffsetSegs;
    mScaleUnitVect = gridUnitScaleVect;

    if (!mPrimaryFlag) return;

    /* update info text if 'this' wireframe is primary */
    mEditInfoTextSwitch->setAllChildrenOn();

    float scaleUnit = gridUnitScaleVect.x() > 0 ? gridUnitScaleVect.x() : gridUnitScaleVect.y();
    scaleUnit = scaleUnit > 0 ? scaleUnit : gridUnitScaleVect.z();

    char info[128];
    float scaleval = scaleUnit * nOffsetSegs + 1.0f;
    scaleval = scaleval > 0 ? scaleval:0;
    sprintf(info, "Scale = %3.2f \nSnapping = ", scaleval);
    mEditInfoText->setText(info + gridUnitScaleInfo);
}
/***************************************************************
* Function: applyRotation()
*
* 'axisSVect': rotational snapping values around each axis,
*  for instance, Vec3(2, 0, 0) means rotation around X-axis by
*  two times of 'gridUnitAngle'
*  only one component of 'axisIntVect' is supposed to be non-zero
*
***************************************************************/
void CAVEGroupEditGeodeWireframe::applyRotation(const osg::Vec3s &axisSVect, const float &gridUnitAngle,
						const string &gridUnitAngleInfo)
{
    if (!mPrimaryFlag) return;

    mRotateSwitch->setAllChildrenOn();

    /* rotate in other direction: clear all children of 'mRotateSwitch' except child[0], rebuild offset tree */
    if ((mRotateSVect.x() * axisSVect.x() + mRotateSVect.y() * axisSVect.y() + mRotateSVect.z() * axisSVect.z()) <= 0)
    {
	unsigned int numChildren = mRotateSwitch->getNumChildren();
	if (numChildren > 1)
	{
	    mRotateSwitch->removeChildren(1, numChildren - 1);
	    MatrixTransVector::iterator itrMatTrans = mRotateMatTransVector.begin();
	    mRotateMatTransVector.erase(itrMatTrans + 1, itrMatTrans + numChildren);
	}
	mRotateSVect = Vec3s(0, 0, 0);
    }

    /* decide unit rotation quat and start/end index of children under 'mRotateSwitch' */
    Vec3 gridRotationAxis;
    short idxStart = 0, idxEnd = 0;
    if (axisSVect.x() != 0)
    {
	idxStart = mRotateSVect.x();
	idxEnd = axisSVect.x();
	if (axisSVect.x() > 0) gridRotationAxis = Vec3(1, 0, 0);
	else gridRotationAxis = Vec3(-1, 0, 0);
    }
    else if (axisSVect.y() != 0)
    {
	idxStart = mRotateSVect.y();
	idxEnd = axisSVect.y();
	if (axisSVect.y() > 0) gridRotationAxis = Vec3(0, 1, 0);
	else gridRotationAxis = Vec3(0, -1, 0);
    }
    else if (axisSVect.z() != 0)
    {
	idxStart = mRotateSVect.z();
	idxEnd = axisSVect.z();
	if (axisSVect.z() > 0) gridRotationAxis = Vec3(0, 0, 1);
	else gridRotationAxis = Vec3(0, 0, -1);
    }
    idxStart = idxStart > 0 ? idxStart: -idxStart;
    idxEnd = idxEnd > 0 ? idxEnd : -idxEnd;

    /* create or remove a sequence of extra children under 'mRotateSwitch' */
    if (idxStart < idxEnd)
    {
	for (short i = idxStart + 1; i <= idxEnd; i++)
	{
	    Matrixd rotMat;
	    rotMat.makeRotate(gridUnitAngle * i, gridRotationAxis);
	    MatrixTransform *rotateTrans = new MatrixTransform;
	    CAVEGeodeEditWireframeRotate *rotateGeode = new CAVEGeodeEditWireframeRotate;
	    mRotateSwitch->addChild(rotateTrans);
	    mRotateMatTransVector.push_back(rotateTrans);
	    rotateTrans->addChild(rotateGeode);
	    rotateTrans->setMatrix(mBoundSphereScaleMat * rotMat);
	}
    }
    else if (idxStart > idxEnd)
    {
	mRotateSwitch->removeChildren(idxEnd + 1, idxStart - idxEnd);
	MatrixTransVector::iterator itrMatTrans = mRotateMatTransVector.begin();
	itrMatTrans += idxEnd + 1;
	mRotateMatTransVector.erase(itrMatTrans, itrMatTrans + (idxStart - idxEnd));
    }

    mRotateSVect = axisSVect;

    /* update info text if 'this' wireframe is primary */
    mEditInfoTextSwitch->setAllChildrenOn();

    char info[128];
    const float gridUnitAngleDegree = gridUnitAngle * 180 / M_PI;
    sprintf(info, "Angle = %3.2f\nSnapping = ", gridUnitAngleDegree * idxEnd);
    mEditInfoText->setText(info + gridUnitAngleInfo);
}
/***************************************************************
* Function: applyTranslation()
*
* 'gridSVect': number of snapping segments along each direction
* 'gridUnitLegnth': actual length represented by each segment,
*  only one component of 'gridSVect' is supposed to be non-zero
*
***************************************************************/
void CAVEGroupEditGeodeWireframe::applyTranslation(const osg::Vec3s &gridSVect, const float &gridUnitLegnth,
							const string &gridUnitLegnthInfo)
{
    mMoveSwitch->setAllChildrenOn();

    /* move to other direction: clear all children of 'mMoveSwitch' except child[0], rebuild offset tree */
    if ((mMoveSVect.x() * gridSVect.x() + mMoveSVect.y() * gridSVect.y() + mMoveSVect.z() * gridSVect.z()) <= 0)
    {
	unsigned int numChildren = mMoveSwitch->getNumChildren();
	if (numChildren > 1)
	{
	    mMoveSwitch->removeChildren(1, numChildren - 1);
	    MatrixTransVector::iterator itrMatTrans = mMoveMatTransVector.begin();
	    mMoveMatTransVector.erase(itrMatTrans + 1, itrMatTrans + numChildren);
	}
	mMoveSVect = Vec3s(0, 0, 0);
    }

    /* decide unit offset vector and start/end index of children under 'mMoveSwitch' */
    Vec3 gridOffsetVect;
    short idxStart = 0, idxEnd = 0;
    if (gridSVect.x() != 0)
    {
	idxStart = mMoveSVect.x();
	idxEnd = gridSVect.x();
	if (gridSVect.x() > 0) gridOffsetVect = Vec3(gridUnitLegnth, 0, 0);
	else gridOffsetVect = Vec3(-gridUnitLegnth, 0, 0);
    }
    else if (gridSVect.y() != 0)
    {
	idxStart = mMoveSVect.y();
	idxEnd = gridSVect.y();
	if (gridSVect.y() > 0) gridOffsetVect = Vec3(0, gridUnitLegnth, 0);
	else gridOffsetVect = Vec3(0, -gridUnitLegnth, 0);
    }
    else if (gridSVect.z() != 0)
    {
	idxStart = mMoveSVect.z();
	idxEnd = gridSVect.z();
	if (gridSVect.z() > 0) gridOffsetVect = Vec3(0, 0, gridUnitLegnth);
	else gridOffsetVect = Vec3(0, 0, -gridUnitLegnth);
    } 
    idxStart = idxStart > 0 ? idxStart: -idxStart;
    idxEnd = idxEnd > 0 ? idxEnd : -idxEnd;

    /* update the first wireframe with global translation and rotation */
    if (idxStart == 0) mMoveMatTransVector[0]->setMatrix(mBoundBoxScaleMat * mAccRootMat);

    /* create or remove a sequence of extra children under 'mMoveSwitch' */
    if (idxStart < idxEnd)
    {
	for (short i = idxStart + 1; i <= idxEnd; i++)
	{
	    Matrixd transMat;
	    transMat.makeTranslate(gridOffsetVect * i);
	    MatrixTransform *moveTrans = new MatrixTransform;
	    CAVEGeodeEditWireframeMove *moveGeode = new CAVEGeodeEditWireframeMove;
	    mMoveSwitch->addChild(moveTrans);
	    mMoveMatTransVector.push_back(moveTrans);
	    moveTrans->addChild(moveGeode);
	    moveTrans->setMatrix(mBoundBoxScaleMat * mAccRootMat * transMat);
	}
    }
    else if (idxStart > idxEnd)
    {
	mMoveSwitch->removeChildren(idxEnd + 1, idxStart - idxEnd);
	MatrixTransVector::iterator itrMatTrans = mMoveMatTransVector.begin();
	itrMatTrans += idxEnd + 1;
	mMoveMatTransVector.erase(itrMatTrans, itrMatTrans + (idxStart - idxEnd));
    }

    mMoveSVect = gridSVect;

    if (!mPrimaryFlag) return;

    /* update info text if 'this' wireframe is primary */
    mEditInfoTextSwitch->setAllChildrenOn();

    char info[128];
    sprintf(info, "Offset = %3.2f m\nSnapping = ", gridUnitLegnth * idxEnd);
    mEditInfoText->setText(info + gridUnitLegnthInfo);
}