PDA

View Full Version : PolySplitRing Tool - Script idea


Zbuffer
12-21-2008, 04:46 PM
Hi,
A friend just showed me the PolySplitRing tool in Maya, and boy, do I wish we had that in Max !

Basically, it allows you to insert Edge Loops at the position of the mouse. Really neat !

I am trying to have a go at it...
but I need help (specially for the preview/mouse parts)

So, How to do this in max ???
pseudo code:
1. get the object under the mouse
2. get the face under the mouse
3. get the faces' edge closest to the mouse
5. ring select the edge
6. divide the edges using the position of the mouse between the edgeVerts
7. connect the new vertices


fn divideEdges obj val = (
obj.SelectEdgeRing()
RingEdges=(polyop.getEdgeSelection obj) as array
polyop.setEdgeSelection obj #()
polyop.setVertSelection obj #()
for e in RingEdges do obj.divideEdge e val select:true
obj.ConnectVertices()
)



What would be the best implementation for this ? a Tool, a MouseTrack ?

the CleanCut script ( http://www.scriptspot.com/rhyde/cleancut.html ) can be good base to start

If any of you script gurus want to have a go at it, I'm sure the max community would appreciate this tool !

Any hints, infos, code etc.. most welcome !

RobGalanakis
12-21-2008, 05:20 PM
We just had a long thread at Polycount about this:

http://boards.polycount.net/showthread.php?t=58089

I didn't get a chance to contribute anything significant, but if anyone here comes up with a better solution than what that other guy did, please post it there, or I can do it.

jonahhawk
12-21-2008, 07:11 PM
I know this doesn't help with scripting but... Polyboost has this tool. (and more) http://www.polyboost.com/

go to Features, Modeling, then scroll down to Poly Draw.

Zbuffer
12-22-2008, 01:19 PM
Thx for the input.
The thread @ polycount is very interesting !


I hope to post something in a few days...

PiXeL_MoNKeY
12-22-2008, 04:00 PM
You may want to look at the IllusionCatalyst (http://illusioncatalyst.com/ic_shape_ref.html#DrawTool) Draw Loop tool. It appears that it may do what you want, and is free.

-Eric

SyncViewS
12-22-2008, 07:06 PM
Hi guys,
IllusionCatalyst (version 1.1.1) can insert an edge loop only in the middle of edge crossed, by using the Draw tool and pressing SHIFT. I already coded an update which allows to insert the loop anywhere according to the crossing edge position. Unfortunately it doesn't have a preview feature. I tried to get something with gw viewport drawing, but came up to nothing good. I guess the SDK can provide a better way, like the hint dashed line got in the standard cut tool. If you like my set of instruments and consider this feature fundamental, I can pack up a small new release.

p.s.
Thanks Eric for remembering and pointing out my tools.

- Enrico

Zbuffer
12-22-2008, 11:00 PM
Hi Enrio
I just tried you scripts !!! WAY cool !!!
and open source... WoW !! thx a bunch

I shamelessly stole code from CleanCut...

well, I managed to get the object, then the face, then the edge
and I can show a preview, BUT, I can't get the preview to update with the mouse moving...
(though the real function inserts the loop at the mouse point...
also, There is a problem when edges are not ordered...

maybe that can give someone an idea...
NOTE: VERY BUGGY AND NOT FINISHED


---------------------------------------------
---- Mosttly inspired from Cleancut:
---- http://www.scriptspot.com/rhyde/cleancut.html
----------------------------------------------
macroScript Insert_Loop
category:"Zbuffer"
(
global rcvb -- the redraw callback
unRegisterRedrawViewsCallback rvcb
local thresh
local RingEdges
local Edge_Percent=0.5
local PolyObj
local MeshObj
local PolyIndex
local EdgeIndex
local clickPoint
local FirstClick=true
-- From CLeanCut
fn getPolyIndexFromTri msh poly tri =
(
triverts = (meshop.getVertsUsingFace msh tri) as array
result = undefined
allVertsFaces = #()
for item in triverts do
(
append allVertsFaces ((polyOp.getFacesUsingVert poly item) as array)
)
for item in allVertsFaces[1] do
(
if (((findItem allVertsFaces[2] item) != 0) and ((findItem allVertsFaces[3] item) != 0)) do
(
result = item
)
)
result
)

fn GetPosAlongEdges obj edges val =
(
local pos=#()
for edg in edges do
(
v=polyop.getEdgeVerts obj edg
sort v
p1=Polyop.getVert obj v[1]
p2=Polyop.getVert obj v[2]
append pos (p1+((p2-p1)*val))
)
pos
)
-- From CleanCut
fn autoThreshold obj samples:5 factor:8 =
(
seed(random (random 1 65535) (random 1 65535))
alength = 0
for i in 1 to samples do
(
rnd_idx = random 1 obj.numFaces
fac = obj.faces[rnd_idx].index
edg = (polyOp.getFaceEdges obj fac as array)[1]
e_verts = polyOp.getEdgeVerts obj edg as array
alength += (distance (polyOp.getVert obj e_verts[2]) (polyOp.getVert obj e_verts[1]))
)
thresh = ((alength/samples)/factor)
)

fn isClosedRing obj edges =
(
res=false
faces1 = polyop.getEdgeFaces obj edges[1]
faces2 = polyop.getEdgeFaces obj edges[edges.count]
for i in faces2 do if finditem faces1 i !=0 do res=true
res
)
-- the redraw Callback
fn highlightEdges =
(
l_col = green
gw.setColor #line l_col
local pos=GetPosAlongEdges PolyObj RingEdges Edge_Percent
posPairs=#()
for i=1 to (pos.count-1) do
(
append posPairs #(pos[i], pos[i+1])
)
if (isClosedRing PolyObj RingEdges) do append posPairs #(pos[pos.count], pos[1])
for edg in posPairs do
(
pt1 = edg[1]
pt2 = edg[2]
v = (pt2 - pt1)
v_len = length v
sz = thresh/30
vm = matrixFromNormal (normalize v)
vm.translation = pt1
gw.setTransform vm
for i in 0 to 90 by 30 do
(
x = sz * (cos i)
y = sz * (sin i)
gw.polyline #([x,y,0], [x,y,v_len]) false
gw.polyline #([-x,-y,0], [-x,-y,v_len]) false
gw.polyline #([-x,y,0], [-x,y,v_len]) false
gw.polyline #([x,-y,0], [x,-y,v_len]) false
)
)
gw.enlargeUpdateRect #whole
gw.updateScreen()
)
-- pointer to the redraw callback function
fn rvcb = highlightEdges()
-- does the real thing
fn divideEdges obj val =
(
undo "InsertLoop" on
(
obj.SelectEdgeRing()
polyop.setEdgeSelection obj #()
polyop.setVertSelection obj #()
for e in RingEdges do obj.divideEdge e val select:true
obj.ConnectVertices()
)
)
-- find the closest edge to the mouse with the face index
fn FindClosestEdge f pt =
(
FaceEdges=polyop.getFaceEdges PolyObj f
closest=999999
idx=undefined
for edg in FaceEdges do
(
EdgeVerts=polyop.getEdgeVerts PolyObj edg
EdgePos=((polyop.getVert PolyObj EdgeVerts[1]) + (polyop.getVert PolyObj EdgeVerts[2]))/2.0
d=distance pt EdgePos
if d<closest do (closest=d; idx=edg)
)
idx
)
-- the Mouse Track function - only preview
fn DoInsertLoop msg ir obj faceNum shift ctrl alt =
(
case msg of
(
#freemove:(if FirstClick then #continue else #stop)
#mousePoint:( -- user clicked once
if FirstClick then
(
unRegisterRedrawViewsCallback rvcb
PolyIndex = getPolyIndexFromTri MeshObj PolyObj faceNum
EdgeIndex=FindClosestEdge PolyIndex ir.pos
polyop.setEdgeSelection PolyObj EdgeIndex
PolyObj.SelectEdgeRing()
RingEdges=(polyop.getEdgeSelection PolyObj) as array
polyop.setEdgeSelection PolyObj #()
FirstClick=false
RegisterRedrawViewsCallback rvcb
#continue
)
else
(
divideEdges PolyObj Edge_Percent
if isValidNode MeshObj do delete MeshObj
unRegisterRedrawViewsCallback rvcb
#stop
)
)
#mouseMove:( -- user clicked and is moving the mouse
if FirstClick do
(
unRegisterRedrawViewsCallback rvcb
clickPoint=ir.pos
PolyIndex = getPolyIndexFromTri MeshObj PolyObj faceNum
EdgeIndex=FindClosestEdge PolyIndex ir.pos
polyop.setEdgeSelection PolyObj EdgeIndex
PolyObj.SelectEdgeRing()
RingEdges=(polyop.getEdgeSelection PolyObj) as array
polyop.setEdgeSelection PolyObj #()
FirstClick=false
RegisterRedrawViewsCallback rvcb
)
v1=polyop.getVert PolyObj ((polyop.GetEdgeVerts PolyObj EdgeIndex)[1])
v2=polyop.getVert PolyObj ((polyop.GetEdgeVerts PolyObj EdgeIndex)[2])
-- Buggy - need to check the direction of the edge
-- Edge_Percent=1-((distance ir.pos v1)/length (v2-v1))
Edge_Percent=((distance ir.pos v1)/length (v2-v1))
if Edge_Percent<0 do Edge_Percent=0
if Edge_Percent>1 do Edge_Percent=1
-- unregisterRedrawViewsCallback rvcb
-- registerRedrawViewsCallback rvcb
-- redrawViews()
--highlightEdges()
--#continue
)
#mouseAbort:
(
if isValidNode MeshObj do delete MeshObj
unregisterRedrawViewsCallback rvcb
return #stop
)
)
#continue
)
------------------------------------------------------------------------------
if selection[1] != undefined do
if classof selection[1].baseObject == Editable_Poly do
(
local obj=selection[1]
PolyObj=selection[1]
MeshObj = snapshot obj
hide MeshObj
autoThreshold PolyObj factor:12
mouseTrack on:MeshObj trackCallback:DoInsertLoop
unRegisterRedrawViewsCallback rvcb
if isValidNode MeshObj do delete MeshObj
)
)


please help me improve this mess ;)

SyncViewS
12-23-2008, 11:12 AM
Hi Zbuffer,
I'm on it, currently integrating IllusionCatalyst code into your script. The function to get polygon from face mesh isn't accurate, because it doesn't consider the case where three vertices from the same mesh face belong to two polygons. By now I made it draw an edge loop according to the second mouse click position and not in the middle, but doesn't show right and updating preview yet. I'll post some messy code too as soon as it start working someway, then we'll go for optimization to solve heavy calculation issues, a simple recursive function is involved.

- Enrico

Zbuffer
12-23-2008, 01:39 PM
Cool !
i'm leaving for a few days...
I'll try to post some update then...
Hope you can get this sorted out !
Merry Xmas to all

SyncViewS
01-06-2009, 03:09 PM
Hi guys,
I'm glad to share IC_PolySplitRing script. This is my 3ds Max version of the most required Maya tool. Get it freely from IllusionCatalyst (http://www.illusioncatalyst.com) website in the MaxScript page (http://www.illusioncatalyst/mxs.php).

The script has been thoroughly tested, anyhow please report any issue.
Thank you, enjoy!

- Enrico

Piflik
01-06-2009, 03:25 PM
Just downloaded it. If this works as intended, this will be my new favourite tool. :love:

SaiGreat
01-08-2009, 04:36 PM
Very useful tool ~
unfortunately it can't show end result with modifier now,but better than none.:applause:

KiLa
01-08-2009, 07:02 PM
Nice one, thank you!!!

Maybe an option where you could specify whether the preview would show through shaded object or not, would make it even better: if the geometry is dense, the preview line will make the positioning of the new loop difficult.

Thanks again - amazing tool!

-Kimmo

SyncViewS
01-09-2009, 11:15 PM
Thank you guys,
I got in mind some new features like showing the preview loop according to face normals (hide backfacing) and choosing colors for preview. On a first look, they would require some major modifications to the code, but I guess I'll give it a try. In the meantime I found and corrected a small bug that prevented the tool quit with right mouse button click. The updated version is on the IllusionCatalyst (http://www.illusioncatalyst.com) website as usual. Please help me by reporting any bug. Thank you.

- Enrico

CGTalk Moderation
01-09-2009, 11:15 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.