C++ snippet repository

Discussions concerning programming of SOFTIMAGE©
User avatar
rray
Moderator
Posts: 1532
Joined: 26 Sep 2009, 15:51
Location: Bonn, Germany

C++ snippet repository

Post by rray » 30 Jul 2012, 23:45

~o) ~o) ~o) Share your C++ code snippets here. ~o) ~o) ~o)

Some ideas what could go here:

(*) compute distance point to edge/point to plane/plane intersection
(*) get Active Project path
(*) calling a scripting command from C++
(*) compute polygon area

It doesn't have to be some perfect code. Just ctrl+c ctrl+v whatever looks somehow useful. Even if it's in the docs somewhere. Every piece might help someone, even most basic 1-liners are welcome! Just include a little description.

Note: Please do not post questions or comments in this thread.
Please only post when you're sharing a new code snippet. Thanks!


(slightly inspired by this ZBC thread :ymblushing: )

Moderator edit - enlarged the "fine print" due to its importance! - HB
Softimage Resources section (formerly known as rray.de/xsi) updated Oct 01 2017

User avatar
rray
Moderator
Posts: 1532
Joined: 26 Sep 2009, 15:51
Location: Bonn, Germany

Re: C++ snippet repository

Post by rray » 31 Jul 2012, 18:13

point-edge distance function from my old wire-d shader (uses mr libs but dot and norm functions are in the SI API also)

in_pLineO is first point
in_pLineD is vector from first to second point
out_p_l_fT is closest "ratio" on the edge (0..1)
returns "capsule" distance

Code: Select all

miScalar point_line_distance(  miVector* pP, miVector* in_pLineO, miVector* in_pLineD, miScalar* out_p_l_fT )
{
	// Return distance from the point to the line segment

	miScalar	l_fT;
	l_fT = - ( mi_vector_dot( in_pLineO, in_pLineD ) - mi_vector_dot( pP, in_pLineD ) ) / 
			mi_vector_dot( in_pLineD, in_pLineD );

	miVector	l_vPointOnLine;
	l_vPointOnLine.x = in_pLineO->x + in_pLineD->x * l_fT;
	l_vPointOnLine.y = in_pLineO->y + in_pLineD->y * l_fT;
	l_vPointOnLine.z = in_pLineO->z + in_pLineD->z * l_fT;

 	miScalar l_fLen = mi_vector_norm(in_pLineD);
	*out_p_l_fT = l_fT;
   	miScalar l_fD = (miScalar)mi_vector_dist( &l_vPointOnLine, pP );

	if( l_fT < 0.f ) 
		return (miScalar)sqrt( l_fLen * l_fT * l_fLen * l_fT + l_fD * l_fD );
	else if( l_fT > 1.f) 
		return (miScalar)sqrt( l_fLen * (l_fT - 1.0) * l_fLen * (l_fT - 1.0) + l_fD * l_fD );
	else
		return l_fD;
}
Softimage Resources section (formerly known as rray.de/xsi) updated Oct 01 2017

User avatar
origin
Posts: 619
Joined: 09 Jun 2009, 11:59
Location: warsaw

Re: C++ snippet repository

Post by origin » 01 Aug 2012, 08:40

Getting polygon location (position) under mouse cursor
in_obj - object to raycast
in_raysample - mouse screen position e.g. CVector3(200,300,0)
polyInd - polygon index to raycast
out_pos - output 3d position

performance times:
1,5 mil tri sphere: 6 ms
5 mil tri sphere: 19 ms

Code: Select all

	CStatus GetSinglePolyLocationSample3(ToolContext& in_ctxt, X3DObject& in_obj, CVector3 in_raysample, LONG polyInd, CVector3 &out_pos)
	{	
		PolygonMesh pmesh( in_obj.GetActivePrimitive().GetGeometry() );
		CTransformation localToGlobal = in_obj.GetKinematics().GetGlobal().GetTransform();
		
		PolygonFace face = pmesh.GetPolygons().GetItem( polyInd );
		CLongArray pfaceInd = face.GetNeighborPolygons().GetIndexArray();
		pfaceInd.Add(polyInd);
		
		if ( pmesh.SetupPointLocatorQueries( siClosestSurfaceRaycastIntersection,&localToGlobal, pfaceInd.GetCount(),pfaceInd.GetArray(), 10 ) != CStatus::OK)
			return CStatus::False;
		
		CVector3 l_rayview;
		
		if(	in_ctxt.WorldToView(in_raysample, l_rayview) != CStatus::OK )
			return CStatus::Fail;
			
		CLine l_ray;
		in_ctxt.GetWorldRay((LONG)l_rayview[0],(LONG)l_rayview[1],l_ray);
		CVector3	rayt = l_ray.GetTangent();
		CVector3	rayp = l_ray.GetOrigin();

		PointLocatorData	locators;
		locators = pmesh.GetRaycastIntersections( 1, (double*)&rayp, (double*)&rayt, siSemiLineIntersection  );

		if ( !locators.IsPtLocatorValid(0) )
			return CStatus::Fail;		
		if (pmesh.EvaluatePositions(locators, -1, 0, (double*)&out_pos) != CStatus::OK)
			return CStatus::Fail;	
		
		out_pos.MulByTransformationInPlace(localToGlobal);
		return CStatus::OK;
	}

Ahmidou
Posts: 105
Joined: 04 Jan 2010, 14:00

Re: C++ snippet repository

Post by Ahmidou » 15 May 2013, 04:44

A function to convert Axis/Angle to a 3x3 rotation matrix in an ICE node:

Code: Select all

void matrixFromAxisAngle(MATH::CVector3f a, float angle, MATH::CMatrix3f& m1)
{
	float m[3][3];
	double x=a.GetX();
	double y=a.GetY();
	double z=a.GetZ();
	double c = cos(angle);
	double s = sin(angle);
	double t = 1.0 - c;

	m[0][0] = c + x*x*t;
	m[1][1] = c + y*y*t;
	m[2][2] = c + z*z*t;

	double tmp1 = x*y*t;
	double tmp2 = z*s;
	m[1][0] = tmp1 + tmp2;
	m[0][1] = tmp1 - tmp2;
	tmp1 = x*z*t;
	tmp2 = y*s;
	m[2][0] = tmp1 - tmp2;
	m[0][2] = tmp1 + tmp2;
	tmp1 = y*z*t;
	tmp2 = x*s;
	m[2][1] = tmp1 + tmp2;
	m[1][2] = tmp1 - tmp2;

	m1.Set(m);
}

Ahmidou
Posts: 105
Joined: 04 Jan 2010, 14:00

Re: C++ snippet repository

Post by Ahmidou » 27 May 2013, 07:43

This is the command I'm using to undo the SetPositionArray

Code: Select all

////////////////////////////////////////////////////////////////////////////////
//
// paintDeform Undo/redo command
//
////////////////////////////////////////////////////////////////////////////////
class CStrokeUpdateTask
{
	public:
	struct Pos
	{
		CVector3Array delta;
	};

	CStrokeUpdateTask( X3DObject& in_obj, CVector3Array delta, CVector3Array prevDelta )
	{
		m_pos.delta = delta;
		m_origpos.delta = prevDelta;
		m_obj = in_obj;
	}

	void Do( )
	{
		update( m_pos.delta );
	}

	void Undo( )
	{
		update( m_origpos.delta );
	}

	void Redo( )
	{
		Do( );
	}

	private:

	void update( CVector3Array delta )
	{
		Geometry geo( m_obj.GetActivePrimitive().GetGeometry());
		geo.GetPoints().PutPositionArray(delta);
	}

	Pos m_pos;
	Pos m_origpos;
	X3DObject m_obj;
};

XSIPLUGINCALLBACK CStatus updateStroke_Init( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	Command oCmd;
	oCmd = ctxt.GetSource();
	oCmd.PutDescription(L"");
	oCmd.SetFlag(siSupportsKeyAssignment,false);
	oCmd.EnableReturnValue(true);

	ArgumentArray args = oCmd.GetArguments();

	args.Add( L"object" );
	args.Add( L"delta" );
	args.Add( L"prevDelta" );

	return CStatus::OK;
}

XSIPLUGINCALLBACK CStatus updateStroke_Execute( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	CValueArray args = ctxt.GetAttribute(L"Arguments");

	Application().LogMessage(L"updateStroke_Execute called",siVerboseMsg);


	CValueArray wrapwrapper = args[1];
	CVector3Array &pos= *((CVector3Array *)(ULLONG)wrapwrapper[0]);
	CVector3Array &prevPos= *((CVector3Array *)(ULLONG)wrapwrapper[1]);
	X3DObject obj = CRef(args[0]);

	CStrokeUpdateTask* pTask = new CStrokeUpdateTask( obj, pos, prevPos );
	pTask->Do();

	ctxt.PutAttribute( L"ReturnValue", true );

	ctxt.PutAttribute( L"UndoRedoData", (CValue::siPtrType)pTask);

	return CStatus::OK;
}

XSIPLUGINCALLBACK CStatus updateStroke_Undo( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	CStrokeUpdateTask* p = (CStrokeUpdateTask*)(CValue::siPtrType)ctxt.GetAttribute(L"UndoRedoData");
	p->Undo( );
	Application().LogMessage(L"Undo called with ID: " + CString( ctxt.GetAttribute(L"UndoRedoData") ),siVerboseMsg);
	return CStatus::OK;
}

XSIPLUGINCALLBACK CStatus updateStroke_Redo( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	CStrokeUpdateTask* p = (CStrokeUpdateTask*)(CValue::siPtrType)ctxt.GetAttribute(L"UndoRedoData");
	p->Redo( );
	Application().LogMessage(L"Redo called with ID: " + CString( ctxt.GetAttribute(L"UndoRedoData") ),siVerboseMsg);
	return CStatus::OK;
}

XSIPLUGINCALLBACK CStatus updateStroke_TermUndoRedo( CRef& in_ctxt )
{
	Context ctxt( in_ctxt );
	CStrokeUpdateTask* p = (CStrokeUpdateTask*)(CValue::siPtrType)ctxt.GetAttribute(L"UndoRedoData");
	delete p;
	Application().LogMessage(L"TermUndoRedo called with ID: " + CString( ctxt.GetAttribute(L"UndoRedoData") ),siVerboseMsg);
	return CStatus::OK;
}
then I'm calling the command this way

Code: Select all

CValue outArg;
CValueArray inArgs;
inArgs.Add((CValue)m_sel);
CValueArray wrapwrapper;
wrapwrapper.Add( (ULLONG)&posArray );
wrapwrapper.Add( (ULLONG)&initPosArray );
inArgs.Add( wrapwrapper );
CStatus st = app.ExecuteCommand( L"updateStroke",inArgs, outArg );
if( st != CStatus::OK ) {
	app.LogMessage( L"exec failed. " + st.GetDescription() );
}