Home Technical Talk

symmetric poly work

polycounter
Offline / Send Message
rollin polycounter
hi folks

does anybody of you know some trick or plugin to give max some kind of a real symmetric work ability?

point is: I want to easily edit a symmetric model with unsymmetric UV´s without loosing the UV´s through the symmetry modifier

thx!!

Replies

  • Michael Knubben
    I can't help you, sorry. I've always just deleted the parts of a model that I wanted to mirror, then unwrapped, then mirrored those parts again and made sure I never had to do symmetric editing afterwards. There might be a way to do it in Max, but I always assumed there wasn't. Then again, I'm still on Max 7, heh.
    If it's only a small edit, I wouldn't mind doing it for you in Silo. If it's anything more than that, I hope someone knows of a way to do it in Max. Which version are you on?
  • MoP
    Offline / Send Message
    MoP polycounter lvl 18
    You could try this: duplicate the model, edit using Symmetry, then copy the Unwrap modifier from the original object's stack to the new object. Dunno if it'll work but it might be worth a try.
  • Neox
    Offline / Send Message
    Neox godlike master sticky
    nope vertexorder is messed up then and the unwrap will do ugly things

    polyboost should be able to do what you need
  • rollin
    Offline / Send Message
    rollin polycounter
    thx man.. you guys are fast!
  • Farfarer
    Man, I've really been missing something like this in Max.

    I should look in to polyboost...
  • Rob Galanakis
  • Funky Bunnies
    Offline / Send Message
    Funky Bunnies polycounter lvl 17
    that transmographier modifier looks nice, Rob

    I coulda sworn bobo had a script to do this or something... just mirror your transformations along an axis and find a threshold of the position to find what points to modify on the other side...

    Anyway, thanks for the link
    that modifier looks pretty robust :D
  • KikiAlex
    --globale
    qazxsw2_symmetry_undo = "MySim"
    qazxsw2_symmetry_auto_axa = undefined
    
    struct sym_vert
    (
    index,
    simetric	
    )
    
    
    fn baga_index_de_mesa_scoate_index_de_uv mesa index canal =
    (
    	vertecsi_de_pe_fete =#()
    	fete_cu_vertexu = (polyop.GetFacesUsingVert mesa index)
    	unde_pe_fete_cu_vertexu =#()
    	indecsi_mapare = #()
    	rezultat = #()
    	for f in fete_cu_vertexu do
    		(
    			append vertecsi_de_pe_fete (polyOp.getFaceVerts mesa f)
    		)
    	for v_f in vertecsi_de_pe_fete do
    		(
    			for d = 1 to v_f.Count do
    			(
    				if v_f[d] == index do
    					(
    					append unde_pe_fete_cu_vertexu d
    					)
    			)
    		)
    	for f_map in fete_cu_vertexu do
    		(
    			append indecsi_mapare (polyop.getMapFace mesa canal f_map)
    		)
    	
    	for i_map = 1 to unde_pe_fete_cu_vertexu.Count do
    		(
    			append rezultat indecsi_mapare[i_map][(unde_pe_fete_cu_vertexu[i_map])]
    		)
    	
    	return rezultat 
    )
    
    
    
    
    
    fn gaseste_invers mesa v_index val_x val_y val_z =
    (
    	distanta_test = 99999999999999999999999
    	ala_bun = v_index
    	mat_i = (matrix3 [val_x,0,0] [0,val_y,0] [0,0,val_z] [0,0,0])
    	pozitia_pe_invers = ((((polyop.GetVert mesa.baseobject v_index node:mesa)*inverse mesa.transform)*mat_i)*mesa.transform)
    	for vert = 1 to  (polyop.GetNumVerts mesa) do
    		(
    			dist_nou = (distance pozitia_pe_invers ((polyop.GetVert mesa.baseobject vert node:mesa)))
    			if  dist_nou < distanta_test do
    				(
    				distanta_test = dist_nou
    				ala_bun = vert
    				)
    		)
    	return ala_bun
    )
    
    fn precalculare_simetrie mesa val_x val_y val_z =
    (
    	undo off
    	(
    	cati_verti = (polyop.GetNumVerts mesa) 
    	progres_l = cati_verti/100
    	if progres_l < 1 do  progres_l = 1
    	--print "sss"
    	--print progres_l 
    	--print "sss"
    	progres = 1
    	sstring = "Searching Symmetry: " 
    	if val_x == -1 do sstring +="X"
    	if val_y == -1 do sstring +="Y"
    	if val_z == -1 do sstring +="Z"
    	progressStart sstring 
    	buffer_sym = #()
    	for vt = 1 to cati_verti do
    		(
    			progres = (vt/progres_l)-progres_l
    			if progres < 0 do progres = 0
    			if (progressUpdate (progres as integer)) then
    			(
    			sym_vert_temp = sym_vert (vt) (gaseste_invers mesa vt val_x val_y val_z)
    			append buffer_sym sym_vert_temp
    			)
    			else
    			(
    			vt = cati_verti
    			progressEnd()
    			return undefined
    			)
    		)
    	)
    	progressEnd()
    	return buffer_sym
    )
    
    --print (precalculare_simetrie selection[1] 1 -1 1)
    fn transforma_dupa_sym_buffer buffer_sym mesa vert val_x val_y val_z cu_mapare =
    (
    	mat_inv = (matrix3 [val_x,0,0] [0,val_y,0] [0,0,val_z] [0,0,0])
    	for m = 1 to buffer_sym.Count do
    		(
    		if buffer_sym[m].index == vert and buffer_sym[m].index != buffer_sym[m].simetric do
    			(
    			o_nou = ((polyop.GetVert mesa.baseobject buffer_sym[m].index node:mesa)*inverse mesa.transform)
    			poz_fi =  (o_nou * mat_inv)
    			--print poz_fi
    			polyOP.SetVert mesa.baseobject (buffer_sym[m].simetric) poz_fi
    			--pentru_uvu
    			canalu = polyOp.getNumMaps mesa.baseobject 
    			if canalu > 0 and cu_mapare do
    				(
    				for j = 0 to (canalu-1) do
    					(
    					if (polyOp.getMapSupport mesa.baseobject j) and ((polyOp.getNumMapVerts mesa.baseobject j) > 0) do
    						(
    						
    					index_normal = baga_index_de_mesa_scoate_index_de_uv mesa.baseobject buffer_sym[m].index j
    					index_oglinda = baga_index_de_mesa_scoate_index_de_uv mesa.baseobject buffer_sym[m].simetric j
    					for i_nor = 1 to index_normal.Count do
    							(
    								try
    								( 
    								temp_poz = polyOp.getMapVert mesa.baseobject j index_normal[i_nor]
    								polyOp.setMapVert mesa.baseobject j index_oglinda[i_nor] temp_poz
    								)
    								catch()
    							)
    					
    						)
    					)
    				)
    			)
    		)
    )
    
    
    fn simetrie_selectie_sym_buffer buffer_sym mesa val_x val_y val_z cu_mapare =
    (
    	undo qazxsw2_symmetry_undo on
    	(
    	verti_selectati = (polyOP.getVertSelection mesa as array)
    
    	for vs in verti_selectati do
    		(
    			transforma_dupa_sym_buffer buffer_sym mesa vs val_x val_y val_z cu_mapare
    		)
    	)
    ) 
    
    
    
    fn gaseste_axa_simetrie_f1 mesa =
    (
    	buf_x = (precalculare_simetrie selection[1] -1 1 1)
    	buf_y = (precalculare_simetrie selection[1] 1 -1 1)
    	buf_z = (precalculare_simetrie selection[1] 1 1 -1)
    	px_r = 0
    	px = 0
    	py = 0
    	pz = 0 
    	for bx = 1 to buf_x.Count do
    		(
    		px_r += buf_x[bx].index
    		)
    	for b_x  = 1 to buf_x.Count do
    		(
    		px += buf_x[b_x].simetric
    		)
    		---
    	for b_y  = 1 to buf_y.Count do
    		(
    		py += buf_y[b_y].simetric
    		)
    		---
    	for b_z  = 1 to buf_z.Count do
    		(
    		pz += buf_z[b_z].simetric
    		)
    	--print px
    	--print py
    	--print pz
    	--print px_r
    	-----------------------
    	if px/10000 == px_r/10000 do 
    		(
    		--print "x"
    		qazxsw2_symmetry_auto_axa = "x"
    		return buf_x
    		)
    	if py/10000 == px_r/10000 do
    		(
    		--print "y"
    		qazxsw2_symmetry_auto_axa = "y"
    		return buf_y
    		)
    	if pz/10000 == px_r/10000 do 
    		(
    		--print "z"
    		qazxsw2_symmetry_auto_axa = "z"
    		return buf_z
    		)
    		return undefined
    )
    
    fn cu_axa_pe_x mesa =
    (
    	buf_x = (precalculare_simetrie selection[1] -1 1 1)
    	return buf_x
    )
    
    fn cu_axa_pe_y mesa =
    (
    	buf_y = (precalculare_simetrie selection[1] 1 -1 1)
    	return buf_y
    )
    
    fn cu_axa_pe_z mesa =
    (
    	buf_z = (precalculare_simetrie selection[1] 1 1 -1)
    	return buf_z
    )
    --print (gaseste_axa_simetrie_f1 $)--auto_sim
    ----------------------
    --cu_axa_pe_y mesa
    --cu_axa_pe_z mesa
    --cu_axa_pe_x mesa
    ----------------------
    --transforma_dupa_sym_buffer buf_demo selection[1] 259 -1 1 1
    --buf_demo = (precalculare_simetrie selection[1] -1 1 1)
    --print buf_demo
    --simetrie_selectie_sym_buffer buf_demo selection[1] -1 1 1
    
    -------------------------------------------------------------
     --globale
     if qazxsw2_symmetry_sim_y == undefined do qazxsw2_symmetry_sim_y = #()
     if qazxsw2_symmetry_sim_z == undefined do qazxsw2_symmetry_sim_z = #()
     if qazxsw2_symmetry_sim_x == undefined do qazxsw2_symmetry_sim_x = #()
     
     fn save_sim =
     (
     	unde = getsavefilename types:"*.sim_dat|*.sdat"
    	if (unde != undefined) and (unde != "") do
    		(
    			intrare_f = createfile unde
    			if intrare_f != undefined do
    				(
    				format "%" "Fisier de simetrie KIKI n" to:intrare_f
    				for sx in qazxsw2_symmetry_sim_x do
    					(
    					format "%,%n" sx.index sx.simetric to:intrare_f
    					)
    				format "%" "|n" to:intrare_f
    				for sy in qazxsw2_symmetry_sim_y do
    					(
    					format "%,%n" sy.index sy.simetric to:intrare_f
    					)
    				format "%" "|n" to:intrare_f
    				for sz in qazxsw2_symmetry_sim_z do
    					(
    					format "%,%n" sz.index sz.simetric to:intrare_f
    					)
    				)
    		)
     )
     
     fn transforma_string_sym_vert intrare =
     (
     	int2 = filterString intrare ","
    	if (int2[1] != undefined) and (int2[2] != undefined) do
    		(
    		sret = sym_vert (int2[1] as integer) (int2[2] as integer)
    		return sret
    		)
    	return undefined
     )
     
     fn load_sim  = 
     (
     	temp_i = #()
    	intrari = #()
    	temp_x = #()
    	temp_y = #()
    	temp_z = #()
    	dat_x = #()
    	dat_y = #()
    	dat_z = #()
    	
     	unde = getOpenFileName types:"*.sim_dat|*.sdat"
    		if (unde != undefined) do
    		(
    			intrare_f = openFile unde 
    			if intrare_f != undefined do
    				(
    				while not(eof intrare_f) do
    					(
    					append temp_i (readLine intrare_f)
    					)
    				)
    		close intrare_f
    		)
    	if temp_i != undefined do
    		(
    			--pentru index de intrare
    			for i = 1 to temp_i.Count do
    				(
    				if temp_i[i] == "|" or temp_i[i] == "Fisier de simetrie KIKI " do 
    					(
    					append intrari (i+1)
    					)
    				)
    			--pentru_x
    			for j = intrari[1]+1 to  (intrari[2]) do
    				(
    					(
    					append temp_x temp_i[j]
    					)
    				)
    			--pentru_y
    			for j = intrari[2] to  ((intrari[3])-2) do
    				(
    					(
    					append temp_y temp_i[j]
    					)
    				)
    			--pentru_z
    			for k = intrari[3] to  ((temp_i.Count)) do
    				(
    					(
    					append temp_z temp_i[k]
    					)
    				)
    			-----------------
    			--transfera in date
    			for m = 1 to temp_x.Count do
    				(
    				if temp_x[m] != undefined do
    					(
    					--print "s"
    					x_tm = (transforma_string_sym_vert temp_x[m])
    					if x_tm != undefined do
    							( 
    							append dat_x x_tm
    							)
    					)
    				)
    			for n = 1 to temp_y.Count do
    				(
    				if temp_y[n] != undefined do
    					(
    					--print "s2"
    					y_tm = (transforma_string_sym_vert temp_y[n])
    					if y_tm != undefined do
    							( 
    							append dat_y y_tm
    							)
    					)
    				)
    			for p = 1 to temp_z.Count do
    				(
    				if temp_z[p] != undefined do
    					(
    					--print "s3"
    					z_tm = (transforma_string_sym_vert temp_z[p])
    					if z_tm != undefined do
    							( 
    							--print z_tm
    							append dat_z z_tm
    							)
    					)
    				)
    		)
    	qazxsw2_symmetry_sim_x = dat_x
    	qazxsw2_symmetry_sim_y = dat_y
    	qazxsw2_symmetry_sim_z = dat_z
     )
     
    rollout symmRollout "Move Symmetry" width:162 height:498
    (
    	button auto_sim "Auto find Symmetry" pos:[15,256] width:134 height:28
    	button btn_x "X Symmetry" pos:[15,289] width:134 height:28
    	button btn_y "Y Symmetry" pos:[15,321] width:134 height:28
    	button btn_z "Z Symmetry" pos:[15,354] width:134 height:28
    	GroupBox grp1 "Activ Buffer" pos:[14,6] width:133 height:49
    	label lbl_x " " pos:[23,26] width:38 height:24
    	label lbl_y " " pos:[64,26] width:36 height:24
    	label lbl_z " " pos:[109,26] width:35 height:24
    	button ok_s_x "Call on selection Symmetry X" pos:[10,63] width:141 height:26
    	button btn16 "Call on selection Symmetry Y" pos:[10,94] width:141 height:26
    	button btn17 "Call on selection Symmetry Z" pos:[10,126] width:141 height:26
    	label lbl10 "  Popescu Alexandru Cristian nr kiki_karon@yahoo.com" pos:[6,458] width:150 height:30
    	button btn_k "Load" pos:[13,386] width:136 height:25
    	button btn_s "Save" pos:[13,416] width:135 height:26
    	checkbox cb1 "Keep UVW" pos:[10,156] width:135 height:16 checked:true
    	
    	Groupbox grp2 "Symmetry buffer" pos:[7,239] width:148 height:212
    	checkbutton rtx "Real Time X Symmetry" pos:[11,176] width:139 height:18 enabled:false
    	checkbutton rty "Real Time Y Symmetry" pos:[11,197] width:139 height:18 enabled:false
    	checkbutton rtz "Real Time Z Symmetry" pos:[11,218] width:139 height:18 enabled:false
    	on symmRollout open do
    	(
    		if qazxsw2_symmetry_sim_y.Count != 0 do lbl_y.text = " Y n" +  (qazxsw2_symmetry_sim_y.Count as string)
    		if qazxsw2_symmetry_sim_x.Count != 0 do lbl_x.text = " X n" +  (qazxsw2_symmetry_sim_x.Count as string)
    		if qazxsw2_symmetry_sim_z.Count != 0 do lbl_z.text = " Z n" +  (qazxsw2_symmetry_sim_z.Count as string)
    		-----
    		if qazxsw2_symmetry_sim_y.Count != 0 do rty.enabled = true
    		if qazxsw2_symmetry_sim_x.Count != 0 do rtx.enabled = true
    		if qazxsw2_symmetry_sim_z.Count != 0 do rtz.enabled = true
    	
    	)
    	on rtx changed state do
    		(
    		if state == on do
    			(
    			when geometry selection[1].baseobject changes  id:#smart_sim_rt_x do
    				(
    					if selection[1] != undefined and ((classof selection[1].baseobject) == Editable_poly) do
    						(
    						simetrie_selectie_sym_buffer qazxsw2_symmetry_sim_x selection[1] -1 1 1 cb1.State
    						)
    				)
    			)
    		if state != on do
    			(
    			deleteallChangeHandlers  id:#smart_sim_rt_x
    			)
    		)
    		
    	on rty changed state do	
    		(
    		if state == on do
    			(
    			when geometry selection[1].baseobject changes  id:#smart_sim_rt_y do
    				(
    					if selection[1] != undefined and ((classof selection[1].baseobject) == Editable_poly) do
    						(
    						simetrie_selectie_sym_buffer qazxsw2_symmetry_sim_y selection[1] 1 -1 1 cb1.State
    						)
    				)
    			)
    		if state != on do
    			(
    			deleteallChangeHandlers  id:#smart_sim_rt_y
    			)
    		)
    		
    	on rtz changed state do	
    		(
    		if state == on do
    			(
    			when geometry selection[1].baseobject changes  id:#smart_sim_rt_z do
    				(
    					if selection[1] != undefined and ((classof selection[1].baseobject) == Editable_poly) do
    						(
    						simetrie_selectie_sym_buffer qazxsw2_symmetry_sim_z selection[1] 1 1 -1 cb1.State
    						)
    				)
    			)
    		if state != on do
    			(
    			deleteallChangeHandlers  id:#smart_sim_rt_z
    			)
    		)	
    		
    		
    		
    		
    	on auto_sim pressed do
    	(
    		if (classof selection[1].baseobject) == Editable_poly do
    			(
    			temp_lib = gaseste_axa_simetrie_f1 selection[1]
    			if qazxsw2_symmetry_auto_axa != undefined do
    				(
    					if qazxsw2_symmetry_auto_axa == "x" do
    						(
    							qazxsw2_symmetry_sim_x = temp_lib
    						)
    					if qazxsw2_symmetry_auto_axa == "y" do
    						(
    							qazxsw2_symmetry_sim_y = temp_lib
    						)
    					if qazxsw2_symmetry_auto_axa == "z" do
    						(
    							qazxsw2_symmetry_sim_z = temp_lib
    						)
    				)
    			qazxsw2_symmetry_auto_axa = undefined
    			if qazxsw2_symmetry_sim_y.Count != 0 do lbl_y.text = " Y n" +  (qazxsw2_symmetry_sim_y.Count as string)
    			if qazxsw2_symmetry_sim_x.Count != 0 do lbl_x.text = " X n" +  (qazxsw2_symmetry_sim_x.Count as string)
    			if qazxsw2_symmetry_sim_z.Count != 0 do lbl_z.text = " Z n" +  (qazxsw2_symmetry_sim_z.Count as string)
    			-----
    			if qazxsw2_symmetry_sim_y.Count != 0 do rty.enabled = true
    			if qazxsw2_symmetry_sim_x.Count != 0 do rtx.enabled = true
    			if qazxsw2_symmetry_sim_z.Count != 0 do rtz.enabled = true
    			)
    	)
    	on btn_x pressed do
    	(
    		if (classof selection[1].baseobject) == Editable_poly do
    			(
    			qazxsw2_symmetry_sim_x = cu_axa_pe_x selection[1]
    			if qazxsw2_symmetry_sim_x.Count != 0 do lbl_x.text = " X n" +  (qazxsw2_symmetry_sim_x.Count as string)
    			if qazxsw2_symmetry_sim_x.Count != 0 do rtx.enabled = true
    					)
    	)
    	on btn_y pressed do
    	(
    		if (classof selection[1].baseobject) == Editable_poly do
    			(
    			qazxsw2_symmetry_sim_y = cu_axa_pe_y selection[1]
    			if qazxsw2_symmetry_sim_y.Count != 0 do lbl_y.text = " Y n" +  (qazxsw2_symmetry_sim_y.Count as string)
    			if qazxsw2_symmetry_sim_y.Count != 0 do rty.enabled = true
    			)
    	)
    	on btn_z pressed do
    	(
    		if (classof selection[1].baseobject) == Editable_poly do
    			(
    			qazxsw2_symmetry_sim_z = cu_axa_pe_z selection[1]
    			if qazxsw2_symmetry_sim_z.Count != 0 do lbl_z.text = " Z n" +  (qazxsw2_symmetry_sim_z.Count as string)
    			if qazxsw2_symmetry_sim_z.Count != 0 do rtz.enabled = true
    			)
    	)
    	on ok_s_x pressed do
    	(
    		if selection[1] != undefined and ((classof selection[1].baseobject) == Editable_poly) do
    			(
    			simetrie_selectie_sym_buffer qazxsw2_symmetry_sim_x selection[1] -1 1 1 cb1.State
    			)
    	)
    	on btn16 pressed do
    	(
    		if selection[1] != undefined and ((classof selection[1].baseobject) == Editable_poly) do
    			(
    			simetrie_selectie_sym_buffer qazxsw2_symmetry_sim_y selection[1] 1 -1 1 cb1.State
    			)
    	)
    	on btn17 pressed do
    	(
    		if selection[1] != undefined and ((classof selection[1].baseobject) == Editable_poly) do
    			(
    			simetrie_selectie_sym_buffer qazxsw2_symmetry_sim_z selection[1] 1 1 -1 cb1.State
    			)
    	)
    	on btn_k pressed do
    	(
    	load_sim()
    	if qazxsw2_symmetry_sim_y.Count != 0 do lbl_y.text = " Y n" +  (qazxsw2_symmetry_sim_y.Count as string)
    	if qazxsw2_symmetry_sim_x.Count != 0 do lbl_x.text = " X n" +  (qazxsw2_symmetry_sim_x.Count as string)
    	if qazxsw2_symmetry_sim_z.Count != 0 do lbl_z.text = " Z n" +  (qazxsw2_symmetry_sim_z.Count as string)
    	)
    	on btn_s pressed do
    	(
    	save_sim()	
    	)
    )createdialog symmRollout 
    --save_sim()
    --load_sim buffer_x buffer_y buffer_z
    
    

    OK, this is a BETA script , it calculates symmetry using the pivot as the mirror point, the mesh should be an 'editable poly' and it should have =< 10000 tris
    You should 'Reset Xform' the mesh before using it,you should not have any modifiers in the stack,
    It only works on move,rotate,scale.
    It can't use soft-selection.

    To use it press the :
    -Symmetry buffer>X Symmetry(or what kind of symmetry you need).
    -Wait to male the buffer(on my computer for 10000tris took 3min).
    -press the Real Time X Symmetry and work.
    -you can also press 'Call on selection Symmetry X'(or what kind of symmetry you need) if you don't need it to be real time or it drags to much,select what you want to be mirrored and press it.
    -if you want to keep the buffer you can save it and use it later(Symmetry buffer>Save\Load).
  • rollin
    Offline / Send Message
    rollin polycounter
    wow Rob, thats exactly what i was looking for.. thx !!
Sign In or Register to comment.