CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
reply share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 01-20-2013, 07:58 PM   #16
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
Quote:
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.
 
Old 01-20-2013, 08:44 PM   #17
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
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 !
 
Old 01-20-2013, 09:54 PM   #18
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
Quote:
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.
 
Old 01-20-2013, 10:04 PM   #19
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
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-20-2013 at 10:14 PM.
 
Old 01-20-2013, 10:29 PM   #20
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
here is fixed and simplified the ISnap interface by using {get, set} status properties.
Code:
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:
Code:
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-20-2013 at 10:32 PM.
 
Old 01-21-2013, 06:11 PM   #21
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
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

Code:
//************************************************** ****************************************** // 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

Code:
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-21-2013 at 07:13 PM.
 
Old 01-25-2013, 11:47 AM   #22
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
this turns out to be a real time saver.

Code:
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.
 
Old 01-25-2013, 02:28 PM   #23
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
Quote:
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
 
Old 01-25-2013, 09:32 PM   #24
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
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

Code:
// 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) ); }


Code:
// 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-25-2013 at 10:33 PM.
 
Old 01-25-2013, 11:44 PM   #25
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
very very nice. thank you. i will definitely add it to the extension that i use
 
Old 01-26-2013, 07:58 AM   #26
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
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


Code:
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-27-2013 at 03:44 PM.
 
Old 01-28-2013, 06:17 PM   #27
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
following this thread http://forums.cgsociety.org/showthr...?f=98&t=1090733
i wrote this function...
Code:
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.
 
Old 02-04-2013, 02:15 PM   #28
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
the code is primitive the function might be useful:
Code:
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:
Code:
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
 
Old 02-07-2013, 03:07 PM   #29
Klunk
Lord of the posts
 
Klunk's Avatar
portfolio
Klunk
United Kingdom
 
Join Date: Sep 2005
Posts: 701
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>

Code:
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>
Code:
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>

Code:
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>

Code:
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>

Code:
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-07-2013 at 03:30 PM.
 
Old 02-07-2013, 03:28 PM   #30
denisT
MAX Doctor
 
denisT's Avatar
portfolio
Denis Trofimov
CA, USA
 
Join Date: Jul 2009
Posts: 9,424
Send a message via ICQ to denisT
VERY COOL! i like it! thanks
 
reply share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

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:20 AM.


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