/***************************************************************
* Function: setCenterPos()
***************************************************************/
void CAVEGroupReference::setCenterPos(const Vec3 &center)
{
    mCenter = center;
    Matrixf transMat;
    transMat.makeTranslate(mCenter);
    mMatrixTrans->setMatrix(transMat);
}
/***************************************************************
* Function: setCenterPos()
***************************************************************/
void CAVEGroupReferencePlane::setCenterPos(const osg::Vec3 &center)
{
    /* snap 'center' vector with respect to mUnitGridSize */
    Vec3 centerRounded;
    float snapUnitX, snapUnitY, snapUnitZ;
    snapUnitX = snapUnitY = snapUnitZ = mUnitGridSize;
    if (center.x() < 0) snapUnitX = -mUnitGridSize;
    if (center.y() < 0) snapUnitY = -mUnitGridSize;
    if (center.z() < 0) snapUnitZ = -mUnitGridSize;
    int xSeg = (int)(abs((int)((center.x() + 0.5 * snapUnitX) / mUnitGridSize)));
    int ySeg = (int)(abs((int)((center.y() + 0.5 * snapUnitY) / mUnitGridSize)));
    int zSeg = (int)(abs((int)((center.z() + 0.5 * snapUnitZ) / mUnitGridSize)));
    centerRounded.x() = xSeg * snapUnitX;
    centerRounded.y() = ySeg * snapUnitY;
    centerRounded.z() = zSeg * snapUnitZ;

    /* set highlights of either XZ plane or YZ plane */
    Vec3 offset = centerRounded - mCenter;
    float offx = offset.x() * offset.x();
    float offy = offset.y() * offset.y();
    if (offx > offy) mYZPlaneGeode->setAlpha(1.0f);
    else mYZPlaneGeode->setAlpha(0.4f);
    if (offx < offy) mXZPlaneGeode->setAlpha(1.0f);
    else mXZPlaneGeode->setAlpha(0.4f);

    mCenter = centerRounded;
    Matrixf transMat;
    transMat.makeTranslate(mCenter);
    mMatrixTrans->setMatrix(transMat);
}
/***************************************************************
* Function: acceptCAVEGeodeShape()
*
* Compared with original coordinates data in 'CAVEGeodeShape', 
* generated coordinates in 'CAVEGeodeIconSurface' is eaxctly the
* the same as those appeared in 'CAVEGeodeShape'. The scaling and
* translation to 'gIconCenter' effects are impletemented by its
* acendent 'PositionAltitudeTransform' object.
* 
***************************************************************/
void CAVEGroupIconSurface::acceptCAVEGeodeShape(CAVEGeodeShape *shapeGeode, CAVEGeodeShape *shapeGeodeRef)
{
    mCAVEGeodeShapeOriginPtr = shapeGeode;

    CAVEGeometryVector &orgGeomVector = shapeGeode->getCAVEGeometryVector();
    CAVEGeometryVector &refGeomVector = shapeGeodeRef->getCAVEGeometryVector();
    int nGeoms = orgGeomVector.size();
    if (nGeoms <= 0) return;

    /* re-generate vertex coordinate list, keep normal and texcoords the same from 'CAGEGeodeShape' */
    mSurfVertexArray = new Vec3Array;
    mSurfNormalArray = new Vec3Array;
    mSurfUDirArray = new Vec3Array;
    mSurfVDirArray = new Vec3Array;
    mSurfTexcoordArray = new Vec2Array;

    Vec3Array* geodeVertexArray = shapeGeode->mVertexArray;
    Vec3Array* geodeNormalArray = shapeGeode->mNormalArray;
    Vec3Array* geodeUDirArray = shapeGeode->mUDirArray;
    Vec3Array* geodeVDirArray = shapeGeode->mVDirArray;
    Vec2Array* geodeTexcoordArray = shapeGeode->mTexcoordArray;

    Vec3 *geodeVertexDataPtr, *geodeNormalDataPtr, *geodeUDirDataPtr, *geodeVDirDataPtr;
    Vec2 *geodeTexcoordDataPtr;

    /* check the valid status of all data field from 'CAVEGeodeShape' */
    if (geodeVertexArray->getType() == Array::Vec3ArrayType)
        geodeVertexDataPtr = (Vec3*) (geodeVertexArray->getDataPointer());
    else return;

    if (geodeNormalArray->getType() == Array::Vec3ArrayType)
        geodeNormalDataPtr = (Vec3*) (geodeNormalArray->getDataPointer());
    else return;

    if (geodeUDirArray->getType() == Array::Vec3ArrayType)
        geodeUDirDataPtr = (Vec3*) (geodeUDirArray->getDataPointer());
    else return;

    if (geodeVDirArray->getType() == Array::Vec3ArrayType)
        geodeVDirDataPtr = (Vec3*) (geodeVDirArray->getDataPointer());
    else return;

    if (geodeTexcoordArray->getType() == Array::Vec2ArrayType)
        geodeTexcoordDataPtr = (Vec2*) (geodeTexcoordArray->getDataPointer());
    else return;

    /* convert vertex coordinates from CAVEGeodeShape space to CAVEGeodeIcon space */
    int nVerts = shapeGeode->mNumVertices;
    for (int i = 0; i < nVerts; i++) mSurfVertexArray->push_back(geodeVertexDataPtr[i]);

    /* preserve the same normals and texture coordinates */
    int nNormals = shapeGeode->mNumNormals;
    for (int i = 0; i < nNormals; i++)
    {
	mSurfNormalArray->push_back(geodeNormalDataPtr[i]);
	mSurfUDirArray->push_back(geodeUDirDataPtr[i]);
	mSurfVDirArray->push_back(geodeVDirDataPtr[i]);
    }

    int nTexcoords = shapeGeode->mNumTexcoords;
    for (int i = 0; i < nTexcoords; i++) mSurfTexcoordArray->push_back(geodeTexcoordDataPtr[i]);

    /* apply offset from 'gShapeCenter' to Vec3(0, 0, 0) on root level */
    Matrixf transMat;
    transMat.makeTranslate(-gShapeCenter);
    mRootTrans->setMatrix(transMat);

    /* copy CAVEGeometry objects into separate 'CAVEGeodeIconSurface' */
    for (int i = 0; i < nGeoms; i++)
    {
	CAVEGeodeIconSurface *iconSurface = new CAVEGeodeIconSurface(&mSurfVertexArray, &mSurfNormalArray,
					&mSurfTexcoordArray, &(orgGeomVector[i]), &(refGeomVector[i]));

	/* 1) take record of 'iconSurface' in mCAVEGeodeIconVector; 2) add it to 'this' group */
	mCAVEGeodeIconVector.push_back(iconSurface);
	mRootTrans->addChild(iconSurface);
    }
}