Exemple #1
0
Exporter::Result Exporter::exportLight(NiNodeRef parent, INode *node, GenLight* light)
{
   TimeValue t = 0;
   NiLightRef niLight;
   switch (light->Type())
   {
   case OMNI_LIGHT:
      {
         if (light->GetAmbientOnly())
         {
            niLight = new NiAmbientLight();
         }
         else
         {
            NiPointLightRef pointLight = new NiPointLight();
            float atten = light->GetAtten(t, ATTEN_START);
            switch (light->GetDecayType())
            {
            case 0: pointLight->SetConstantAttenuation(1.0f); break;
            case 1: pointLight->SetLinearAttenuation( atten / 4.0f ); break;
            case 2: pointLight->SetQuadraticAttenuation( sqrt(atten / 4.0f) ); break;
            }
            niLight = StaticCast<NiLight>(pointLight);
         }
     }
      break;
   case TSPOT_LIGHT:
   case FSPOT_LIGHT:
      niLight = new NiSpotLight();
      break;
   case DIR_LIGHT:
   case TDIR_LIGHT:
      niLight = new NiDirectionalLight();
      break;
   }
   if (niLight == NULL)
      return Skip;

   niLight->SetName(node->GetName());

   Matrix3 tm = getObjectTransform(node, t, !mFlattenHierarchy);
   niLight->SetLocalTransform( TOMATRIX4(tm, false) );

   niLight->SetDimmer( light->GetIntensity(0) );
   Color3 rgbcolor = TOCOLOR3( light->GetRGBColor(0) );
   if (light->GetAmbientOnly())
   {
      niLight->SetDiffuseColor(Color3(0,0,0));
      niLight->SetSpecularColor(Color3(0,0,0));
      niLight->SetAmbientColor(rgbcolor);
   }
   else
   {
      niLight->SetDiffuseColor(rgbcolor);
      niLight->SetSpecularColor(rgbcolor);
      niLight->SetAmbientColor(Color3(0,0,0));
   }
   parent->AddChild( DynamicCast<NiAVObject>(niLight) );
   return Ok;
}
Exemple #2
0
Exporter::Result Exporter::exportMesh(NiNodeRef &ninode, INode *node, TimeValue t)
{
	ObjectState os = node->EvalWorldState(t);

	bool local = !mFlattenHierarchy;

	TriObject *tri = (TriObject *)os.obj->ConvertToType(t, Class_ID(TRIOBJ_CLASS_ID, 0));
	if (!tri)
		return Skip;

	Mesh *copymesh = NULL;
	Mesh *mesh = &tri->GetMesh();

	Matrix3 mtx(true), rtx(true);
	if (Exporter::mCollapseTransforms)
	{
		mtx = GetNodeLocalTM(node, t);
		mtx.NoTrans();
		Quat q(mtx);
		q.MakeMatrix(rtx);
		mesh = copymesh = new Mesh(*mesh);
		{
			int n = mesh->getNumVerts();
			for ( unsigned int i = 0; i < n; ++i ) {
				Point3& vert = mesh->getVert(i);
				vert = mtx * vert;
			}
			mesh->checkNormals(TRUE);
#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 6+
			MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals ();
			if (NULL != specNorms) {
				specNorms->CheckNormals();
				for ( unsigned int i = 0; i < specNorms->GetNumNormals(); ++i ) {
					Point3& norm = specNorms->Normal(i);
					norm = (rtx * norm).Normalize();
				}
			}
#endif
		}
	}
	// Note that calling setVCDisplayData will clear things like normals so we set this up first
	vector<Color4> vertColors;
	if (mVertexColors)
	{
		bool hasvc = false;
		if (mesh->mapSupport(MAP_ALPHA))
		{
			mesh->setVCDisplayData(MAP_ALPHA);         int n = mesh->getNumVertCol();
			if (n > vertColors.size())
				vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f));
			VertColor *vertCol = mesh->vertColArray;
			if (vertCol) {
				for (int i=0; i<n; ++i) {
					VertColor c = vertCol[ i ];
					float a = (c.x + c.y + c.z) / 3.0f;
					vertColors[i].a = a;
					hasvc |= (a != 1.0f);
				}
			}
		}
		if (mesh->mapSupport(0))
		{
			mesh->setVCDisplayData(0);
			VertColor *vertCol = mesh->vertColArray;
			int n = mesh->getNumVertCol();
			if (n > vertColors.size())
				vertColors.assign(n, Color4(1.0f, 1.0f, 1.0f, 1.0f));
			if (vertCol) {
				for (int i=0; i<n; ++i) {
					VertColor col = vertCol[ i ];
					vertColors[i] = Color4(col.x, col.y, col.z, vertColors[i].a);
					hasvc |= (col.x != 1.0f || col.y != 1.0f || col.z != 1.0f);
				}
			}
		}
		if (!hasvc) vertColors.clear();
	}

#if VERSION_3DSMAX <= ((5000<<16)+(15<<8)+0) // Version 5
	mesh->checkNormals(TRUE);
#else
	MeshNormalSpec *specNorms = mesh->GetSpecifiedNormals ();
	if (NULL != specNorms) {
		specNorms->CheckNormals();
		if (specNorms->GetNumNormals() == 0)
			mesh->checkNormals(TRUE);
	} else {
		mesh->checkNormals(TRUE);
	}
#endif

	Result result = Ok;

	Modifier* geomMorpherMod = GetMorpherModifier(node);
	bool noSplit = FALSE;
//	bool noSplit = (NULL != geomMorpherMod);

	while (1)
	{
		FaceGroups grps;
		if (!splitMesh(node, *mesh, grps, t, vertColors, noSplit))
		{
			result = Error;
			break;
		}
		bool exportStrips = mTriStrips && (Exporter::mNifVersionInt > VER_4_2_2_0);

		Matrix44 tm = Matrix44::IDENTITY;
		if ( mExportExtraNodes || (mExportType != NIF_WO_ANIM && isNodeKeyed(node) ) ) {
			tm = TOMATRIX4(getObjectTransform(node, t, false) * Inverse(getNodeTransform(node, t, false)));
		} else {
			Matrix33 rot; Vector3 trans;
			objectTransform(rot, trans, node, t, local);
			tm = Matrix44(trans, rot, 1.0f);
		}
		tm = TOMATRIX4(Inverse(mtx)) * tm;

		TSTR basename = node->NodeName();
		TSTR format = (!basename.isNull() && grps.size() > 1) ? "%s:%d" : "%s";

		int i=1;
		FaceGroups::iterator grp;
		for (grp=grps.begin(); grp!=grps.end(); ++grp, ++i)
		{
			string name = FormatString(format, basename.data(), i);
			NiTriBasedGeomRef shape = makeMesh(ninode, getMaterial(node, grp->first), grp->second, exportStrips);
			if (shape == NULL)
			{
				result = Error;
				break;
			}

			if (node->IsHidden())
				shape->SetVisibility(false);

			shape->SetName(name);
			shape->SetLocalTransform(tm);

			if (Exporter::mZeroTransforms) {
				shape->ApplyTransforms();
			}

			makeSkin(shape, node, grp->second, t);

			if (geomMorpherMod) {
				vector<Vector3> verts = shape->GetData()->GetVertices();
				exportGeomMorpherControl(geomMorpherMod, verts, shape->GetData()->GetVertexIndices(), shape);
				shape->GetData()->SetConsistencyFlags(CT_VOLATILE);
			}

		}

		break;
	}

	if (tri != os.obj)
		tri->DeleteMe();

	if (copymesh)
		delete copymesh;

	return result;
}
/// @todo verify that the ordering of the jacobian returned is accurate against VrepVFController.hpp
/// @return jacobian in ColumnMajor format where each row is a joint from base to tip, first 3 columns are translation component, last 3 columns are rotation component
Eigen::MatrixXf getJacobian(vrep::VrepRobotArmDriver& driver)
{

        // Initialize Variables for update
        auto jointHandles_ = driver.getJointHandles();
        int numJoints =jointHandles_.size();
        std::vector<float> ikCalculatedJointValues(numJoints,0);
        vrep::VrepRobotArmDriver::State currentArmState_;
        driver.getState(currentArmState_);
        
        /// @todo get target position, probably relative to base
        const auto& handleParams = driver.getVrepHandleParams();
        auto ikGroupHandle_ = std::get<vrep::VrepRobotArmDriver::RobotIkGroup>(handleParams);
        
        auto target = std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams);
        auto tip = std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams);
        
        // save the current tip to target transform
        Eigen::Affine3d tipToTarget =getObjectTransform( target,tip);
        
        // set the current transform to the identity so simCheckIkGroup won't fail
        // @see http://www.forum.coppeliarobotics.com/viewtopic.php?f=9&t=3967
        // for details about this issue.
        setObjectTransform( target,tip,Eigen::Affine3d::Identity());
        
        // debug:
        // std::cout << "TipToTargetTransform:\n" << tipToTarget.matrix() << "\n";
        
        /// Run inverse kinematics, but all we really want is the jacobian
        /// @todo find version that only returns jacobian
        /// @see http://www.coppeliarobotics.com/helpFiles/en/apiFunctions.htm#simCheckIkGroup
        auto ikcalcResult =
        simCheckIkGroup(ikGroupHandle_
                       ,numJoints
                       ,&jointHandles_[0]
                       ,&ikCalculatedJointValues[0]
                       ,NULL /// @todo do we need to use these options?
                       );
        /// @see http://www.coppeliarobotics.com/helpFiles/en/apiConstants.htm#ikCalculationResults
        if(ikcalcResult!=sim_ikresult_success && ikcalcResult != sim_ikresult_not_performed)
        {
            BOOST_LOG_TRIVIAL(error) << "VrepInverseKinematicsController: didn't run inverse kinematics";
            return Eigen::MatrixXf();
        }
        
        setObjectTransform( target,tip,tipToTarget);
   
        // debug verifying that get and set object transform don't corrupt underlying data
//        Eigen::Affine3d tipToTarget2 =getObjectTransform( target,tip);
//        std::cout << "\ntiptotarget\n" << tipToTarget.matrix();
//        std::cout << "\ntiptotarget2\n" << tipToTarget2.matrix();
        
        // Get the Jacobian
        int jacobianSize[2];
        float* jacobian=simGetIkGroupMatrix(ikGroupHandle_,0,jacobianSize);
        /// @todo FIX HACK jacobianSize include orientation component, should be 7x6 instead of 7x3
        
#ifdef IGNORE_ROTATION
        jacobianSize[1] = 3;
#endif
    
        
        
        // Transfer the Jacobian to cisst

        // jacobianSize[1] represents the row count of the Jacobian
        // (i.e. the number of equations or the number of joints involved
        // in the IK resolution of the given kinematic chain)
        // Joints appear from tip to base.

        // jacobianSize[0] represents the column count of the Jacobian
        // (i.e. the number of constraints, e.g. x,y,z,alpha,beta,gamma,jointDependency)

        // The Jacobian data is in RowMajor order, i.e.:
        // https://en.wikipedia.org/wiki/Row-major_order

        std::string str;
        
        // jacobianSize[1] == eigen ColMajor "rows" , jacobianSize[0] == eigen ColMajor "cols"
        
        Eigen::Map<Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> > mtestjacobian(jacobian,jacobianSize[1],jacobianSize[0]);
        Eigen::MatrixXf eigentestJacobian = mtestjacobian.rowwise().reverse().transpose();
    
        return eigentestJacobian;
}
Exemple #4
0
void Exporter::objectTransform(Matrix33 &rot, Vector3 &trans, INode *node, TimeValue t, bool local)
{
   Matrix3 tm = getObjectTransform(node, t, local);
   convertMatrix(rot, tm);
   trans.Set(tm.GetTrans().x, tm.GetTrans().y, tm.GetTrans().z);
}
Exemple #5
0
    /// check out sawConstraintController
    void updateKinematics(){
    
        jointHandles_ = VrepRobotArmDriverP_->getJointHandles();
        auto eigentestJacobian=::grl::vrep::getJacobian(*VrepRobotArmDriverP_);

        /// The row/column major order is swapped between cisst and VREP!
        this->currentKinematicsStateP_->Jacobian.SetSize(eigentestJacobian.cols(),eigentestJacobian.rows());
        Eigen::Map<Eigen::Matrix<double,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> > mckp2(this->currentKinematicsStateP_->Jacobian.Pointer(),this->currentKinematicsStateP_->Jacobian.cols(),this->currentKinematicsStateP_->Jacobian.rows());
        mckp2 = eigentestJacobian.cast<double>();
        
        
        //Eigen::Map<Eigen::Matrix<float,Eigen::Dynamic,Eigen::Dynamic,Eigen::ColMajor> > mf(eigentestJacobian,eigentestJacobian.cols(),eigentestJacobian.rows());
        //Eigen::MatrixXf eigenJacobian = mf;
        Eigen::MatrixXf eigenJacobian = eigentestJacobian;
        
        
        ///////////////////////////////////////////////////////////
        // Copy Joint Interval, the range of motion for each joint
        
        
        // lower limits
        auto & llim = std::get<vrep::VrepRobotArmDriver::JointLowerPositionLimit>(currentArmState_);
        std::vector<double> llimits(llim.begin(),llim.end());
        jointPositionLimitsVFP_->LowerLimits = vctDoubleVec(llimits.size(),&llimits[0]);
        
        // upper limits
        auto & ulim = std::get<vrep::VrepRobotArmDriver::JointUpperPositionLimit>(currentArmState_);
        std::vector<double> ulimits(ulim.begin(),ulim.end());
        jointPositionLimitsVFP_->UpperLimits = vctDoubleVec(ulimits.size(),&ulimits[0]);
        
        // current position
        auto & currentJointPos = std::get<vrep::VrepRobotArmDriver::JointPosition>(currentArmState_);
        std::vector<double> currentJointPosVec(currentJointPos.begin(),currentJointPos.end());
        vctDoubleVec vctDoubleVecCurrentJoints(currentJointPosVec.size(),&currentJointPosVec[0]);
        
        // update limits
        /// @todo does this leak memory when called every time around?
        UpdateJointPosLimitsVF(positionLimitsName,jointPositionLimitsVFP_->UpperLimits,jointPositionLimitsVFP_->LowerLimits,vctDoubleVecCurrentJoints);
        
        
        const auto& handleParams = VrepRobotArmDriverP_->getVrepHandleParams();
        Eigen::Affine3d currentEndEffectorPose =
        getObjectTransform(
                             std::get<vrep::VrepRobotArmDriver::RobotTipName>(handleParams)
                            ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
                          );
        auto  currentEigenT = currentEndEffectorPose.translation();
        auto& currentCisstT = currentKinematicsStateP_->Frame.Translation();
        currentCisstT[0] = currentEigenT(0);
        currentCisstT[1] = currentEigenT(1);
        currentCisstT[2] = currentEigenT(2);
#ifndef IGNORE_ROTATION
        Eigen::Map<Eigen::Matrix<double,3,3,Eigen::ColMajor>> ccr(currentKinematicsStateP_->Frame.Rotation().Pointer());
        ccr = currentEndEffectorPose.rotation();
#endif // IGNORE_ROTATION
        /// @todo set rotation component of current position
        
        
        Eigen::Affine3d desiredEndEffectorPose =
        getObjectTransform(
                             std::get<vrep::VrepRobotArmDriver::RobotTargetName>(handleParams)
                            ,std::get<vrep::VrepRobotArmDriver::RobotTargetBaseName>(handleParams)
                          );
        auto  desiredEigenT = desiredEndEffectorPose.translation();
        auto& desiredCisstT = desiredKinematicsStateP_->Frame.Translation();
        desiredCisstT[0] = desiredEigenT(0);
        desiredCisstT[1] = desiredEigenT(1);
        desiredCisstT[2] = desiredEigenT(2);
#ifndef IGNORE_ROTATION
        Eigen::Map<Eigen::Matrix<double,3,3,Eigen::ColMajor>> dcr(desiredKinematicsStateP_->Frame.Rotation().Pointer());
        dcr = desiredEndEffectorPose.rotation();
#endif // IGNORE_ROTATION
        /// @todo set rotation component of desired position
        
        // for debugging, the translation between the current and desired position in cartesian coordinates
        auto inputDesired_dx = desiredCisstT - currentCisstT;
        
        vct3 dx_translation, dx_rotation;
        
        // Rotation part
        vctAxAnRot3 dxRot;
        vct3 dxRotVec;
        dxRot.FromNormalized((currentKinematicsStateP_->Frame.Inverse() * desiredKinematicsStateP_->Frame).Rotation());
        dxRotVec = dxRot.Axis() * dxRot.Angle();
        dx_rotation[0] = dxRotVec[0];
        dx_rotation[1] = dxRotVec[1];
        dx_rotation[2] = dxRotVec[2];
        //dx_rotation.SetAll(0.0);
        dx_rotation = currentKinematicsStateP_->Frame.Rotation() * dx_rotation;
        
        Eigen::AngleAxis<float> tipToTarget_cisstToEigen;
        
        Eigen::Matrix3f rotmat;
        double theta = std::sqrt(dx_rotation[0]*dx_rotation[0]+dx_rotation[1]*dx_rotation[1]+dx_rotation[2]*dx_rotation[2]);
        rotmat= Eigen::AngleAxisf(theta,Eigen::Vector3f(dx_rotation[0]/theta,dx_rotation[1]/theta,dx_rotation[2]/theta));
        
//        std::cout << "\ntiptotarget     \n" << tipToTarget.matrix() << "\n";
//        std::cout << "\ntiptotargetcisst\n" << rotmat.matrix() << "\n";
        
        
        //BOOST_LOG_TRIVIAL(trace) << "\n   test         desired dx: " << inputDesired_dx << " " << dx_rotation << "\noptimizer Calculated dx: " << optimizerCalculated_dx;
        SetKinematics(*currentKinematicsStateP_);  // replaced by name of object
        // fill these out in the desiredKinematicsStateP_
        //RotationType RotationMember; // vcRot3
        //TranslationType TranslationMember; // vct3
    
        SetKinematics(*desiredKinematicsStateP_); // replaced by name of object
        // call setKinematics with the new kinematics
        // sawconstraintcontroller has kinematicsState
        // set the jacobian here
        
        //////////////////////
        /// @todo move code below here back under run_one updateKinematics() call
        
       /// @todo need to provide tick time in double seconds and get from vrep API call
       float simulationTimeStep = simGetSimulationTimeStep();
       UpdateOptimizer(simulationTimeStep);
       
       vctDoubleVec jointAngles_dt;
       auto returncode = Solve(jointAngles_dt);
       
       
       /// @todo check the return code, if it doesn't have a result, use the VREP version as a fallback and report an error.
       if(returncode != nmrConstraintOptimizer::NMR_OK) BOOST_THROW_EXCEPTION(std::runtime_error("VrepInverseKinematicsController: constrained optimization error, please investigate"));
       
       
       /// @todo: rethink where/when/how to send command for the joint angles. Return to LUA? Set Directly? Distribute via vrep send message command?
        std::string str;
       // str = "";
       for (std::size_t i=0 ; i < jointHandles_.size() ; i++)
       {
          float currentAngle;
          auto ret = simGetJointPosition(jointHandles_[i],&currentAngle);
          BOOST_VERIFY(ret!=-1);
          float futureAngle = currentAngle + jointAngles_dt[i];
          //simSetJointTargetVelocity(jointHandles_[i],jointAngles_dt[i]/simulationTimeStep);
          //simSetJointTargetPosition(jointHandles_[i],jointAngles_dt[i]);
          //simSetJointTargetPosition(jointHandles_[i],futureAngle);
          simSetJointPosition(jointHandles_[i],futureAngle);
                str+=boost::lexical_cast<std::string>(jointAngles_dt[i]);
                if (i<jointHandles_.size()-1)
                    str+=", ";
       }
        BOOST_LOG_TRIVIAL(trace) << "jointAngles_dt: "<< str;
        
        auto optimizerCalculated_dx = this->currentKinematicsStateP_->Jacobian * jointAngles_dt;
       
        BOOST_LOG_TRIVIAL(trace) << "\n            desired dx: " << inputDesired_dx << " " << dx_rotation << "\noptimizer Calculated dx: " << optimizerCalculated_dx;
    }