Notifications
Clear all

[Closed] Useful mxs sdk extension functions

I do find it very odd that those normal functions are not in polyops and meshops !? Oh I like those and have a application for them

also you should probably rename VertexToSpecNormals to getNormalsUsingVert (makes it more mxs like) to late for me as I’m to lazy to change the calling scripts

I’m intrigued by these functions, how do you actually get these set up with max?

Do you need to compile a DLX file?

yep, with ms visual studio (version dependent on the target version of max) and the sdk, which is somewhere on your max install disks. My experience of it is, and peoples reluctance to use it is not using the sdk (though the reference is sketchy at best) is getting to grips with creating the initial project in ms visual studio, the stream of errors that can run down the output window when you get it wrong can seem very daunting and ms dev speech is something to behold . But Once up and running though in the case of most of these functions its a case of cut, paste, compile and run.
there is a free book on the subject

If these are all so useful is it worth lobbying Autodesk to include them in the next 3dsmax build? Surely you’ve done all the hard work for them?

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…

I really wish I could post some useful functions like you guys but I hadn’t had to deal with that kind of geometry stuff.

Thanks for sharing, btw.
I am sure it will be useful one day…

I really wish I could post some useful functions like you guys but I hadn’t had to deal with that kind of geometry stuff.

I wouldn’t worry we’re not that fussy

from the slow rollout drawing thread these can turn off redraw while adding rollouts then force a redraw when complete. Gets rid of the annoying flicker with large and complex gui.

// usage: <bool> SetWindowRedraw <HWND>window <bool>

def_visible_primitive(SetWindowRedraw, "SetWindowRedraw");
   
   Value* SetWindowRedraw_cf(Value **arg_list, int count)
   {
   	check_arg_count(SetWindowRedraw, 2, count);
   	HWND hWnd = (HWND)arg_list[0]->to_int();
   	bool redraw = arg_list[1]->to_bool();
   
   	LRESULT res = SendMessage( hWnd , WM_SETREDRAW, redraw, 0);
   	return bool_result(res);
   }

// usage: RedrawWindow window

def_visible_primitive(RedrawWindow, "RedrawWindow");
   
   Value* RedrawWindow_cf(Value **arg_list, int count)
   {
   	check_arg_count(RedrawWindow, 1, count);
   	HWND hWnd = (HWND)arg_list[0]->to_int();
   
   	LRESULT lres = SendMessage( hWnd , WM_SETREDRAW, true, 0);
   	BOOL res = RedrawWindow(hWnd, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
   	return bool_result(lres);
   }

window handle can be accessed with something like

hwnd = (windows.getchildhwnd 0 myrollout.title)[1]

there is probably a better way to get the current dialog handle in the sdk but I to lazy too look ! again thanks to Denis for pointing me in the right direction ( I really should learn more about the windows api )


def_visible_primitive(getDialogHWND, "getDialogHWND");
Value* getDialogHWND_cf(Value **arg_list, int count)
{
	check_arg_count(getDialogHWND, 1, count);
	if (is_rollout(arg_list[0])) 
	{
		HWND hwnd = ((Rollout*)arg_list[0])->page;
		return IntegerPtr::intern((INT_PTR)hwnd);
	}
	if (is_rolloutfloater(arg_list[0]))
	{
		HWND hwnd = ((RolloutFloater*)arg_list[0])->window;
		return IntegerPtr::intern((INT_PTR)hwnd);
	}	
	return &undefined;
}

sweet, I’m absolutely staggered at the visual improvement these 3 tiny functions make ! Also useful for getting rid of the flicker when setting gui items to disabled on a selection change or in a selection change handler (which has irritated me for years)

following on from the quadifier challenge I ported my mxs function to the sdk, very quick now.

returns a bitarray of edges that if removed would create quads, the routine respects material
boundaries and the mesh topology <topo_tolerance> 1.0 faces must be planar 0.0 any ol’ face
will do. The quads edges are selected on how “square” the quads are using <quad_tolerance>
(0.0 being perfect 1.0 allows parallel edges) there is an issue where it cannot tell the difference
between concave and convex polys though

<bitarray> QuadifyEdges <poly> <quad_tolerance> <topo_tolerance>


 
  def_visible_primitive(QuadifyEdges,"QuadifyEdges");
  
  Value* QuadifyEdges_cf(Value** arg_list, int count)
  {
      check_arg_count(QuadifyEdges, 3, count);
      MNMesh* pmesh = get_polyForValue(arg_list[0], MESH_READ_ACCESS, NULL, QuadifyEdges);
      float quad_tolerance = arg_list[1]->to_float();
      float topo_tolerance = arg_list[2]->to_float();
  
      int numedges = pmesh->nume;
  
      BitArray edges(numedges);
      edges.ClearAll();
  
      for(int i = 0; i < numedges ;i++)
      {
          MNEdge* edge = pmesh->E(i);
  
          if(edge->GetFlag(MN_DEAD)) 
              continue;
  
          if(edge->f2 == -1)
              continue;
  
          MNFace* f1 = pmesh->F(edge->f1);
          MNFace* f2 = pmesh->F(edge->f2);
          float edgeAngle = pmesh->GetFaceNormal(edge->f1,true) % pmesh->GetFaceNormal(edge->f2,true);
  
          if(f1->deg == 3 && f2->deg == 3 && f1->material == f2->material && edgeAngle > topo_tolerance)
          {
  // collect the edges that make up the prospective quad
  
              int v1e1 = -1;    // v1 f1 edge but not the current edge
              for(int j = 0; j < 3; j++)
              {
                  if(f1->edg[j] == i) continue; 
                  if(pmesh->E(f1->edg[j])->v1 == edge->v1 || pmesh->E(f1->edg[j])->v2 == edge->v1)
                  {
                      v1e1 = f1->edg[j];
                      break;
                  }
              }
              int v1e2 = -1; // v1 f2 edge but not the current edge
              for(int j = 0; j < 3; j++)
              {
                  if(f2->edg[j] == i) continue; 
                  if(pmesh->E(f2->edg[j])->v1 == edge->v1 || pmesh->E(f2->edg[j])->v2 == edge->v1)
                  {
                      v1e2 = f2->edg[j];
                      break;
                  }
              }
              int v2e1 = -1; // v2 f1 edge but not the current edge
              for(int j = 0; j < 3; j++)
              {
                  if(f1->edg[j] == i) continue; 
                  if(pmesh->E(f1->edg[j])->v1 == edge->v2 || pmesh->E(f1->edg[j])->v2 == edge->v2)
                  {
                      v2e1 = f1->edg[j];
                      break;
                  }
              }
              int v2e2 = -1; // v2 f2 edge but not the current edge
              for(int j = 0; j < 3; j++)
              {
                  if(f2->edg[j] == i) continue; 
                  if(pmesh->E(f2->edg[j])->v1 == edge->v2 || pmesh->E(f2->edg[j])->v2 == edge->v2)
                  {
                      v2e2 = f2->edg[j];
                      break;
                  }
              }
              if( v1e1 == -1 ||  v1e2 == -1 || v2e1 == -1 || v2e2 == -1)
                  continue;  // something wrong to get here :(
  
              Point3 e1dir = (pmesh->v[pmesh->E(v1e1)->v2].p - pmesh->v[pmesh->E(v1e1)->v1].p).FNormalize();
              Point3 e2dir = (pmesh->v[pmesh->E(v1e2)->v2].p - pmesh->v[pmesh->E(v1e2)->v1].p).FNormalize();
              float v1edgeangle = fabs(e1dir % e2dir);
  
              e1dir = (pmesh->v[pmesh->E(v2e1)->v2].p - pmesh->v[pmesh->E(v2e1)->v1].p).FNormalize();
              e2dir = (pmesh->v[pmesh->E(v2e2)->v2].p - pmesh->v[pmesh->E(v2e2)->v1].p).FNormalize();
              float v2edgeangle = fabs(e1dir % e2dir);
  
              if(v1edgeangle < quad_tolerance && v2edgeangle < quad_tolerance)
                  edges.Set(i);
          }
      }
      return new BitArrayValue(edges);
  }
Page 4 / 18