Notifications
Clear all

[Closed] HelperObject that works in a Deform modifier

Is it possible ?

A deformable object is an object with modifiable points that flows through the pipeline. It is not a separate type, but rather is an instance of the Object type that will return TRUE to the Object::IsDeformable() method. Deformable objects must support the following Object methods: Object::NumPoints(), Object::GetPoint(), Object::SetPoint(), and Object::Deform().

Requests by the geometry pipeline for deformable objects are done using the Class_IDdefObjectClassID. Objects that are deformable should return TRUE in the method Object::CanConvertToType() when passed defObjectClassID. A deformable object should also return its this pointer from the implementation of the function Object::ConvertToType() when passed defObjectClassID.

Examples of deformable objects are LinearShape, ParticleObject, PatchObject, PolyObject, SplineShape, and TriObject. An example of a non-deformable object is the CameraObject

even with all the above implemented max still crashes if you try it with a helperObject

1 Reply

this seems to be a workable solution…

	Tab<Point3> points;
	Interval geomValid;
	
	
	MyHelper(BOOL shallow = FALSE) : pblock(NULL), geomValid(FOREVER)
	{
		if(!shallow) // 
		{
			MyHelperDesc.MakeAutoParamBlocks(this);
			// initialize points here
			SetAFlag(A_OBJ_CREATING);
		}
	}
	
	BOOL IsSubClassOf(Class_ID classID) { return classID == ClassID() || classID == DEFORMABLE_HELPER_CLASS_ID; }

	float GetSize()							{ return pblock->GetFloat(khelper_size) * 0.5f; }
	int IsDeformable()						{ return TRUE; }
	int NumPoints()							{ return points.Count(); }
	Point3 GetPoint(int i)					{ return points[i] * GetSize(); }
	void SetPoint(int  i, const Point3&  p) { points[i] = p/GetSize(); } 
	void Deform(Deformer *defProc, int useSel)
    {
		float size = GetSize();
        int npts = points.Count();
        for (int i = 0; i < npts; ++i)
		{
			Point3 pt = points[i] * size;
			pt = defProc->Map(i, pt);
			points[i] = pt/size;
		}
    } 
	int CanConvertToType(Class_ID objtype)  { return IsSubClassOf(objtype) || objtype == defObjectClassID; }
	Object* ConvertToType(TimeValue t, Class_ID objtype) 
	{ 
		return (IsSubClassOf(objtype) || objtype == defObjectClassID) ? this : NULL;
	}

	Object *MakeShallowCopy(ChannelMask channels) 
	{
		MyHelper* newobj = new MyHelper(TRUE);
		newobj->ShallowCopy(this, channels);
		return newobj;
	}

	void ShallowCopy(Object* fromObj, ChannelMask  channels)  
	{
		assert(fromObj->ClassID()==ClassID());
		MyHelper*fobj = static_cast<MyHelper*>(fromObj);
		pblock = fobj->pblock;

		Object::ShallowCopy(fromObj,channels);
		if(channels & GEOM_CHANNEL) 
		{
			points = fobj->points;
			geomValid = fobj->geomValid;
		}
	}
	
	Interval ChannelValidity(TimeValue t, int nchan) 
	{
		if(IsBaseClassOwnedChannel(nchan))
			return Object::ChannelValidity(t,nchan);

		switch(nchan) 
		{
			case GEOM_CHAN_NUM: return geomValid; break;
			default: return FOREVER;
		}
	}

	void SetChannelValidity(int nchan, Interval v) 
	{
		Object::SetChannelValidity(nchan,v);
		switch(nchan) 
		{
			case GEOM_CHAN_NUM: geomValid = v; break;
		}
	}	

	void InvalidateChannels(ChannelMask channels) 
	{
		Object::InvalidateChannels(channels);
		if (channels & GEOM_CHANNEL) geomValid.SetEmpty();
	}