Alternative to WorldToScreen?

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Alternative to WorldToScreen?

Post by synthsin75 »

Following Paul's bake script, this now works for layer transforms, XY rotation, shear, and camera.
https://www.mediafire.com/file/hye23wwv ... t.zip/file

Thanks, Paul!!

Code: Select all

function LayerScript(moho)
	local doc, frame = moho.document, moho.frame
	local layer, layer2 = moho:LayerAsVector(moho.layer), moho:LayerAsVector(moho.document:Layer(0))
	local mesh, mesh2 = layer:Mesh(), layer2:Mesh()
	
	for i = 0, 1 do
		local pt = mesh:Point(i)
		local pt2 = mesh2:Point(i)
		pt2.fPos = pt.fPos
		
		local m = LM.Matrix:new_local()
		local cam = LM.Matrix:new_local()
		
		local camPos = LM.Vector3:new_local()
		
		local vec3 = LM.Vector3:new_local()
		
		local deltaX, deltaY
		
		camPos = moho.document.fCameraTrack:GetValue(frame)
		
		layer:GetFullTransform(frame, m, doc)
		
		m:Invert()
		doc:GetCameraMatrix(frame, cam)
		m:Multiply(cam)
		m:Invert()
		
		vec3:Set(pt2.fPos.x, pt2.fPos.y, 0)
		
		m:Transform(vec3)
		
		deltaX = (vec3.z) * (vec3.x - camPos.x) / (vec3.z - camPos.z)
		deltaY = (vec3.z) * (vec3.y - camPos.y) / (vec3.z - camPos.z)
		
		pt2.fPos.x = vec3.x - deltaX
		pt2.fPos.y = vec3.y - deltaY
	end
end
User avatar
Rai López
Posts: 2243
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: Alternative to WorldToScreen?

Post by Rai López »

synthsin75 wrote: Tue Jan 11, 2022 4:43 pm

Code: Select all

function LayerScript(moho)
	local doc, frame = moho.document, moho.frame
	local layer, layer2 = moho.document:LayerByAbsoluteID(4), moho.document:LayerByAbsoluteID(2)
	local mesh, mesh2 = moho:LayerAsVector(layer):Mesh(), moho:LayerAsVector(layer2):Mesh()
	
	for i = 1, 1 do
		local pt = mesh:Point(i)
		local pt2 = mesh2:Point(i)
		pt2.fPos = pt.fPos
		
		local m = LM.Matrix:new_local()
		local cam = LM.Matrix:new_local()
		
		local camPos = LM.Vector3:new_local()
		
		local vec3 = LM.Vector3:new_local()
		
		local deltaX, deltaY
		
		camPos = moho.document.fCameraTrack:GetValue(frame)
		
		layer:GetFullTransform(frame, m, doc)
		
		m:Invert()
		doc:GetCameraMatrix(frame, cam)
		m:Multiply(cam)
		m:Invert()
		
		vec3:Set(pt2.fPos.x, pt2.fPos.y, 0)
		
		m:Transform(vec3)
		
		deltaX = (vec3.z) * (vec3.x - camPos.x) / (vec3.z - camPos.z)
		deltaY = (vec3.z) * (vec3.y - camPos.y) / (vec3.z - camPos.z)
		
		pt2.fPos.x = vec3.x - deltaX
		pt2.fPos.y = vec3.y - deltaY
	end
end
This is also great, synthsin! I've not had time yet to really study all that Paul's code, but for the first time I'm seeing an advance here (maybe I did something wrong with your other pieces of code, but applying it to the moho testing file I said I was not able to see differences on them). Now, this code is working to me at least under two scenarios, when there is no layer nor camera translation, as always, BUT also when any camera translations applies! Which seems simply magic :D

Unfortunately, it seems to still fail when parent layer transformations take place as can bee seen from frame 100 till the end, but maybe this is only a matter of going up hierarchy layer per layer subtracting/counteracting matices so that their sum stops creating points motion feedback (for the way they overreact, like summing up each parent layers transforms). I have to leave now, but I'll study both codes as soon as posible and I'll try to understand the involved math... In any case, this makes me think again this well could be the way to go. What more can I say, a big THANK YOU to both!

EDIT: Oh, I didn't see you included your own testing file, sorry! The code I quoted was adapted to mine (the one I linked in my second post). I'll test it with yours as soon as posible too, of course. Thanks again!
...
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Alternative to WorldToScreen?

Post by synthsin75 »

Yeah, the last code I posted works for everything, including parent layer transforms. Haven't had time to adapt it to use with your file, Ramon.
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Alternative to WorldToScreen?

Post by synthsin75 »

Okay, I couldn't let this go, so I've done even more. At first, I was thinking of using point groups to match up points, but that would be a pain to setup. Then I thought of writing a tool to match up points in the workspace. But I settled on any points that are within 0.009 of each other on frame zero automatically being stitched together. Works pretty good, but doesn't handle if the controlled layer has any parent or layer transforms...or if the controlling layer has layer transforms on frame zero:

Code: Select all

-- **************************************************
-- Syn_Stitch_Points
-- (c)2022 J.Wesley Fowler (synthsin75)
-- **************************************************
function LayerScript(moho)
	if (not moho:LayerAsVector(moho.layer)) then
		moho.layer:SetLayerScript("")
		print("Syn_Stitch_Points must be embedded on a vector layer \n".."The layerscript has been removed from layer: \""..moho.layer:Name().."\"")
		return
	end
	local m, cam, vec3
	for i = 0, math.huge do
		if (not moho.document:LayerByAbsoluteID(i)) then
			break
		end
		if (moho.document:LayerByAbsoluteID(i) ~= moho.layer and
		 moho.document:LayerByAbsoluteID(i):LayerType() == MOHO.LT_VECTOR) and (moho.frame > 0) then
			for j = 0, moho:Mesh():CountPoints()-1 do
				for k = 0, moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh():CountPoints()-1 do
					
					if (math.abs(moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh():Point(k)
					 .fAnimPos:GetValue(0).x - moho:Mesh():Point(j).fAnimPos:GetValue(0).x) < 0.009) and
					 (math.abs(moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh():Point(k)
					 .fAnimPos:GetValue(0).y - moho:Mesh():Point(j).fAnimPos:GetValue(0).y) < 0.009) then
						
						moho:LayerAsVector(moho.document:LayerByAbsoluteID(i))
						:Mesh():Point(k).fPos = moho:Mesh():Point(j).fPos
						
						m = LM.Matrix:new_local()
						cam = LM.Matrix:new_local()
						vec3 = LM.Vector3:new_local()
						
						moho.layer:GetFullTransform(moho.frame, m, moho.document)
						
						m:Invert()
						moho.document:GetCameraMatrix(moho.frame, cam)
						m:Multiply(cam)
						m:Invert()
						
						vec3:Set(moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh()
						 :Point(k).fAnimPos:GetValue(0).x, 
						 moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh()
						 :Point(k).fAnimPos:GetValue(0).y, 0)
						
						m:Transform(vec3)
						
						moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh():Point(k).fPos.x = vec3.x - ((vec3.z) *
						 (vec3.x - moho.document.fCameraTrack:GetValue(moho.frame).x) /
						 (vec3.z - moho.document.fCameraTrack:GetValue(moho.frame).z))
						moho:LayerAsVector(moho.document:LayerByAbsoluteID(i)):Mesh():Point(k).fPos.y = vec3.y - ((vec3.z) *
						 (vec3.y - moho.document.fCameraTrack:GetValue(moho.frame).y) /
						 (vec3.z - moho.document.fCameraTrack:GetValue(moho.frame).z))
					end
				end
			end
		end
	end
end

I also used as few variables as possible, in the hope that it would help performance. Don't know if that's worth making it harder to read though.
Still more to do.
User avatar
Greenlaw
Posts: 9269
Joined: Mon Jun 19, 2006 5:45 pm
Location: Los Angeles
Contact:

Re: Alternative to WorldToScreen?

Post by Greenlaw »

As a user who only occasionally dabbles in scripting, it was super cool watching how this one quickly evolved in the hands of experts.

Thanks for sharing guys! This thread is inspiring as well as educational! 😺
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Alternative to WorldToScreen?

Post by synthsin75 »

:D

Still too many exceptions to consider it anywhere near done.
Fun to play with though.
User avatar
hayasidist
Posts: 3526
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Alternative to WorldToScreen?

Post by hayasidist »

really sorry I can't devote more time to this right now ... I'm up to my ears in other stuff!
synthsin75 wrote: Wed Jan 12, 2022 2:10 am At first, I was thinking of using point groups to match up points, but that would be a pain to setup. Then I thought of writing a tool to match up points in the workspace. But I settled on any points that are within 0.009 of each other on frame zero automatically being stitched together.
ok - so you decided against it, but ... a thought for setting up associations:

Wes came up with the idea of having a layerscript as a string held in a tool / menu script http://www.lostmarble.com/forum/viewtop ... 67#p185964

so rather than the layerscript searching out associations [run-time expensive], this is maybe something that can be done once so the "set up tool" creates a string defining arrays of mesh point ids in the master and slave layers
e.g.

Code: Select all

--
-- UNTESTED  VERY INCOMPLETE  so not directly usable ... but the principle, I think, is sound
-- ===========================
--
local mPts = "local MasterPoints = {" 
local sPts = "local SlavePoints = "{" -- could have multiple slave layers???!!! (secondary selections)
for i = 0, masterMesh:CountPoints-1 do
	if <choice criterion> -- e.g. fSelected then
		mPts = mPts .. tostring(i) .. ","
		<find the corresponding slave point -- call it j> 
		sPts = "SlavePoints = "{" .. tostring(j) .. ","
	end
end
mPts = mPts:sub(1,mPts:len()-1) .. "}" -- replace the last "," with closing array }
sPts = sPts:sub(1,sPts:len()-1) .. "}" 

local layerScript = 
[[function LayerScript(moho)
]] .. mPts .. "/n ".. sPts .. "/n"
[[--code body
for i = 1, #mPts do
	-- etc
end
]]
-- write the layerscript file to (e.g.) custom directory, and embed it in the right layer(s) 
User avatar
Rai López
Posts: 2243
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: Alternative to WorldToScreen?

Post by Rai López »

WOW! That is definitely a great step with usability terms in mind, Wes. I've been all the time so worried about if the foundations was possible that didn't think too much beyond that, and named point groups, although sounded a little cumbersome to setup to me too, seemed enough for the personal use I had in mind at least, where normally only a few points was going to really require setup. But the frame 0 setup is far better than that in all senses and would open the tool to much more complex uses if necessary. Good point too, Paul! About creating tables instead going through each point all the time and something that was going to be considered at some point, so thank you very much to you too for that advance.

Well, about those foundations... I've been not able to get any real progress with the parent layers transforms issue, but the fact that Paul's Bake script seems to be able to manage all that in base of the tests I've done, tells me that the answer is simply awaiting to be seen right there, so I'll continue just studying that code for now. But now that, taking apart the current limitations and issues, I can see it almost fully working real time and all (I mean, not only in my mind :lol:), don't you think it's simply great can count with the possibility of elastically join totally independent/separated elements this way?? I mean, Moho has been always good on this, but with limitations and not being able to really work unattendedly, specially if any perspective or layer/camera transform came into play... It somehow starts reminding me to a Toom Boom effect that always called my attention named: Glue, but not sure if it truly glued 3D transformed elements, so maybe this is even better? :)

And well I'm not saying this is super revolutionary or something so, because it might not be for everyone (or, precisely, it may depend on how intuitive/simple will finally the setup process result), but I do think having this possibility will open the door to a lot of 2.5D possibilities that I've always wanted to go through. Well, time to continue trial-erroring...
Last edited by Rai López on Wed Jan 12, 2022 2:41 pm, edited 1 time in total.
...
User avatar
Víctor Paredes
Site Admin
Posts: 5665
Joined: Wed Jan 26, 2005 12:18 am
Location: Barcelona/Chile
Contact:

Re: Alternative to WorldToScreen?

Post by Víctor Paredes »

This is extremely interesting.
Do you have any ideas/examples about where to use it?
Image Image Image Image
Moho Product Manager

www.mohoanimation.com
Rigged animation supervisor in My father's dragon - Lead Moho artist in Wolfwalkers - Cartoon Saloon - My personal Youtube Channel
User avatar
Rai López
Posts: 2243
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: Alternative to WorldToScreen?

Post by Rai López »

Víctor Paredes wrote: Wed Jan 12, 2022 2:35 pm This is extremely interesting.
Do you have any ideas/examples about where to use it?
Thanks for the interest, Víctor! Personally, the main use I've always had in mind is what you can basically see in the simple testing file from my second post, but just because that "flat" 3D head turns is something I've always wanted for my kinda simple characters. Of course in this case you cannot see the final result yet because, for a complete head turn at least, that would require both controlled points of the neck get somehow switched each other at the point "HEAD" layer Y rotation gets flipped respect camera (still thinking on how to solve such problem, but there are enough open issues already to go anticipating more of them :roll:). The good thing about all this is, once/if it worked under all scenarios, there would be no limit in how this kind of smooth and "shapeless" characters could be designed, the thickness of the neck/head in this case, the position respect body... or character's shape in general no mater how crazy it be. In theory, it should always work perfectly joined no-matter-what and under any 3D transformation.

Another uses I can think are, i.e., limbs where you also could freely play with perspective or 3D rotations while they remain (smoothly or not) joined, and that kind of uses would not require the extra complexity of switching controlled points (which I admit is like a very personal requirement). Although seeing it working now, I'm also start thinking if couldn't it be useful too for constructing/faking kinda complex 3D designs (I mean, more complex at least than a simple cube or similar, for example) which points could be freely animated while everything remain smooth and joined... Hmm, but simply thinking out loud for now!
Last edited by Rai López on Wed Jan 12, 2022 5:39 pm, edited 1 time in total.
...
User avatar
synthsin75
Posts: 9979
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: Alternative to WorldToScreen?

Post by synthsin75 »

Víctor Paredes wrote: Wed Jan 12, 2022 2:35 pm Do you have any ideas/examples about where to use it?
I imagine it could be used to fake 3D with 2D vectors or tie a complex design together, like hair that has to go from behind the head to over the front of a shoulder (stuff we'd usually have to use a reference of the entire layer for, and just remove the irrelevant shapes).
Daxel
Posts: 996
Joined: Wed Mar 27, 2019 8:34 pm

Re: Alternative to WorldToScreen?

Post by Daxel »

I wasn't understanding anything so I checked the file and now I get it. I think it's very useful indeed.
It's easy to see what the script is doing checking the file, but is not easy to explain.
It's an embedded script that allows you to control specific points of a shape moving points of other shape that are on the same position but on a different layer.

In practice, it's similar to using reference layers because you can control the position of points that are on a different layer. I find it useful specially when dealing with certain layer order limitations, like we can do with references.

For example: you create a drawing of an element, like a scarf. Of course you need it to be in front of the neck, but also behind the neck. You can create a scarf_front layer and a scar_back layer, but because we may find esier to animate the scarf as if those two parts were connected, with its points connected, we may want to have just one scarf layer with two shapes connected, the front and back shape, and to make the back appear behind the neck we can create a reference on top and change the transparency of the shapes if we need to. With this embedded script we can do something similar but without the complications that sometimes arise using reference layers, and without having to deal with the transparency of shapes. We can have the points that we need conected between different layers, just connected by this script. I'm sure I could find many more uses with time, and I'm not sure if I understand how Ramón López wants to use it.
User avatar
hayasidist
Posts: 3526
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Alternative to WorldToScreen?

Post by hayasidist »

Ramón López wrote: Wed Jan 12, 2022 2:23 pm with the possibility of elastically join totally independent/separated elements this way??
.. so master moves from a to b over time t; and slave's response is a progression (potentially non-linear) and not necessarily over the same time period...???? Is that what you mean??

If so, [famous last words] dead easy (in theory :D )

what we have now is slave point's position = fIdentity(master point pos, time) --- but there's no actual function because we just use Pos(s) = Pos(m) for all frames

and what we want is a different function - say fElastic - that calculates Pos(s) at the given frame using (again for example) a "standard" PID control algorithm that looks at Pos(m) over a range of frames. ... and that could make Pos(s) do all sorts of things in response to motion in Pos(m)

for example if Pos(m) is the blue line - step function; then Pos(s) can follow any of the other curves (and ones that aren't in the following diagram) by tweaking the PID parameters

Image

Intellectually totally straightforward .. (don't get put off by the look of the maths in the linked article!) .. ought to be codable in LUA .. even more so if we adopt the config tool approach to write the layerscipt with hard coded data
User avatar
Rai López
Posts: 2243
Joined: Sun Aug 08, 2004 1:41 pm
Location: Spain
Contact:

Re: Alternative to WorldToScreen?

Post by Rai López »

hayasidist wrote: Wed Jan 12, 2022 8:18 pm
Ramón López wrote: Wed Jan 12, 2022 2:23 pm with the possibility of elastically join totally independent/separated elements this way??
.. so master moves from a to b over time t; and slave's response is a progression (potentially non-linear) and not necessarily over the same time period...???? Is that what you mean??

[...]

and what we want is a different function - say fElastic - that calculates Pos(s) at the given frame using (again for example) a "standard" PID control algorithm that looks at Pos(m) over a range of frames. ...

Just to clarify, when I talked with terms like elasticity and smoothness, I was only referring to make use of the old Moho technique of adding a "tail point" to the end of a curve so that you can move that point and affect the curvature of its neighbor in order to get fluid continuity between two different curves and, therefore, shapes (it's a well known technique but I don't know if I expressed myself well enough :roll:). Anyway, it can be seen, because (although they are not linked yet due to the state of the script) that's why I added such tail points to the neck points of my testing file, because the idea is those points can also be linked to the ones matching position in the other layer to guarantee as smoother curves transition as possible even under 3D layer rotations or point/shape animations.

So, well, I'm afraid I'm totally lost about all that info and graph... sorry if it sounded like something more sophisticated than it really was 😅
...
User avatar
hayasidist
Posts: 3526
Joined: Wed Feb 16, 2011 8:12 pm
Location: Kent, England

Re: Alternative to WorldToScreen?

Post by hayasidist »

Ramón López wrote: Thu Jan 13, 2022 1:33 am Just to clarify, when I talked with terms like elasticity and smoothness ...
Ah! I had read that as referring to interpolation types elastic and smooth ... No worries...

I've not dived deeply into "keeping the line neatly curved" when what you're moving (directly or as a slave) are endpoints (on different layers just to make things harder) ... But (doing a manual test) it looks as though it can be done by adjusting the bezier handle on each of the end points
Post Reply