Useful mxs sdk extension functions

Become a member of the CGSociety

Connect, Share, and Learn with our Large Growing CG Art Community. It's Free!

REPLY TO THREAD
 
Thread Tools Search this Thread Display Modes
  01 January 2013
Originally Posted by claude666: your PathConfigMgr example with a property called radius
....
good now you know how we feel looking at some of your mxs stuff

now it's much clearer
thanks!
as you understand i'm rewriting my mxs extension libraries to the interface style. which is pretty cool i found.
 
  01 January 2013
function publishing's more c++ like interface is nicer to deal with than the macro heavy exposure method and has nice ecapsulation (especially with your way of doing it) but the exposure method does have a 2:1 advantage in speed critical routines going for it !
 
  01 January 2013
Originally Posted by claude666: but the exposure method does have a 2:1 advantage in speed critical routines going for it !

yes. i know that.
 
  01 January 2013
claude666,
what is IDS_RADIUS in your sample and where i have to define it?

edit... never mind. i've got it

Last edited by denisT : 01 January 2013 at 10:14 PM.
 
  01 January 2013
here is fixed and simplified the ISnap interface by using {get, set} status properties.

 class ISnap : public FPInterfaceDesc
 {
 public:
 
 	static const Interface_ID id;
 
 	enum FunctionIDs
 	{
 		_SnapAngle, 
 		_SnapPercent,
 		_GetSnapAngle,
 		_SetSnapAngle,
 		_GetSnapPercent,
 		_SetSnapPercent,
 
 		_getAStatus, _setAStatus,
 		_getPStatus, _setPStatus,
 	};
 
 #define IDS_ASTATUS 0 
 #define IDS_PSTATUS 1 
 
 	ISnap() : FPInterfaceDesc(id, _M("ISnap"), 0, NULL, FP_CORE, end)
 	{
 		AppendFunction(
 			_SnapAngle,_M("SnapAngle"), 0, TYPE_FLOAT, 0, 3,
 				_M("angle"), 0, TYPE_FLOAT,
 				_M("fast"), 0 , TYPE_BOOL, f_keyArgDefault, TRUE,
 				_M("force"), 0 , TYPE_BOOL, f_keyArgDefault, FALSE,
 			end); 
 		AppendFunction(
 			_SnapPercent,_M("SnapPercent"), 0, TYPE_FLOAT, 0, 1,
 				_M("percent"), 0, TYPE_FLOAT,
 			end); 
 		AppendFunction(
 			_GetSnapAngle,_M("GetSnapAngle"), 0, TYPE_FLOAT, 0, 0,
 			end); 
 		AppendFunction(
 			_SetSnapAngle,_M("SetSnapAngle"), 0, TYPE_VALUE, 0, 1,
 				_M("val"), 0, TYPE_FLOAT,
 			end); 
 		AppendFunction(
 			_GetSnapPercent,_M("GetSnapPercent"), 0, TYPE_FLOAT, 0, 0,
 			end); 
 		AppendFunction(
 			_SetSnapPercent,_M("SetSnapPercent"), 0, TYPE_VALUE, 0, 1,
 				_M("val"), 0, TYPE_FLOAT,
 			end); 
 		AppendProperty(_getAStatus, _setAStatus, _T("AngleSnapStatus"), IDS_ASTATUS, TYPE_bool, end); 
 		AppendProperty(_getPStatus, _setPStatus, _T("PercentSnapStatus"), IDS_PSTATUS, TYPE_bool, end); 
 	}
 	bool aStatus;
 	bool getAStatus() { return MAXScript_interface7->ASnapStatus() != 0; }
 	void setAStatus(bool val) { aStatus = SetAngleSnapStatus(val); }
 
 	bool pStatus;
 	bool getPStatus() { return MAXScript_interface7->PSnapStatus() != 0; }
 	void setPStatus(bool val) { aStatus = SetPercentSnapStatus(val); }
 
 	float SnapAngle(float angle, BOOL fast = TRUE, BOOL force = FALSE) {
 		return GetCOREInterface()->SnapAngle(angle, fast, force);
 	}
 	float SnapPercent(float percent) {
 		return GetCOREInterface()->SnapPercent(percent);
 	}
 	float GetSnapAngle() {
 		return MAXScript_interface7->GetSnapAngle();
 	}
 	Value* SetSnapAngle(float val) {
 		MAXScript_interface7->SetSnapAngle(val);
 		return &ok;
 	}
 	float GetSnapPercent() {
 		return MAXScript_interface7->GetSnapPercent();
 	}
 	Value* SetSnapPercent(float val) {
 		MAXScript_interface7->SetSnapPercent(val);
 		return &ok;
 	}
 	bool SetAngleSnapStatus(bool val) {
 		bool prev = (MAXScript_interface7->ASnapStatus()) ? true : false;
 		if (prev != val) MAXScript_interface7->ToggleASnap();
 		return val;
 	}
 	bool SetPercentSnapStatus(bool val) {
 		bool prev = (MAXScript_interface7->PSnapStatus()) ? true : false;
 		if (prev != val) MAXScript_interface7->TogglePSnap();
 		return val;
 	}
 	BEGIN_FUNCTION_MAP
 		FN_3(_SnapAngle, TYPE_FLOAT, SnapAngle, TYPE_FLOAT, TYPE_BOOL, TYPE_BOOL)
 		FN_1(_SnapPercent, TYPE_FLOAT, SnapPercent, TYPE_FLOAT)
 		FN_0(_GetSnapAngle, TYPE_FLOAT, GetSnapAngle)
 		FN_1(_SetSnapAngle, TYPE_VALUE, SetSnapAngle, TYPE_FLOAT)
 		FN_0(_GetSnapPercent, TYPE_FLOAT, GetSnapPercent)
 		FN_1(_SetSnapPercent, TYPE_VALUE, SetSnapPercent, TYPE_FLOAT)
 
 		PROP_FNS(_getAStatus, getAStatus, _setAStatus, setAStatus, TYPE_bool);
 		PROP_FNS(_getPStatus, getPStatus, _setPStatus, setPStatus, TYPE_bool);
 	END_FUNCTION_MAP
 
 };
 const Interface_ID ISnap::id = Interface_ID(0x02feb1967, 0x790a7898);
 static ISnap isnapInterface;
 


it's now:

  Interface: ISnap
   Properties:
	.AngleSnapStatus : bool : Read|Write
	.PercentSnapStatus : bool : Read|Write
   Methods:
	<float>SnapAngle <float>angle fast:<boolean> force:<boolean>
	   fast default value: true
	   force default value: false
	<float>SnapPercent <float>percent
	<float>GetSnapAngle()
	<value>SetSnapAngle <float>val
	<float>GetSnapPercent()
	<value>SetSnapPercent <float>val
   Actions:

claude666, thanks again.

Last edited by denisT : 01 January 2013 at 10:32 PM.
 
  01 January 2013
this one covers some old ground Denis

return the triangles that make up a poly face... if corner_index is set to false then it returns the vert index else it returns the face corner index

//**************************************************  ******************************************
 // getPolyTriangles 
 // mxs exposure
 
 def_visible_primitive(getPolyTriangles,"getPolyTriangles");
 
 // usage: <bool> getPolyTriangles   <edit_poly node> <int face> <bool corner_index>
 
 Value* getPolyTriangles_cf(Value **arg_list, int count)
 {
 	check_arg_count(getPolyTriangles, 3, count);
 	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getPolyTriangles);
 	int face = arg_list[1]->to_int() - 1;
 	range_check(face,0,(pmesh->numf - 1), GetString(IDS_FACE_INDEX_OUT_OF_RANGE));
 	int corner_index = arg_list[2]->to_bool();
 
 	Tab<int> tri;
 	pmesh->f[face].GetTriangles(tri);
 
 // create the return array
 
 	int tri_count = tri.Count();
 	one_typed_value_local(Array* result); 
 	vl.result = new Array(tri_count);
 
 // copy data
 
 	for(int i=0; i < tri_count; i++)
 		corner_index ? vl.result->append(Integer::intern(tri[i] + 1)) :  
 				vl.result->append(Integer::intern(pmesh->f[face].vtx[tri[i]] + 1)) ;
 	return_value(vl.result);
 }


the range_check & get_polyForValue macros can be found in maxsdk\samples\maxscript\mxsagni\MXSAgni.h and the function get_polyForValue calls (_get_polyForValue) can be found in maxsdk\samples\maxscript\mxsagni\common_funcs.cpp

"hidden" interior edges can then be found with

fn GetInteriorEdges tris = (for v = 1 to (tris.count - 3) by 3 collect #(tris[v],tris[v+2]);)


where tris is the output from getPolyTriangles

Last edited by Klunk : 01 January 2013 at 07:13 PM.
 
  01 January 2013
this turns out to be a real time saver.

def_visible_primitive(getEdgeLength,"getEdgeLength");

// <float> getEdgeLength  <Poly poly> <int edge>

Value* getEdgeLength_cf(Value** arg_list, int count)
{
	check_arg_count(getEdgeLength, 2, count);

// get the mesh

	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getEdgeLength);

// get the edge

	int edge = arg_list[1]->to_int() - 1; // mxs to sdk
	range_check(edge,0,(pmesh->nume - 1), GetString(IDS_EDGE_INDEX_OUT_OF_RANGE));

// return the length

	return Float::intern(Distance(pmesh->v[pmesh->E(edge)->v1].p,pmesh->v[pmesh->E(edge)->v2].p));
}


distance would be your preferred function and the poly mesh functions and range check macro are as before.
 
  01 January 2013
Originally Posted by Klunk: this turns out to be a real time saver.

it's the real saver...get-angle-between-edge-faces function is needed to keep the company
 
  01 January 2013
comes in two flavours simple and proper, though proper is twice as slow as simple and simple is about 8x (on 2 quad object) faster than mxs. On a 3200 poly object its 128x faster

// a simplistic face edge angle
     
     def_visible_primitive(getEdgeFaceAngle,"getEdgeFaceAngle");
     
     // <float> getEdgeFaceAngle   <Poly poly> <int edge>
     
     Value* getEdgeFaceAngle_cf(Value** arg_list, int count)
     {
     	check_arg_count(getEdgeFaceAngle, 2, count);
     
     // get the mesh
     
     	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getEdgeFaceAngle);
     
     // get the edge
     
     	int edge = arg_list[1]->to_int() - 1; // mxs to sdk
     	range_check(edge,0,(pmesh->nume - 1), GetString(IDS_EDGE_INDEX_OUT_OF_RANGE));
     
     // He is dead, Jim
     
     	if(pmesh->E(edge)->GetFlag(MN_DEAD))
     		return &undefined;
     
     // we have an open edge
     
     	if(pmesh->E(edge)->f2 == -1) 
     		return Float::intern(1.0f);
     
     // return the dot
     
     	return Float::intern( pmesh->GetFaceNormal(pmesh->E(edge)->f1,true) % pmesh->GetFaceNormal(pmesh->E(edge)->f2,true) );
     }


// the proper method face edge angle
     
     def_visible_primitive(getEdgeFaceAngleReflex,"getEdgeFaceAngleReflex");
     
     // <float> getEdgeFaceAngleReflex   <Poly poly> <int edge> <int& reflex>
     
     Value* getEdgeFaceAngleReflex_cf(Value** arg_list, int count)
     {
     	check_arg_count(getEdgeFaceAngleReflex, 3, count);
     
     // get the mesh
     
     	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getEdgeFaceAngleReflex);
     
     // get the edge
     
     	int edge = arg_list[1]->to_int() - 1; // mxs to sdk
     	range_check(edge,0,(pmesh->nume - 1), GetString(IDS_EDGE_INDEX_OUT_OF_RANGE));
     
     	MNEdge* pedge = pmesh->E(edge);
     
     // set the reflex thunk
     
     	Thunk* reflexThunk = arg_list[2]->to_thunk();
     	
     // He is dead, Jim
     
     	if(pedge->GetFlag(MN_DEAD))
     		return &undefined;
     
     // we have an open edge 
     
     	if(pedge->f2 == -1) 
     	{
     		reflexThunk->assign(Integer::intern(1));
     		return Float::intern(1.0f);
     	}
     
     // get spare f1 spare vert
     
     	MNFace* f1 = pmesh->F(pedge->f1);
     	Point3& c1 = pmesh->v[f1->vtx[f1->FindTriPoint(f1->EdgeIndex(edge))]].p;
     
     // compute normal
     
     	Point3& a = pmesh->v[pedge->v1].p;
     	Point3& b = pmesh->v[pedge->v2].p;
     	Point3 ab = b - a;
     	Point3 ac = c1 - a;
     	Point3 n1 = (ab ^ ac).Normalize();
     
     // compute matrix
     
     	Matrix3 mat;
     	MatrixFromNormal(n1, mat);
     	mat.SetTranslate(a);
     
     // get spare f2 spare vert
     
     	MNFace* f2 = pmesh->F(pedge->f2);
     	Point3& c2 = pmesh->v[f2->vtx[f2->FindTriPoint(f2->EdgeIndex(edge))]].p;
     
     // compute normal
     
     	Point3 bc = c2 - b;
     	Point3 n2 = (bc ^ ab).Normalize();
     
     // transform spare vert into f1 coordsys
     
     	Point3 c2_in_f1 = c2 * Inverse(mat);
     
     // if c2_in_f1.z neg reflex = true  
     
     	reflexThunk->assign(Integer::intern(c2_in_f1.z < 0.0f ? 1 : 0));
     
     // return the dot
     
     	return Float::intern(n1 % n2);
     }
     
     

Last edited by Klunk : 01 January 2013 at 10:33 PM.
 
  01 January 2013
very very nice. thank you. i will definitely add it to the extension that i use
 
  01 January 2013
a cleaner version (though no faster, think the bottle neck is in findtripoint & EdgeIndex) using plane equation to see if the angle is reflex. Also removed the thunk and poke the reflex param directly so no need for the "&"...

edit: put the thunk back as the direct access was having strange effect on the indexing conversion between mxs & sdk



      def_visible_primitive(getEdgeFaceAngleReflex,"getEdgeFaceAngleReflex");
   
   // <float> getEdgeFaceAngleReflex <Poly poly> <int edge> <int& reflex>
   
   Value* getEdgeFaceAngleReflex_cf(Value** arg_list, int count)
   {
   	check_arg_count(getEdgeFaceAngleReflex, 3, count);
   
   // get the mesh
   
   	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, getEdgeFaceAngleReflex);
   
   // get the edge
   
   	int edge = arg_list[1]->to_int() - 1; // mxs to sdk
   	range_check(edge,0,(pmesh->nume - 1), GetString(IDS_EDGE_INDEX_OUT_OF_RANGE));
   	MNEdge* pedge = pmesh->E(edge);
   
   // set the reflex thunk
   
   	Thunk* reflexThunk = arg_list[2]->to_thunk();
   	
   // He is dead, Jim
   
   	if(pedge->GetFlag(MN_DEAD))
   		return &undefined;
   
   // we have an open edge 
   
   	if(pedge->f2 == -1) 
   	{
   		reflexThunk->assign(Integer::intern(1));
   		return Float::intern(1.0f);
   	}
   
   // get spare f1 spare vert
   
   	MNFace* face = pmesh->F(pedge->f1);
   	Point3& c1 = pmesh->v[face->vtx[face->FindTriPoint(face->EdgeIndex(edge))]].p;
   
   // compute f1 normal
   
   	Point3& a = pmesh->v[pedge->v1].p;
   	Point3& b = pmesh->v[pedge->v2].p;
   
   	Point3 ab = b - a;
   	Point3 ac = c1 - a;
   	Point3 n1 = (ab ^ ac).FNormalize();
   
   // define the plane
   
   	float d = n1 % c1;
   
   // get spare f2 spare vert
   
   	face = pmesh->F(pedge->f2);
   	Point3& c2 = pmesh->v[face->vtx[face->FindTriPoint(face->EdgeIndex(edge))]].p;
   
   // compute f2 normal
   
   	Point3 bc = c2 - b;
   	Point3 n2 = (bc ^ ab).FNormalize();
   
   // is c2 below the plane defined by n1 & d  
   
   	reflexThunk->assign(Integer::intern((n1 % c2) - d < 0.0f ? 1 : 0));
   
   // return the dot
   
   	return Float::intern(n1 % n2);
   }
      


edit: have found more efficient way of doing this in mxs and the performance is on average only 5/6 times better.

Last edited by Klunk : 01 January 2013 at 03:44 PM.
 
  01 January 2013
following this thread http://forums.cgsociety.org/showthr...?f=98&t=1090733
i wrote this function...

def_visible_primitive(patchAttach, "patchAttach");
Value* patchAttach_cf(Value **arg_list, int count)
{
	check_arg_count(patchAttach, 2, count);

	INode *patch = arg_list[0]->to_node();
	INode *node = arg_list[1]->to_node();

	if (patch == node) return &false_value;
	
	Object* obj = Get_Object_Or_XRef_BaseObject(patch->GetObjectRef());
	if (obj->ClassID() == patchObjectClassID) 
	{
		PatchObject *ep = dynamic_cast<PatchObject *>(obj);

		GeomObject *object = (GeomObject*)node->GetObjectRef()->Eval(MAXScript_interface->GetTime()).obj;
   
		if(object->CanConvertToType(patchObjectClassID)) {
			PatchObject *attPatch = (PatchObject*)object->ConvertToType(MAXScript_interface->GetTime(),patchObjectClassID);
			if(attPatch) {
				PatchMesh source = attPatch->patch;
				bool canUndo = true;
				ep->DoAttach(node, &source, canUndo);

				if(attPatch != (PatchObject*)object) delete attPatch;
				return &true_value;
			}
		}
	}
	return &false_value;
}

it uses DoAttach which very old, and as many other methods of that time needs to be executed when patch is selected and it is in modifier panel...
it's possible to use a lower level (PatchMesh) Attach but it needs more work.
 
  02 February 2013
the code is primitive the function might be useful:

 def_visible_primitive(abortRender, "abortRender");
 Value* abortRender_cf(Value **arg_list, int count)
 {
 	check_arg_count(patchAttach, 0, count);
 	MAXScript_interface->AbortRender();
 	return MAXScript_interface->CheckForRenderAbort() ? &true_value : &false_value;
 }
 


mxs use:

 fn preRenderAbort event: = 
 (
 	format "% >> % %\n" event (callbacks.notificationparam()) (abortRender())
 )
 callbacks.removescripts id:#render_test
 callbacks.addscript #preRender "preRenderAbort event:#preRender" id:#render_test 
 callbacks.addscript #preRenderEval "preRenderAbort event:#preRenderEval" id:#render_test 
 
 
  02 February 2013
I was hoping this would be more than a 2 man show Denis, if you don't already have these I think you will like them.....

exposes editable poly specified normals without using the edit normal modifier and having the target node selected and the modify panel open for it to work. It would be easy to expand on these if the functionality you need is not here, anyway enjoy....


hasSpecifiedNormals, checks for the MNNormalSpec is present, though this maybe empty
usage: <bool> hasSpecifiedNormals <edit_poly_node>


    def_visible_primitive(hasSpecifiedNormals,"hasSpecifiedNormals");
    
    Value* hasSpecifiedNormals_cf(Value **arg_list, int count)
    {
    	check_arg_count(hasSpecifiedNormals, 1, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, hasSpecifiedNormals);
    	return bool_result(pmesh->GetSpecifiedNormals());
    }



clearSpecifiedNormals, clear specified normals from an editable poly
usage: <bool> clearSpecifiedNormals <edit_poly_node>

def_visible_primitive(clearSpecifiedNormals,"clearSpecifiedNormals");
    
    Value* clearSpecifiedNormals_cf(Value **arg_list, int count)
    {
    	check_arg_count(clearSpecifiedNormals, 1, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, clearSpecifiedNormals);
    
    	if(pmesh->GetSpecifiedNormals())
    	{
    		pmesh->ClearSpecifiedNormals();
    		return &true_value;
    	}
    	else
    		return &false_value;
    }
    


buildSpecifiedNormals, builds specified normals for an editable poly caution this clears any current specified normals before rebuilding the normals
usage: <bool> buildSpecifiedNormals <edit_poly_node>

def_visible_primitive(buildSpecifiedNormals,"buildSpecifiedNormals");
    
    Value* buildSpecifiedNormals_cf(Value **arg_list, int count)
    {
    	check_arg_count(buildSpecifiedNormals, 1, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, buildSpecifiedNormals);
    
    // clear any existing normals
    
    	if(pmesh->GetSpecifiedNormals())
    		pmesh->ClearSpecifiedNormals();
    
    // create an empty specified normals
    
    	pmesh->SpecifyNormals();
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    // initialize the normals
    
    		nspec->Initialize();
    
    // create the faces
    
    		if(nspec->FAlloc(pmesh->numf))
    		{
    // build the normals
    
    			nspec->BuildNormals();
    			return &true_value;
    		}
    	}
    	return &false_value;
    }


getNumSpecNormalFaces, returns the number of specified normal faces
usage: <int> getNumSpecNormalFaces <edit_poly_node>

def_visible_primitive(getNumSpecNormalFaces,"getNumSpecNormalFaces");
    
    Value* getNumSpecNormalFaces_cf(Value **arg_list, int count)
    {
    	check_arg_count(getNumSpecNormalFaces, 1, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, getNumSpecNormalFaces);
    
    	int numfaces = 0;
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    		numfaces = nspec->GetNumFaces();
    	return Integer::intern(numfaces);
    }
    


getNumSpecNormals, returns the number of specified normals
usage: <int> getNumSpecNormals <edit_poly_node>

def_visible_primitive(getNumSpecNormals,"getNumSpecNormals");
    
    Value* getNumSpecNormals_cf(Value **arg_list, int count)
    {
    	check_arg_count(getNumSpecNormals, 1, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, getNumSpecNormalFaces);
    
    	int numNormals = 0;
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    		numNormals = nspec->GetNumNormals();
    	return Integer::intern(numNormals);
    }


setAllSpecNormalsExplicit , sets all normals explicit or not
usage: <bool> setAllSpecNormalsExplicit <edit_poly_node> <bool flag>

def_visible_primitive(setAllSpecNormalsExplicit,"setAllSpecNormalsExplicit");
    
    Value* setAllSpecNormalsExplicit_cf(Value **arg_list, int count)
    {
    	check_arg_count(setAllSpecNormalsExplicit, 2, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, setAllSpecNormalsExplicit);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		nspec->MakeNormalsExplicit(false, NULL ,arg_list[1]->to_bool());
    		return &true_value;
    	}
    	return &false_value;
    }


setAllSpecNormalsSpecified , sets all normals explicit or not
usage: <bool> setAllSpecNormalsSpecified <edit_poly_node> <bool flag>

def_visible_primitive(setAllSpecNormalsSpecified,"setAllSpecNormalsSpecified");
    
    Value* setAllSpecNormalsSpecified_cf(Value **arg_list, int count)
    {
    	check_arg_count(setAllSpecNormalsSpecified, 2, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, setAllSpecNormalsSpecified);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		nspec->SpecifyNormals(false, NULL);
    		return &true_value;
    	}
    	return &false_value;
    }


resetAllSpecNormals , resets all normals which are then recalculated
usage: <bool> resetAllSpecNormals <edit_poly_node>

def_visible_primitive(resetAllSpecNormals,"resetAllSpecNormals");
    
    Value* resetAllSpecNormals_cf(Value **arg_list, int count)
    {
    	check_arg_count(resetAllSpecNormals, 1, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, resetAllSpecNormals);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		nspec->ResetNormals(false,NULL);
    		return &true_value;
    	}
    	return &false_value;
    }


setSpecNormal , sets the normal value
usage: <bool> setSpecNormal <edit_poly_node> <int normal_id> <point3 normal>

def_visible_primitive(setSpecNormal,"setSpecNormal");
    
    Value* setSpecNormal_cf(Value **arg_list, int count)
    {
    	check_arg_count(setSpecNormal, 3, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, setSpecNormal);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		int normalID = arg_list[1]->to_int() - 1;
    		range_check(normalID,0,(nspec->GetNumNormals() - 1), GetString(IDS_NORMAL_INDEX_OUT_OF_RANGE));
    
    		nspec->Normal(normalID) = arg_list[2]->to_point3();
    		return &true_value;
    	}
    	return &false_value;
    }


getSpecNormal , gets the normal value
usage: <point3> getSpecNormal <edit_poly_node> <int normal_id>

def_visible_primitive(getSpecNormal,"getSpecNormal");
    
    Value* getSpecNormal_cf(Value **arg_list, int count)
    {
    	check_arg_count(getSpecNormal, 2, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, getSpecNormal);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		int normalID = arg_list[1]->to_int() - 1;
    		range_check(normalID,0 ,(nspec->GetNumNormals() - 1), GetString(IDS_NORMAL_INDEX_OUT_OF_RANGE));
    
    		return new Point3Value(nspec->Normal(normalID));
    	}
    	return &undefined;
    }


getSpecNormalIndex , gets the normal index from the face and corner (1..to facedeg)
usage: <int> getSpecNormalIndex <edit_poly_node> <int face> <int corner>

    def_visible_primitive(getSpecNormalIndex,"getSpecNormalIndex");
    
    Value* getSpecNormalIndex_cf(Value **arg_list, int count)
    {
    	check_arg_count(getSpecNormalIndex, 3, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, getSpecNormalIndex);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		int face = arg_list[1]->to_int() - 1;
    		int corner = arg_list[2]->to_int() - 1;
    		
    		range_check(face,0,(nspec->GetNumFaces() - 1), GetString(IDS_FACE_INDEX_OUT_OF_RANGE));
    		range_check(corner,0,(nspec->Face(face).GetDegree() - 1), GetString(IDS_FACE_CORNER_INDEX_OUT_OF_RANGE));
    
    		return Integer::intern(nspec->GetNormalIndex(face,corner) + 1);
    	}
    	return &undefined;
    }


getVertIndex , gets the vert index from the face and corner (1..to facedeg) this is to mimic the editnormals GetVertexID function
usage: <int> getVertIndex <edit_poly_node> <int face> <int corner>

def_visible_primitive(getVertIndex,"getVertIndex");
    
    Value* getVertIndex_cf(Value **arg_list, int count)
    {
    	check_arg_count(getVertIndex, 3, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, getVertIndex);
    
    	int face = arg_list[1]->to_int() - 1;
    	int corner = arg_list[2]->to_int() - 1;
    
    	range_check(face,0,(pmesh->numf - 1), GetString(IDS_FACE_INDEX_OUT_OF_RANGE));
    	range_check(corner,0,(pmesh->f[face].deg - 1), GetString(IDS_FACE_CORNER_INDEX_OUT_OF_RANGE));
    
    	return Integer::intern(pmesh->f[face].vtx[corner] + 1);
    }
    

VertexToSpecNormals , returns a bitarray of normal ids from a vertex id
usage: <bitarray> VertexToSpecNormals <edit_poly_node> <int vertex>

def_visible_primitive(VertexToSpecNormals,"VertexToSpecNormals");
    
    Value* VertexToSpecNormals_cf(Value **arg_list, int count)
    {
    	check_arg_count(VertexToSpecNormals, 2, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, VertexToSpecNormals);
    
    // range check
    
    	int vert = arg_list[1]->to_int() - 1;
    	range_check(vert,0,(pmesh->numv - 1), GetString(IDS_VERTEX_INDEX_OUT_OF_RANGE));
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    // new bitarray to size required
    
    		BitArray normals(nspec->GetNumNormals());
    		normals.ClearAll();
    
    		int numfaces = nspec->GetNumFaces();
    
    // make sure we use the max number of faces
    
    		if(pmesh->numf < numfaces) 
    			numfaces = pmesh->numf;
    
    // exit if zero
    
    		if(!numfaces) 
    			return &undefined;
    		
    		for (int i=0; i < numfaces; i++) 
    		{
    // skip over dead faces
    
    			if (pmesh->f[i].GetFlag(MN_DEAD)) 
    				continue;
    
    			MNNormalFace& face = nspec->Face(i);
    			int facedeg = face.GetDegree();
    
    // use the max face degree
    
    			if(pmesh->f[i].deg < facedeg) 
    				facedeg = pmesh->f[i].deg;
    
    			for(int j=0; j < facedeg; j++) 
    			{
    // next vert if not ours
    
    				if(vert != pmesh->f[i].vtx[j]) 
    					continue;
    
    // grab the normal index
    
    				int normalID = face.GetNormalID(j);
    
    // check we're in range if not continue
    
    				if(normalID < 0 || normalID >= normals.GetSize()) 
    					continue;
    
    // save the normal id
    
    				normals.Set(normalID);
    			}
    		}
    		return new BitArrayValue(normals);
    	}
    	return &undefined;
    }


getSpecNormalFaceDeg , gets the normal face degree
usage: <int> getSpecNormalFaceDeg <edit_poly_node> <int face>

def_visible_primitive(getSpecNormalFaceDeg,"getSpecNormalFaceDeg");
    
    Value* getSpecNormalFaceDeg_cf(Value **arg_list, int count)
    {
    	check_arg_count(getSpecNormalFaceDeg, 2, count);
    	MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_BASE_OBJ, NULL, getSpecNormalFaceDeg);
    
    	MNNormalSpec* nspec = pmesh->GetSpecifiedNormals();
    	if(nspec)
    	{
    		int face = arg_list[1]->to_int() - 1;
    		range_check(face,0,(nspec->GetNumFaces() - 1),GetString(IDS_FACE_INDEX_OUT_OF_RANGE));
    
    		return Integer::intern(nspec->Face(face).GetDegree());
    	}
    	return &undefined;
    }


edit: i've just noticed i've used MESH_BASE_OBJ instead of MESH_READ_ACCESS in functions where they don't change the mesh. Just means some functionality (working on objects with modifier present) will be lost but it keeps it consistent I suppose.

Last edited by Klunk : 02 February 2013 at 03:30 PM.
 
  02 February 2013
VERY COOL! i like it! thanks
 
reply share thread



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright 2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 05:07 PM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.