We are pleased to announce that the si-community board has been upgraded to phpBB version 3.2.1! Let us know what you think , report bugs , and find out what has been improved in this thread
Click the "X" in the upper right corner to close this announcement

C++ custom tool SDK programming tip

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

C++ custom tool SDK programming tip

Post by rray » 26 Jul 2011, 12:14

Here's a tip how to get the actual component object (edge, point, polygon) from a custom tool snap/pick operation.

This is useful for example in case you want to highlight an edge.

The component arrives as the first and only element of the Component Collection of the SubComponent property of a CollectionItem. Phew ,).... The C++ API doesn't provide access to either of those elements, so you'll have to go through the CComAPIHander again (similar to handling component selections)

So basically to get the component, you will have to do:

Code: Select all

CRef ref = in_ctxt.GetSnapComponent(); 
if(!ref.IsValid())
	break;
										
CComAPIHandler cCollItem(ref);
CComAPIHandler cSubComp(cCollItem.GetProperty(L"SubComponent"));
CComAPIHandler cCompColl(cSubComp.GetProperty(L"ComponentCollection"));
if(LONG(cCompColl.GetProperty(L"Count")) != 1L)
	break;

CValue rVal;
CValueArray rrParams;
rrParams.Add(0L);
CStatus bOk = cCompColl.Invoke(L"Item", CComAPIHandler::PropertyGet, rVal, rrParams);
CRef edgeRef(rVal);
Edge theEdge(edgeRef);
[/size]

Code: Select all

Edge theEdge(in_ctxt.GetSnapComponent());
[/size]
would have been easier.... but it works ;)

Note that snap works on the unsubdivided mesh of a subd surface, and pick works on the subdivided mesh (uses a hidden pick bitmap)

Hope this helps somebody get started with custom tool programming.
Last edited by rray on 26 Jul 2011, 18:59, edited 1 time in total.
Reason: some added info....

User avatar
Memag
Posts: 339
Joined: 09 Aug 2010, 01:37
Location: Tits

Re: C++ custom tool programming tip

Post by Memag » 26 Jul 2011, 13:45

Thank you rray.
The old "XSI user normals" SDK example/tool has hover highlight and select functionality.
I wonder if it's possible to "chop ++" the actual normal display and rotation tweaking code, and leave it as multi-component selection tool with highlighting?
Maybe even put loop and range select on middle and right click? Is this possible?

Thanks.

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

Re: C++ custom tool programming tip

Post by rray » 26 Jul 2011, 14:15

Tweak tool "sort of" does that, presumed you don't move anything
Never looked into the old "UserNormals" code. But I guess it would be possible to modify the code. Although since the tool SDK wasn't finished back then I assume it involved a bit of hacking. So probably it would be easier to build on one of the new tool SDK examples.

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

Re: C++ custom tool SDK programming tip

Post by rray » 26 Jul 2011, 19:12

Btw, how would I get the subdivided version of an edge in case I want to highlight that?

Currently looking into the GeometryAccessor, but no idea if this will work.

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

Re: C++ custom tool SDK programming tip

Post by origin » 15 Aug 2011, 15:07

Thanks ray, now I got highlighting of all components, funny thing it's reacting faster than tweak tool
Of course subdees are not working...

on a sidenote, would be cool to have a source code of new edge split tool which will be available in SAP for 2012...since it's build on custom tool sdk, It would be very helpful to look into its code

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

Re: C++ custom tool SDK programming tip

Post by origin » 24 Aug 2011, 01:54

rray wrote:Btw, how would I get the subdivided version of an edge in case I want to highlight that?

Currently looking into the GeometryAccessor, but no idea if this will work.
yep, GeometryAccessor works flawless.
here's code for polygons (objSelected is X3dObject from picking and theFace is face from picking, out_vertPos is vertices position for OGL triangles drawing)

it's quite slow for higher poly meshes, not sure if I can optimize that

Code: Select all

								PolygonMesh mesh(this->objSelected.GetActivePrimitive().GetGeometry() );
								PolygonFace theFace(compRef);
								Property oGApprox;
								this->objSelected.GetPropertyFromName("geomapprox", oGApprox);
								siSubdivisionRuleType subdrule;
								switch ( (int)oGApprox.GetParameter("gapproxmosr").GetValue() ) {
									case 0: subdrule = siCatmullClark;break;
									case 1: subdrule = siXSIDooSabin ;break;
									case 2: subdrule = siLinearSubdivision ;break;
									default: subdrule = siCatmullClark;break;
								};

								CGeometryAccessor geoAc(mesh.GetGeometryAccessor(siConstructionModeDefault,
														subdrule,
														oGApprox.GetParameter("gapproxmosl").GetValue(),
														oGApprox.GetParameter("gapproxmoad").GetValue(),
														oGApprox.GetParameter("gapproxmoan").GetValue() 
									)
									);
								
								LONG faceindex = theFace.GetIndex();

								CLongArray vertInd, trianglesInd,triangleVertInd;
								CDoubleArray vertPos,out_vertPos;
								LONG triangleInd;
								geoAc.GetVertexIndices(vertInd);
								geoAc.GetVertexPositions(vertPos);
								geoAc.GetTriangleVertexIndices(triangleVertInd);
								geoAc.GetPolygonTriangleIndices(trianglesInd);
								
								CLongArray SelfaceInd;

								for (LONG i=0;i<geoAc.GetTriangleCount();i++)
								{
									geoAc.GetPolygonTriangleIndex(i, triangleInd);
									if (triangleInd == faceindex)
									{
										SelfaceInd.Add(i);
									}
								}

								for(LONG i=0;i<SelfaceInd.GetCount();i++)//for every triangle index
								{
									LONG tidx = SelfaceInd[i]*3;
									
									
									for(int k=0;k<3;k++)
									{
										LONG tvidx = triangleVertInd[tidx+k];
										LONG vidx = tvidx*3;
										out_vertPos.Add( vertPos[ vidx ]);
										out_vertPos.Add( vertPos[ vidx + 1]) ;
										out_vertPos.Add( vertPos[ vidx + 2]);
										
									}
								}

scaron
Posts: 114
Joined: 08 Jul 2009, 05:16

Re: C++ custom tool SDK programming tip

Post by scaron » 24 Aug 2011, 03:11

rray wrote:Here's a tip how to get the actual component object (edge, point, polygon) from a custom tool snap/pick operation.

This is useful for example in case you want to highlight an edge.
alternatively you could...

Code: Select all

CRef ref = in_ctxt.GetSnapComponent();
if(!ref.IsValid())
   break;                          
CComAPIHandler cCollItem(ref);
CComAPIHandler cSubComp(cCollItem.GetProperty(L"SubComponent"));
CValueArray indices = cSubComp.GetProperty( L"ElementArray" );
m_meshObject = cSubComp.GetProperty( L"Parent3DObject" );
PolygonMesh mesh( m_meshObject.GetActivePrimitive().GetGeometry() );
Edge edge = mesh.GetEdges().GetItem(indices[0]);
essentially get the element index, parent 3d object, and ask for that index again from the geo. i only suggest that because it took me 5 mins to figure out what the hell that last part was doing in your example code ;)

i wonder why this had to go through com api? i feel like the need for it was removed a long time ago.

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

Re: C++ custom tool SDK programming tip

Post by rray » 24 Aug 2011, 11:33

yep, GeometryAccessor works flawless.
here's code for polygons (objSelected is X3dObject from picking and theFace is face from picking, out_vertPos is vertices position for OGL triangles drawing)

it's quite slow for higher poly meshes, not sure if I can optimize that
Hey thanks for the code, completely missed that function of the GeometryAccessor, was only looking at GetGeometryElementFlags of the Cluster class which let to nothing. Very useful for that!
Btw, I noticed that you use the GetPolygonTriangleIndex function instead of accessing the trianglesInd array, wouldn't that be faster?
essentially get the element index, parent 3d object, and ask for that index again from the geo. i only suggest that because it took me 5 mins to figure out what the hell that last part was doing in your example code ;)

i wonder why this had to go through com api? i feel like the need for it was removed a long time ago.
Thanks Steven - That "Item" call is nasty ;D Your code is better to read, and probably a bit faster too.
I too hope COM will go away from the C++ API, but it's good to have the CComAPIWrapper already instead of doing pure COM programming using IDispatch etc.

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

Re: C++ custom tool SDK programming tip

Post by origin » 24 Aug 2011, 13:30

I tried GetPolygonTriangleIndices but it's returning indicies of new polygons, not old ones.
I made it abit faster by starting iterating from index faceindex*(pow(4.0,oglapproxlevel)) and ending loop just after I have all indexes but it's still dead slow on hi poly meshes.

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

Re: C++ custom tool SDK programming tip

Post by rray » 24 Aug 2011, 14:10

Ok I see. Hm this is weird, the docs mention that GetPolygonTriangleIndexArray should be used if GetPolygonTriangleIndex is used for each triangle on the object, but I can't find that function in CGeometryAccessor.

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

Re: C++ custom tool SDK programming tip

Post by origin » 24 Aug 2011, 15:13

I'm wondering if it wasn't be simpler to just subdivide components with custom catmull clark algorithm.
Because right now:
-getting new vertex pos is easy cause index doesn't change with subdees
-no way to get new edges out of non-subd edge?
-getting new polygons very slow

? B-)

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

Re: C++ custom tool SDK programming tip

Post by origin » 31 Aug 2011, 10:25

I've managed to greatly speed up face index searching by using binary search. So it's like 100 ms for 300k sphere (subdivided to 2million polys). But it still lags compared to tweak tool :<

Ray do you know is there any way to profile a plugin? Now im using clock() but I would have to decorate all code with clock() to know where plugin slowdowns.

For the record because doc is a bit lame in this matter (maybe its bug?):

GetPolygonTriangleIndex (LONG in_tindex, LONG &out_pindex) - will give us index of the polygon that was used to generate the triangle (original polygon from level 0)

GetPolygonTriangleIndices (CLongArray &out_array) - will give us indices of the polygons that was used to generate the triangles (NOT indices of original polygons from level 0, but from current level!!! )

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

Re: C++ custom tool SDK programming tip

Post by rray » 31 Aug 2011, 13:50

No, don't know of any profiling tricks, what I ususally do is replace a block of code that I suspect being slow with something that delivers a fast but fake result, and see if it becomes faster.
Should work fine for custom tools because the dll always gets unloaded when the tool is not in action - Which is very nice because you can go from changed code to testing in Softimage literally in a few seconds.

There's probably something wrong with the the IndexArray getter --- it should get the generating polys not the result polys. Either that or the GetPolygonTriangleIndexArray function is missing

scaron
Posts: 114
Joined: 08 Jul 2009, 05:16

Re: C++ custom tool SDK programming tip

Post by scaron » 28 Jul 2012, 00:08

hey piotrek

i am making a brush based custom tool myself (similar to 'meshPaint') and was wondering about your speed of access to the components of a mesh. i want to recreate exactly what the weight paint tool is doing with regards to orienting the brush with the surface. currently on activating the tool i am taking the selection and caching the normals. then during my MouseMove i access the component indices from a PickBuffer and use those indices to look up the normal(s) to use for alignment of my brush. the speed is acceptable currently but the lag of caching the normals might become a hindrance in the future.

i was wondering, if you dont mind sharing, your technique for accessing the normals of a selected mesh inside a custom tool. since these are custom interactive tools, of course speed is paramount.

thanks
steven

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

Re: C++ custom tool SDK programming tip

Post by origin » 28 Jul 2012, 00:55

Hi,
I calculate them by myself, edge& point data from polymeshes were always giving me weird results

Code: Select all

	CVector3 getEdgeNormal(ToolContext& in_ctxt,Edge &in_edge,bool in_mulmatrix)
	{
		
		CPolygonFaceRefArray l_ep(in_edge.GetNeighborPolygons());
		int cnt = l_ep.GetCount();
		CVector3 vn;
		for (int i=0;i<cnt;i++)
		{
			PolygonFace face(l_ep[i]);
			CVector3 s,e,n;
			n=getPolyNormal(in_ctxt,face,false);
			n.NormalizeInPlace();
			vn+=n;
		}
		X3DObject in_obj=in_edge.GetParent();
		if(in_mulmatrix)
			vn*=in_obj.GetKinematics().GetGlobal().GetTransform().GetRotationMatrix3();
		vn.NormalizeInPlace();
		return vn;
	}
	CVector3 getVertexNormal(ToolContext& in_ctxt,Vertex &in_v, bool in_mulmatrix)		//returns normal
	{
		CPolygonFaceRefArray l_vp(in_v.GetNeighborPolygons());
		int cnt = l_vp.GetCount();
		CVector3 vn;

		for (int i=0;i<cnt;i++)
		{
			PolygonFace face(l_vp[i]);
			CVector3 s,e,n;
			n=getPolyNormal(in_ctxt, face,false);
			vn+=n;
		}
		
		X3DObject	in_obj=in_v.GetParent();
		if(in_mulmatrix)
			vn*=in_obj.GetKinematics().GetGlobal().GetTransform().GetRotationMatrix3();
		vn.NormalizeInPlace();
		return vn;
	}
	// calculate polygon normal (Newell's method) http://www.opengl.org/wiki/Calculating_a_Surface_Normal
	CVector3 getPolyNormal(ToolContext& in_ctxt, PolygonFace &in_poly, bool in_mulmatrix)
	{
			X3DObject			in_obj = in_poly.GetParent();
			PolygonMesh			mesh( in_obj.GetActivePrimitive().GetGeometry() );
			CVertexRefArray		verts( in_poly.GetVertices());
			CLongArray			tri_ind( in_poly.GetTriangleSubIndexArray());
			CVector3Array		n,p;	
							
			UINT vertCnt = verts.GetCount();
			double x=0,y=0,z=0;
			for(UINT i=0;i<vertCnt;i++)
			{
				Vertex current = verts[i];			
				Vertex next = verts[ (i+1) % vertCnt];
				CVector3 c(current.GetPosition() );
				CVector3 n(next.GetPosition() );
				x= x+ ( (c[1]-n[1])* (c[2]+n[2]) );
				y= y+ ( (c[2]-n[2])* (c[0]+n[0]) );
				z= z+ ( (c[0]-n[0])* (c[1]+n[1]) );
			}

			CVector3 normal(x,y,z);		
			if( in_mulmatrix )
				normal *= in_obj.GetKinematics().GetGlobal().GetTransform().GetRotationMatrix3();
			normal.NormalizeInPlace();
			return normal;
	}

scaron
Posts: 114
Joined: 08 Jul 2009, 05:16

Re: C++ custom tool SDK programming tip

Post by scaron » 28 Jul 2012, 02:10

thanks for the code snip.. i see for the polygon normal function you have a PolygonFace argument. where is this coming from? is the PickBuffer giving you this class? i thought the PickBuffer just gets you the Index of the filter you choose and not the actual CRef which you can cast to a PolygonFace?

s

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests