Alternative to WorldToScreen?
Moderators: Víctor Paredes, Belgarath, slowtiger
Alternative to WorldToScreen?
Hi. I'm trying to get a point always follow the exact position of another point in a different layer no matter what layer (or camera) transformations have been applied, IOW, like if they where "joined" across space, but since I need it to work from an embedded script I've no way to access functions like i.e. "LM_Graphics:WorldToScreen(pt, where)", due to as you know embedded scripts can not get access to any function dependent on view/LM_Graphics.
I think this is one of those things that would be super easy to solve if it weren't for that, but trying to figure out how it could be done by kind of inverse engineering and dealing with all the possible matrix transformations instead simply blows my head...
So to start with... does someone here think that is even possible? Or should I better try to get it out of my head? Well, thanks in advance for any help.
I think this is one of those things that would be super easy to solve if it weren't for that, but trying to figure out how it could be done by kind of inverse engineering and dealing with all the possible matrix transformations instead simply blows my head...
So to start with... does someone here think that is even possible? Or should I better try to get it out of my head? Well, thanks in advance for any help.
...
- hayasidist
- Posts: 3525
- Joined: Wed Feb 16, 2011 8:12 pm
- Location: Kent, England
Re: Alternative to WorldToScreen?
just to make sure I understand what you're asking...
for example:
layer 1 is not transformed in any way, and has a point at {0,0}
layer 2 is shifted to be at {-.6, -.3} so to be visually coincident with the layer 1 point, it would have to have a point at {.6, .3}
to generalise, then, in (say) layer 2 you want a layerscript that will find the layer 1 reference point(s) and shift layer 2's point(s) so they line up taking into account the layer transforms.
is that the idea?
for example:
layer 1 is not transformed in any way, and has a point at {0,0}
layer 2 is shifted to be at {-.6, -.3} so to be visually coincident with the layer 1 point, it would have to have a point at {.6, .3}
to generalise, then, in (say) layer 2 you want a layerscript that will find the layer 1 reference point(s) and shift layer 2's point(s) so they line up taking into account the layer transforms.
is that the idea?
- synthsin75
- Posts: 9975
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Re: Alternative to WorldToScreen?
Doesn't account for layer z-depth and doesn't stay aligned with XY rotation:
Testing with more than one point:
Code: Select all
function LayerScript(moho)
local layer, layer2 = moho:LayerAsVector(moho.layer), moho:LayerAsVector(moho.document:Layer(0))
local mesh, mesh2 = layer:Mesh(), layer2:Mesh()
local layerGlobal = AE_GetGlobalLayerMatrix(moho, layer, moho.frame)
local pt = mesh:Point(0)
local pt2 = mesh2:Point(0)
pt2.fPos = pt.fPos
layerGlobal:Transform(pt2.fPos)
end
-- **************************************************
-- Alexandra Evseeva @ http://ae.revival.ru/
-- http://www.lostmarble.com/forum/viewtopic.php?p=196232#p196232
-- http://mohoscripts.com/script/ae_utilities
-- **************************************************
function AE_GetGlobalLayerMatrix(moho, layer, frame)
local prevMatrix = LM.Matrix:new_local()
prevMatrix:Identity()
local nextLayer = layer
repeat
local prevLayer = nextLayer
local matrix = LM.Matrix:new_local()
nextLayer:GetLayerTransform(frame, matrix, moho.document)
matrix:Multiply(prevMatrix)
prevMatrix:Set(matrix)
if nextLayer:Parent() then nextLayer = nextLayer:Parent() end
until nextLayer == prevLayer
local cameraMatrix = LM.Matrix:new_local()
moho.document:GetCameraMatrix(frame, cameraMatrix)
cameraMatrix:Invert()
cameraMatrix:Multiply(prevMatrix)
return cameraMatrix
end
-- **************************************************
Code: Select all
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 layerGlobal = AE_GetGlobalLayerMatrix(moho, layer, moho.frame)
local pt = mesh:Point(i)
local pt2 = mesh2:Point(i)
pt2.fPos = pt.fPos
layerGlobal:Transform(pt2.fPos)
end
- Wes
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Re: Alternative to WorldToScreen?
Thanks for the responses, guys. I'll try to clarify as much as much as I can with words, but I think/hope the testing file be more eloquent...
It relays on Layer's and Point's IDs, and only works over one point (left side of the neck) for simplicity and quick testing, the idea is to work over named point groups for easy setup and flexibility, but all that would come later. Well, as you can see by playing (or directly manipulating XY rotation of HEAD layer for example), as long as there are no camera or layer transforms (frame 0 to 50) the slave point follows master point as expected and without gaps (there is a little Line Width mismatching but that's another issue), but as soon as camera or layer is translated (so 3D perspective comes into play) the slave point doesn't remain "joined" anymore... I've been tryin to apply camera matrix in different ways without success yet, but I'm afraid even I got counteract camera displacements, I would still get gaps due to layer transformations, and very specially XY rotations. But, OTOH, something tells me that there must be a way to get a certain vector position in a layer and subtract every layer and/or camera transformation since there is access to all the involved matrices after all, isn't it? Or maybe a way to somehow fake the longed WorldToScreen/ScreenToWorld methods? Who knows... but, well, I hope so
Well, if that assumption was for simplifying reasons I think I understand, but Layer 1 (o master layer) would be indeed transformed in almost all ways, and points would be at any point (although, for the use I have in mind at least, not too far from layer's Origin).hayasidist wrote: ↑Mon Jan 10, 2022 9:57 pm layer 1 is not transformed in any way, and has a point at {0,0}
Yes, but I think what is causing the gaps when layer/camera transformations take place is preciselly the fact that the affected points are indeed not at [0, 0]. I mean, it seems easy to get the layer's Origin full matrix transformation, but as soon as you try to apply it to a displaced point's position is where things seems to start mismatching if there are any camera or layer transforms.hayasidist wrote: ↑Mon Jan 10, 2022 9:57 pm layer 2 is shifted to be at {-.6, -.3} so to be visually coincident with the layer 1 point, it would have to have a point at {.6, .3}
I do need z-depth and (very specially) XY rotation, but thanks. Indeed I already tried to study some of the A.Evseeva scripts, but I admit they exceed my matrices understanding among other things... Although thanks to it and some trial an error I got a very basic starting point:synthsin75 wrote: ↑Mon Jan 10, 2022 11:03 pm Doesn't account for layer z-depth and doesn't stay aligned with XY rotation:
It relays on Layer's and Point's IDs, and only works over one point (left side of the neck) for simplicity and quick testing, the idea is to work over named point groups for easy setup and flexibility, but all that would come later. Well, as you can see by playing (or directly manipulating XY rotation of HEAD layer for example), as long as there are no camera or layer transforms (frame 0 to 50) the slave point follows master point as expected and without gaps (there is a little Line Width mismatching but that's another issue), but as soon as camera or layer is translated (so 3D perspective comes into play) the slave point doesn't remain "joined" anymore... I've been tryin to apply camera matrix in different ways without success yet, but I'm afraid even I got counteract camera displacements, I would still get gaps due to layer transformations, and very specially XY rotations. But, OTOH, something tells me that there must be a way to get a certain vector position in a layer and subtract every layer and/or camera transformation since there is access to all the involved matrices after all, isn't it? Or maybe a way to somehow fake the longed WorldToScreen/ScreenToWorld methods? Who knows... but, well, I hope so
Last edited by Rai López on Tue Jan 11, 2022 2:42 am, edited 1 time in total.
...
- synthsin75
- Posts: 9975
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Re: Alternative to WorldToScreen?
I think I've suggested MohoView:Point2Vec(where, layerM) as an alternative to WorldToScreen before. Don't know if it would help in this instance, off hand.
EDIT: No, doesn't look like layerscripts have access to moho.view.
EDIT: No, doesn't look like layerscripts have access to moho.view.
- Wes
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Re: Alternative to WorldToScreen?
I thought about that at some point, too... but sadly we would be in the same, since it depends on LM_Graphics/MohoView as wellsynthsin75 wrote: ↑Tue Jan 11, 2022 2:42 am I think I've suggested MohoView:Point2Vec(where, layerM) as an alternative to WorldToScreen before. Don't know if it would help in this instance, off hand.
EDIT: Yeah... Clearly, the best outcome here is we could have access to moho.view from embedded scripts (an old dream), but that's how things are...
...
- synthsin75
- Posts: 9975
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Re: Alternative to WorldToScreen?
Not perfect, but this almost handles XY rotation:
Code: Select all
function LayerScript(moho, view)
local layer, layer2 = moho:LayerAsVector(moho.layer), moho:LayerAsVector(moho.document:Layer(0))
local mesh, mesh2 = layer:Mesh(), layer2:Mesh()
local rotX = layer.fRotationX
local rotY = layer.fRotationY
for i = 0, 1 do
local layerGlobal = AE_GetGlobalLayerMatrix(moho, layer, moho.frame)
local pt = mesh:Point(i)
local pt2 = mesh2:Point(i)
pt2.fPos = pt.fPos
layerGlobal:Rotate(0, rotX)
layerGlobal:Rotate(1, rotY)
layerGlobal:Transform(pt2.fPos)
end
end
- Wes
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
- synthsin75
- Posts: 9975
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Re: Alternative to WorldToScreen?
But if you remove the camera matrix, it also handles z-translation:
Removing the camera matrix also makes XY rotation accurate.
EDIT: Don't need to append the x and y rotations without the camera matrix.
Code: Select all
function LayerScript(moho, view)
local layer, layer2 = moho:LayerAsVector(moho.layer), moho:LayerAsVector(moho.document:Layer(0))
local mesh, mesh2 = layer:Mesh(), layer2:Mesh()
local rotX = layer.fRotationX
local rotY = layer.fRotationY
for i = 0, 1 do
local layerGlobal = AE_GetGlobalLayerMatrix(moho, layer, moho.frame)
local pt = mesh:Point(i)
local pt2 = mesh2:Point(i)
pt2.fPos = pt.fPos
--layerGlobal:Rotate(0, rotX)
--layerGlobal:Rotate(1, rotY)
layerGlobal:Transform(pt2.fPos)
end
end
-- **************************************************
-- Alexandra Evseeva @ http://ae.revival.ru/
-- http://www.lostmarble.com/forum/viewtopic.php?p=196232#p196232
-- http://mohoscripts.com/script/ae_utilities
-- **************************************************
function AE_GetGlobalLayerMatrix(moho, layer, frame)
local prevMatrix = LM.Matrix:new_local()
prevMatrix:Identity()
local nextLayer = layer
repeat
local prevLayer = nextLayer
local matrix = LM.Matrix:new_local()
nextLayer:GetLayerTransform(frame, matrix, moho.document)
matrix:Multiply(prevMatrix)
prevMatrix:Set(matrix)
if nextLayer:Parent() then nextLayer = nextLayer:Parent() end
until nextLayer == prevLayer
--[=[
local cameraMatrix = LM.Matrix:new_local()
moho.document:GetCameraMatrix(frame, cameraMatrix)
cameraMatrix:Invert()
cameraMatrix:Multiply(prevMatrix)
return cameraMatrix
--]=]
return prevMatrix
end
-- **************************************************
EDIT: Don't need to append the x and y rotations without the camera matrix.
Last edited by synthsin75 on Tue Jan 11, 2022 4:06 am, edited 1 time in total.
- Wes
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Re: Alternative to WorldToScreen?
Hmm... So do you think not all the transformations can be obtained by means of involved transformation matrices? I also started to have my doubts abou that, but I hoped not have to deal with separated values because matices sounded to me like the most straightforward and precise way... But anyway I'll take a look to it tomorrow, of course. Thanks!
...
Re: Alternative to WorldToScreen?
Crossed post... Really?? Then really I can't wait to try it out tomorrow and see! Thanks (THANKS) again!synthsin75 wrote: ↑Tue Jan 11, 2022 3:32 am Removing the camera matrix also makes XY rotation accurate.
...
- synthsin75
- Posts: 9975
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Re: Alternative to WorldToScreen?
Yeah, it works perfectly for z-translation, XY rotation, and layer shear, but the downside is that it breaks with any camera animation.
Don't know if that can be done as well.
Don't know if that can be done as well.
- Wes
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
- synthsin75
- Posts: 9975
- Joined: Mon Jan 14, 2008 11:20 pm
- Location: Oklahoma
- Contact:
Re: Alternative to WorldToScreen?
Way simpler version of the above:
Code: Select all
function LayerScript(moho)
local doc = moho.document
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 matrix = LM.Matrix:new_local()
layer:GetFullTransform(moho.frame, matrix, doc)
matrix:Transform(pt2.fPos)
end
end
- Wes
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Donations: https://www.paypal.com/paypalme/synthsin75 (Thx, everyone.)
https://www.youtube.com/user/synthsin75
Scripting reference: https://mohoscripting.com/
Re: Alternative to WorldToScreen?
Hi again! I've tried the three versions but, sadly, none of them seem to work to me as soon as any camera OR layer translations take place... It's easy to see this by means of the testing Moho file from my first post if you put A.Evseeva's function first of all and simply change these lines of your codes:
I hope I'm not missing something, but I always get some kind of different point position mismatching from frame 50 on if I try, for example, this:
No matter if I uncomment and return from the function cameraMatrix instead prevMatrix or both, multiply them or whatever... I'm starting to think all this could be (even) trickier than expected and I wonder if shouldn't I start thinking another approaches? But to can turn the page, it's important to me try to use up all the bullets this way before ruling out because in theory (if it worked) it would bring the most perfect results under all circumstances, so for now I think I'll continue trial-and-erroring a little more with all these ma(d)trices thing
Code: Select all
local layer, layer2 = moho.document:LayerByAbsoluteID(4), moho.document:LayerByAbsoluteID(2)
local mesh, mesh2 = moho:LayerAsVector(layer):Mesh(), moho:LayerAsVector(layer2):Mesh()
local rotX = layer:Parent().fRotationX
local rotY = layer:Parent().fRotationY
for i = 1, 1 do
I hope I'm not missing something, but I always get some kind of different point position mismatching from frame 50 on if I try, for example, this:
Code: Select all
function LayerScript(moho)
-- **************************************************
-- Alexandra Evseeva @ http://ae.revival.ru/
-- http://www.lostmarble.com/forum/viewtopic.php?p=196232#p196232
-- http://mohoscripts.com/script/ae_utilities
-- **************************************************
function AE_GetGlobalLayerMatrix(moho, layer, frame)
local prevMatrix = LM.Matrix:new_local()
prevMatrix:Identity()
local nextLayer = layer
repeat
local prevLayer = nextLayer
local matrix = LM.Matrix:new_local()
nextLayer:GetLayerTransform(frame, matrix, moho.document)
matrix:Multiply(prevMatrix)
prevMatrix:Set(matrix)
if nextLayer:Parent() then nextLayer = nextLayer:Parent() end
until nextLayer == prevLayer
--[=[
local cameraMatrix = LM.Matrix:new_local()
moho.document:GetCameraMatrix(frame, cameraMatrix)
cameraMatrix:Invert()
cameraMatrix:Multiply(prevMatrix)
return cameraMatrix
--]=]
return prevMatrix
end
-- **************************************************
local layer, layer2 = moho.document:LayerByAbsoluteID(4), moho.document:LayerByAbsoluteID(2)
local mesh, mesh2 = moho:LayerAsVector(layer):Mesh(), moho:LayerAsVector(layer2):Mesh()
local rotX = layer:Parent().fRotationX
local rotY = layer:Parent().fRotationY
for i = 1, 1 do
local layerGlobal = AE_GetGlobalLayerMatrix(moho, layer, moho.frame)
local pt = mesh:Point(i)
local pt2 = mesh2:Point(i)
pt2.fPos = pt.fPos
--layerGlobal:Rotate(0, rotX)
--layerGlobal:Rotate(1, rotY)
layerGlobal:Transform(pt2.fPos)
end
end
No matter if I uncomment and return from the function cameraMatrix instead prevMatrix or both, multiply them or whatever... I'm starting to think all this could be (even) trickier than expected and I wonder if shouldn't I start thinking another approaches? But to can turn the page, it's important to me try to use up all the bullets this way before ruling out because in theory (if it worked) it would bring the most perfect results under all circumstances, so for now I think I'll continue trial-and-erroring a little more with all these ma(d)trices thing
Last edited by Rai López on Tue Jan 11, 2022 3:20 pm, edited 1 time in total.
...
- hayasidist
- Posts: 3525
- Joined: Wed Feb 16, 2011 8:12 pm
- Location: Kent, England
Re: Alternative to WorldToScreen?
Take a look at this:
http://www.lostmarble.com/forum/viewtop ... 9&p=180070
My "bake vector" script takes all the points in a vector layer and applies all the transforms to them so that the resulting position is as though there were no transforms - i.e. all the layer / bone / camera actions are wiped out but the points are left VISUALLY where they were. (see "local function bakeVector" in the .LUA)
to do this, I convert the vec2 that is fPos to a vec3 - and its the vec3 that needs to be the subject of the matrix transform - which is then converted back to a vec2 using some fairly straightforward maths to project the vec3 onto the plane that is the vector layer.
===
I have not gone any further than thinking about what I'm about to describe, so please treat it as me thinking out loud...
What is, I think, needed is as you've done - to find the "difference" between the master and slave transform matrices and use that where I've used just the layer transform.
And, just in case you're not aware, matrix multiplication is not commutative - IOW A:Mult(B) is not the same as B:Mult(A)
The bottom line of all that is that I'm not sure whether the matrix you want is
Slave:Invert()
Slave:Mult(Master)
or
Master:Invert
Master:Mult(Slave)
or
Slave:Invert()
Master:Mult(Slave)
or
Master:Invert
Slave:Mult(Master)
==
hope that is at least stepping forward....
http://www.lostmarble.com/forum/viewtop ... 9&p=180070
My "bake vector" script takes all the points in a vector layer and applies all the transforms to them so that the resulting position is as though there were no transforms - i.e. all the layer / bone / camera actions are wiped out but the points are left VISUALLY where they were. (see "local function bakeVector" in the .LUA)
to do this, I convert the vec2 that is fPos to a vec3 - and its the vec3 that needs to be the subject of the matrix transform - which is then converted back to a vec2 using some fairly straightforward maths to project the vec3 onto the plane that is the vector layer.
===
I have not gone any further than thinking about what I'm about to describe, so please treat it as me thinking out loud...
What is, I think, needed is as you've done - to find the "difference" between the master and slave transform matrices and use that where I've used just the layer transform.
And, just in case you're not aware, matrix multiplication is not commutative - IOW A:Mult(B) is not the same as B:Mult(A)
The bottom line of all that is that I'm not sure whether the matrix you want is
Slave:Invert()
Slave:Mult(Master)
or
Master:Invert
Master:Mult(Slave)
or
Slave:Invert()
Master:Mult(Slave)
or
Master:Invert
Slave:Mult(Master)
==
hope that is at least stepping forward....
Re: Alternative to WorldToScreen?
This all sounds very interesting, hayasidist! At some point passed through my mind try to somehow include vec3 into the equation, but I didn't now even where to start off, so I'll study your script as soon as possible and see...
Yeah, I think I kinda imagined that, but I must admit for all the other things I have to play trial and error almost all the time because matrix interaction concepts are beyond my capabilities (I got kind of used to it when I worked on some tools that drew a lot of widgets in viewport, but that simply was too long ago...), I mean, for example, I use :Invert() and :Multiply() because I imagine it's the way to counteract upper/inner layer transformations to avoid unwanted feedbacks, but I'm not totally sure about the involved math and what it really does under the hood (OK: IHaveNoIdeaWhatI'mDoingDogWithTie.jpg)hayasidist wrote: ↑Tue Jan 11, 2022 3:19 pm And, just in case you're not aware, matrix multiplication is not commutative - IOW A:Mult(B) is not the same as B:Mult(A)
Yeah, I think try to use that "difference" and get they somehow cancel each other, is more or less what I've always had in mind about this subject, but not taking into account real point's position in vec3 well could be the key of getting unwanted point translations when they are not at [0, 0]. So let's see what I can get once/if I'm able to apply all this... Thanks!hayasidist wrote: ↑Tue Jan 11, 2022 3:19 pm What is, I think, needed is as you've done - to find the "difference" between the master and slave transform matrices and use that where I've used just the layer transform.
...