/* ******************************************************************************
*  Function Name : instanceCube()
*
*  Description :
*
*  Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp
*
*  Return Value : int
*
***************************************************************************** */
int VRAY_clusterThis::instanceCube(GU_Detail * inst_gdp, GU_Detail * mb_gdp)
{
#ifdef DEBUG
   std::cout << "VRAY_clusterThis::instanceCube()" << std::endl;
#endif

   GEO_Primitive * myCube;
   GEO_Point * ppt;
   UT_Matrix4 xform(1.0);
//   UT_XformOrder xformOrder(UT_XformOrder::TRS,  UT_XformOrder::XYZ);
   UT_Matrix3 rot_xform(1.0);
//   UT_Vector3 myDir = myPointAttributes.N;
   UT_Vector3 myUp = UT_Vector3(0,1,0);
   rot_xform.orient(myPointAttributes.N, myUp);
   xform = rot_xform;

   myCube = (GEO_Primitive *) inst_gdp->cube(
               myPointAttributes.myNewPos[0] - ((mySize[0] * myPointAttributes.pscale) / 2),
               myPointAttributes.myNewPos[0] + ((mySize[0] * myPointAttributes.pscale) / 2),
               myPointAttributes.myNewPos[1] - ((mySize[1] * myPointAttributes.pscale) / 2),
               myPointAttributes.myNewPos[1] + ((mySize[1] * myPointAttributes.pscale) / 2),
               myPointAttributes.myNewPos[2] - ((mySize[2] * myPointAttributes.pscale) / 2),
               myPointAttributes.myNewPos[2] + ((mySize[2] * myPointAttributes.pscale) / 2));

   for(int i=0; i < myCube->getVertexCount(); i++) {
         ppt = myCube->getVertexElement(i).getPt();
         UT_Vector4  P = ppt->getPos();
         P *= xform;
         ppt->setPos(P);
      }

   VRAY_clusterThis::setInstanceAttributes(myCube);

   if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) {

         myCube = (GEO_Primitive *) mb_gdp->cube(myPointAttributes.myMBPos[0] - ((mySize[0] * myPointAttributes.pscale) / 2),
                                                 myPointAttributes.myMBPos[0] + ((mySize[0] * myPointAttributes.pscale) / 2),
                                                 myPointAttributes.myMBPos[1] - ((mySize[1] * myPointAttributes.pscale) / 2),
                                                 myPointAttributes.myMBPos[1] + ((mySize[1] * myPointAttributes.pscale) / 2),
                                                 myPointAttributes.myMBPos[2] - ((mySize[2] * myPointAttributes.pscale) / 2),
                                                 myPointAttributes.myMBPos[2] + ((mySize[2] * myPointAttributes.pscale) / 2));

         for(int i=0; i < myCube->getVertexCount(); i++) {
               ppt = myCube->getVertexElement(i).getPt();
               UT_Vector4  P = ppt->getPos();
               P *= xform;
               ppt->setPos(P);
            }

         VRAY_clusterThis::setInstanceAttributes(myCube);
      }

   if(myCVEX_Exec)
      VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname, CLUSTER_CVEX_POINT);

   if(myCVEX_Exec_prim)
      VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM);

   return 0;
}
/* ******************************************************************************
*  Function Name : instanceFile()
*
*  Description :  Instance the geometry from a BGEO file
*
*  Input Arguments : GU_Detail *file_gdp, GU_Detail *inst_gdp, GU_Detail *mb_gdp
*
*  Return Value : int
*
***************************************************************************** */
int VRAY_clusterThis::instanceFile(GU_Detail * file_gdp, GU_Detail * inst_gdp, GU_Detail * mb_gdp)
{
#ifdef DEBUG
   std::cout << "VRAY_clusterThis::instanceFile()" << std::endl;
   cout << "VRAY_clusterThis::instanceFile() myPointAttributes.geo_fname: " << myPointAttributes.geo_fname << endl;
#endif

#define USE_POINT_FNAME 1

   GU_Detail null_gdp;
   UT_Matrix4 xform(1.0);
   UT_Matrix3 rot_xform(1.0);
//   UT_XformOrder xformOrder(UT_XformOrder::SRT,  UT_XformOrder::XYZ);

#ifdef USE_POINT_FNAME
   GU_Detail * file_geo_gdp;
   file_geo_gdp = VRAY_Procedural::allocateGeometry();
   if(!file_geo_gdp->load((const char *)myPointAttributes.geo_fname).success())
      throw VRAY_clusterThis_Exception("VRAY_clusterThis::instanceFile() Failed to load geometry file ", 1);
   GU_Detail temp_gdp(file_geo_gdp);
#else
   GU_Detail temp_gdp(file_gdp);
#endif

   UT_Vector3 myDir = myPointAttributes.N;
   UT_Vector3 myUp = UT_Vector3(0, 1, 0);

// Transform the geo to the new position
   rot_xform.orient(myDir, myUp);
   xform = rot_xform;

   xform.scale(mySize[0] * myPointAttributes.pscale, mySize[1] * myPointAttributes.pscale, mySize[2] * myPointAttributes.pscale);
//    xform.rotate(myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2], xformOrder);
   xform.translate(myPointAttributes.myNewPos[0], myPointAttributes.myNewPos[1], myPointAttributes.myNewPos[2]);
//   xform.xform(xformOrder, myPointAttributes.myNewPos[0], myPointAttributes.myNewPos[1], myPointAttributes.myNewPos[2],
//               myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2],
//               mySize[0], mySize[1], mySize[2]);

   temp_gdp.transform(xform);

//   GU_Detail theFileGDP(theFiles[myPointAttributes.lod][myPointAttributes.anim_frame]);
   addFileAttributeRefs(&temp_gdp);
   setFileAttributes(&temp_gdp);

   // Run CVEX function on this instance
   if(myCVEX_Exec)
      VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname, CLUSTER_CVEX_POINT);
   if(myCVEX_Exec_prim)
      VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM);

   inst_gdp->merge(temp_gdp);


   if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) {
#ifdef USE_POINT_FNAME
         GU_Detail temp_gdp(file_geo_gdp);
#else
         GU_Detail temp_gdp(file_gdp);
#endif

         xform.identity();
         rot_xform.identity();
         rot_xform.orient(myDir, myUp);
         xform = rot_xform;

         xform.scale(mySize[0] * myPointAttributes.pscale, mySize[1] * myPointAttributes.pscale, mySize[2] * myPointAttributes.pscale);
//        xform.rotate(myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2], xformOrder);
         xform.translate(myPointAttributes.myMBPos[0], myPointAttributes.myMBPos[1], myPointAttributes.myMBPos[2]);
         //   xform.xform(xformOrder, myPointAttributes.myMBPos[0], myPointAttributes.myMBPos[1], myPointAttributes.myMBPos[2],
         //               myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2],
         //               mySize[0], mySize[1], mySize[2]);

         // Run CVEX function on this instance
         if(myCVEX_Exec)
            VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname, CLUSTER_CVEX_POINT);
         if(myCVEX_Exec_prim)
            VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM);

         temp_gdp.transform(xform);
         mb_gdp->merge(temp_gdp);
      }


#ifdef USE_POINT_FNAME
   VRAY_Procedural::freeGeometry(file_geo_gdp);
#endif

   return 0;
}
/* ******************************************************************************
*  Function Name : instanceFile()
*
*  Description :  Instance the geometry from a BGEO file
*
*  Input Arguments : GU_Detail *file_gdp, GU_Detail *inst_gdp, GU_Detail *mb_gdp
*
*  Return Value : int
*
***************************************************************************** */
int VRAY_clusterThis::instanceFile(GU_Detail * file_gdp, GU_Detail * inst_gdp, GU_Detail * mb_gdp)
{
#ifdef DEBUG
   std::cout << "VRAY_clusterThis::instanceFile()" << std::endl;
#endif

   GU_Detail temp_gdp(file_gdp), null_gdp;
   UT_Matrix4 xform(1.0);
   UT_Matrix3 rot_xform(1.0);
//   UT_XformOrder xformOrder(UT_XformOrder::SRT,  UT_XformOrder::XYZ);

   UT_Vector3 myDir = myPointAttributes.N;
//   myDir.normalize();
   UT_Vector3 myUp = UT_Vector3(0,1,0);

// Transform the geo to the new position
   rot_xform.orient(myDir, myUp);
   xform = rot_xform;

   xform.scale(mySize[0] * myPointAttributes.pscale, mySize[1] * myPointAttributes.pscale, mySize[2] * myPointAttributes.pscale);
//    xform.rotate(myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2], xformOrder);
   xform.translate(myPointAttributes.myNewPos[0], myPointAttributes.myNewPos[1], myPointAttributes.myNewPos[2]);
//   xform.xform(xformOrder, myPointAttributes.myNewPos[0], myPointAttributes.myNewPos[1], myPointAttributes.myNewPos[2],
//               myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2],
//               mySize[0], mySize[1], mySize[2]);

   temp_gdp.transform(xform);

//   GU_Detail theFileGDP(theFiles[myPointAttributes.lod][myPointAttributes.anim_frame]);
   addFileAttributeOffsets(&temp_gdp);
   setFileAttributes(&temp_gdp);

   // Run CVEX function on this instance
   if(myCVEX_Exec)
      VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname, CLUSTER_CVEX_POINT);

   if(myCVEX_Exec_prim)
      VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM);

   inst_gdp->merge(temp_gdp);


   if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) {
         GU_Detail temp_gdp(file_gdp);

         xform.identity();
         rot_xform.identity();
         rot_xform.orient(myDir, myUp);
         xform = rot_xform;

         xform.scale(mySize[0] * myPointAttributes.pscale, mySize[1] * myPointAttributes.pscale, mySize[2] * myPointAttributes.pscale);
//        xform.rotate(myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2], xformOrder);
         xform.translate(myPointAttributes.myMBPos[0], myPointAttributes.myMBPos[1], myPointAttributes.myMBPos[2]);
         //   xform.xform(xformOrder, myPointAttributes.myMBPos[0], myPointAttributes.myMBPos[1], myPointAttributes.myMBPos[2],
         //               myPointAttributes.N[0], myPointAttributes.N[1], myPointAttributes.N[2],
         //               mySize[0], mySize[1], mySize[2]);

         // Run CVEX function on this instance
         if(myCVEX_Exec)
            VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname, CLUSTER_CVEX_POINT);

         if(myCVEX_Exec_prim)
            VRAY_clusterThis::runCVEX(&temp_gdp, &null_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM);

         temp_gdp.transform(xform);
         mb_gdp->merge(temp_gdp);

      }

   return 0;
}
/* ******************************************************************************
*  Function Name : instanceGrid()
*
*  Description :
*
*  Input Arguments : GU_Detail *inst_gdp, GU_Detail *mb_gdp
*
*  Return Value : int
*
***************************************************************************** */
int VRAY_clusterThis::instanceGrid(GU_Detail * inst_gdp, GU_Detail * mb_gdp)
{
#ifdef DEBUG
   std::cout << "VRAY_clusterThis::instanceGrid()" << std::endl;
#endif

   GEO_Primitive * myGrid;
   GU_GridParms grid_parms;
   GEO_Point * ppt;
   UT_Matrix4 xform(1.0);
//   UT_XformOrder xformOrder(UT_XformOrder::TRS,  UT_XformOrder::XYZ);
   UT_Matrix3 rot_xform(1.0);
//   UT_Vector3 myDir = myPointAttributes.N;
   UT_Vector3 myUp = UT_Vector3(0,1,0);
   rot_xform.orient(myPointAttributes.N, myUp);
   xform = rot_xform;

   grid_parms.rows = 2;
   grid_parms.cols = 2;
   grid_parms.xsize = mySize[0] * myPointAttributes.pscale;
   grid_parms.ysize = mySize[1] * myPointAttributes.pscale;
   grid_parms.xcenter = myPointAttributes.myNewPos[0];
   grid_parms.ycenter = myPointAttributes.myNewPos[1];
   grid_parms.zcenter = myPointAttributes.myNewPos[2];
   grid_parms.plane = GU_PLANE_XY;
   myGrid = inst_gdp->buildGrid(grid_parms, GU_GRID_POLY);

   for(int i=0; i < myGrid->getVertexCount(); i++) {
         ppt = myGrid->getVertexElement(i).getPt();
         UT_Vector4  P = ppt->getPos();
         P *= xform;
         ppt->setPos(P);
      }

   VRAY_clusterThis::setInstanceAttributes(myGrid);

   if(myDoMotionBlur == CLUSTER_MB_DEFORMATION) {

         grid_parms.xcenter = myPointAttributes.myMBPos[0];
         grid_parms.ycenter = myPointAttributes.myMBPos[1];
         grid_parms.zcenter = myPointAttributes.myMBPos[2];
         myGrid = mb_gdp->buildGrid(grid_parms, GU_GRID_POLY);

         for(int i=0; i < myGrid->getVertexCount(); i++) {
               ppt = myGrid->getVertexElement(i).getPt();
               UT_Vector4  P = ppt->getPos();
               P *= xform;
               ppt->setPos(P);
            }

         VRAY_clusterThis::setInstanceAttributes(myGrid);
      }

   if(myCVEX_Exec)
      VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname, CLUSTER_CVEX_POINT);

   if(myCVEX_Exec_prim)
      VRAY_clusterThis::runCVEX(inst_gdp, mb_gdp, myCVEXFname_prim, CLUSTER_CVEX_PRIM);

   return 0;
}