Announcements

Between mid-October and November, the content on AREA will be relocated to the Autodesk Community M&E Hub and the Autodesk Community Gallery. Learn more HERE.

Transfer vertex normals from another object.

Transfer vertex normals from another object.

dmitriy.shpilevoy
Collaborator Collaborator
3,389 Views
14 Replies
Message 1 of 15

Transfer vertex normals from another object.

dmitriy.shpilevoy
Collaborator
Collaborator

I need normals of border vertices on object A to match normals of vertices in same coordinates of object B, basically to fix the seam without affecting object B.

Tried noors normal thief and it does almost that, except there is still a small split that prevents smooth shading. Interestingly enough is that in-house tool produce same result with small normals deviation. Is there other ways to do this or maybe there is something about the mesh itself I need to check/change for scripts to work precisely?

Both objects are editable poly.

border_normals.jpg

0 Likes
Accepted solutions (1)
3,390 Views
14 Replies
Replies (14)
Message 2 of 15

denisT.MaxDoctor
Advisor
Advisor

post the NormalThief script to find the problem with the code and post the sample scene to see if there is anything wrong with the meshes (objects).

 

0 Likes
Message 3 of 15

domo.spaji
Advisor
Advisor

@dmitriy.shpilevoy wrote:

... to fix the seam...

 


"Welder" modifier - with default "weld normals" setting.



 

0 Likes
Message 4 of 15

denisT.MaxDoctor
Advisor
Advisor

@domo.spaji wrote:

@dmitriy.shpilevoy wrote:

... to fix the seam...

 


"Welder" modifier - with default "weld normals" setting.



 


I understand that it does not need to be welded, but only the normals need to be aligned.

0 Likes
Message 5 of 15

dmitriy.shpilevoy
Collaborator
Collaborator

Correct. Objects should remain separate and no changes to B made. Only adjacent vertex normals of A can be modified.

 

example scene attached

 

Noors Normal Thief

http://www.scriptspot.com/files/noorsnormalthief1.1.1_0.ms

 

 

0 Likes
Message 6 of 15

denisT.MaxDoctor
Advisor
Advisor

There is a bug in the script you are using... it can be fixed, but before that it would be good to allow "pairing" (targeting) of vertex normal IDs.

The general (universal) solution is quite complex and is a kind of "treasure" that is a shame to share for free. Therefore, we need to draw up simple rules for clear "pairing" specifically for your case. Could you do it?

0 Likes
Message 7 of 15

dmitriy.shpilevoy
Collaborator
Collaborator

I need to change normals of object A vertices which:

- belong to mesh A border

- are "touching" (within X threshold) border vertices of object B

Keeping the treasure solution private is understandable, though I'm not sure if rules above are narrow enough or cover the universal solution.

 

I would try to poke around with it myself, but alas not that good at maxscript. Thought how can I go about doing something like that and got stuck at first steps - can't figure out how to find closest vertex of another object except comparing each border vertex of A with every border vertex of B. It works(in my head), but might take too much time if both objects have 10k+ tris.

0 Likes
Message 8 of 15

denisT.MaxDoctor
Advisor
Advisor

Can we say that only open edge normals need to be processed?

0 Likes
Message 9 of 15

dmitriy.shpilevoy
Collaborator
Collaborator

Definitely.

0 Likes
Message 10 of 15

denisT.MaxDoctor
Advisor
Advisor

👍

this kind of confines make the algorithm much easier.

0 Likes
Message 11 of 15

denisT.MaxDoctor
Advisor
Advisor

There are three options how to #align normals:

1. A to B

2. B to A

3. Average A and B

 

What is your case?

 

0 Likes
Message 12 of 15

denisT.MaxDoctor
Advisor
Advisor

Averaging only makes sense if we allow the normals for both parts to change (which makes sense in and of itself). Thus, there are only two options: A → B and B → A.

0 Likes
Message 13 of 15

denisT.MaxDoctor
Advisor
Advisor
Accepted solution
try(destroydialog AlignSeamNormalsRol) catch()
rollout AlignSeamNormalsRol "Align Seam Normals" width:191
(
	fn setMaxWindowRedraw act = if hwnd != undefined do 
	(
		hwnd = windows.getmaxhwnd()
		local WM_SETREDRAW = 0x000B
		windows.sendmessage hwnd WM_SETREDRAW act 1
	)
	fn findPairSeams src trg tolerance:0.001 = 
	(
		get_vert = polyop.getvert
		
		src_edgevertex = src.getedgevertex
		trg_edgevertex = trg.getedgevertex
		
		src_edges = polyop.getOpenEdges src
		trg_edges = polyop.getOpenEdges trg
		
		src_centers = for e in src_edges collect
		(
			v0 = src_edgevertex e 1
			v1 = src_edgevertex e 2
			s = (get_vert src v0 + get_vert src v0)/2
			s = s as point4
			s.w = e
			s
		)
		trg_centers = for e in trg_edges collect
		(
			v0 = trg_edgevertex e 1
			v1 = trg_edgevertex e 2
			s = (get_vert trg v0 + get_vert trg v0)/2
			s = s as point4
			s.w = e
			s
		)
		
		scr_targets = #()
		for s in src_centers do
		(
			found = off
			p0 = s as point3
			for k=1 to trg_centers.count while not found do
			(
				t = trg_centers[k]
				p1 = t as point3
				d = distance p0 p1
				if found = (d < tolerance) do
				(
					append scr_targets [s.w, t.w]
				)
			)
		)
		scr_targets
	)

		
	fn alignOpenNormals src trg tolerance:0.01 reset:on average:off = 
	(
		seams = findPairSeams src trg
		
		modi = Edit_Normals()
		setMaxWindowRedraw off
		
	--	addmodifier #(src, trg) modi
		select #(src, trg)
		modPanel.addModToSelection modi
		modi.setselection #{1..modi.getnumnormals node:src}
		if reset do modi.Reset node:src
		modi.Specify node:src
		modi.MakeExplicit node:src
		
		src_edgevertex = src.getedgevertex
		src_edgeface = src.getedgeface
		trg_edgeface = trg.getedgeface
		
		src_facedegree = src.getfacedegree
		trg_facedegree = trg.getfacedegree
		
		src_facevertex = src.getfacevertex
		trg_facevertex = trg.getfacevertex
		
		src_getvertex = src.getvertex
		trg_getvertex = trg.getvertex
		
		getvertex = polyop.getvert 
		
		get_normalid = modi.getNormalID
		
		get_normal = modi.getNormal
		set_normal = modi.setNormal
		
		set_explicit = modi.SetNormalExplicit 
		
		trg_mesh = trg.mesh
		
		data = #()
		in coordsys world for e in seams do 
		(
			src_face = src_edgeface e[1] 1
			trg_face = trg_edgeface e[2] 1
			
			snum = src_facedegree src_face
			tnum = trg_facedegree trg_face
			
			for k=1 to tnum do
			(
				ti = trg_facevertex trg_face k
				tp = getvertex trg ti
				for i=1 to snum do 
				(
					si = src_facevertex src_face i
					sp = getvertex src si
					d = distance tp sp

					if d < tolerance do
					(
						tid = get_normalid trg_face k node:trg
						sid = get_normalid src_face i node:src
						append data [sid, tid]
						
						normal = get_normal tid node:trg
						if average then
						(
							n = get_normal sid node:src
							normal = normalize ((normal + n)/2)
						)
						
						set_normal sid normal node:src
						
						set_explicit sid explicit:true node:src
					)
				)
			)
		)
		
		deleteModifier trg modi
		--collapsestack src
		converttopoly src
		clearselection()
		
		setMaxWindowRedraw on
		
		data
	)	
	
	fn polyFilter node = isvalidnode node and iskindof node Editable_Poly or iskindof node PolyMeshObject 
		
	group "Source: "
	(
		pickbutton source_bt "Pick A Source" width:172 align:#center filter:polyFilter autoDisplay:on
	)
	group "Target: "
	(
		pickbutton target_bt "Pick A Target" width:172 align:#center filter:polyFilter autoDisplay:on
	)
	group "Process: "
	(
		checkbox reset_ch "Reset" checked:off
		
		button execute_bt "Align Normals" width:172 align:#center
		on execute_bt pressed do undo "Align Normals" on
		(
			if polyFilter (source = source_bt.object) and polyFilter (target = target_bt.object) and source != target do
			(
				alignOpenNormals source target reset:reset_ch.state
			)
		)
	)
	on AlignSeamNormalsRol open do
	(
	)
)
createdialog AlignSeamNormalsRol

 

As I said above, the most difficult thing is to find pairs of normals for alignment in the general case. For high-resolution poly objects, this may take some time. There are kd-tree or octree approaches to speed things up. Me and other guys showed implementations on MXS and C#, and posted them on almost dead now CGTalk. But if you're lucky, you might be able to find them.

 

 

Message 14 of 15

denisT.MaxDoctor
Advisor
Advisor

perhaps I might have missed something... but the development of a 100% working tool was not my goal in itself.

0 Likes
Message 15 of 15

dmitriy.shpilevoy
Collaborator
Collaborator

Works like a charm! Thank you.

0 Likes