JHN

09-21-2010, 10:08 AM

Is there an existing way to lerp between 2 matrix values or do I have to decompose the PRS values, (s)lerp them and rebuilt the matrix each step?

Thanks,

-Johan

Thanks,

-Johan

View Full Version : Lerp for matrix3 values

JHN 09-21-2010, 10:08 AM Is there an existing way to lerp between 2 matrix values or do I have to decompose the PRS values, (s)lerp them and rebuilt the matrix each step? Thanks, -Johan |

JHN

09-21-2010, 11:36 AM

Found a thread about it : http://forums.cgsociety.org/showthread.php?f=98&t=859470

Thanks,

-Johan

Thanks,

-Johan

MatanH

09-21-2010, 11:59 AM

Just saw your 2nd post but I'll post my solution anyhow..

(

fn lerp matArray weights =

(

local resMat = matrix3 [0,0,0] [0,0,0] [0,0,0] [0,0,0]

for i = 1 to matArray.count do (

local w = weights[i]

local intMat = matrix3 [w,0,0] [0,w,0] [0,0,w] [w,w,w]

resMat += matArray[i] * intMat

)

resMat

)

if selection.count == 3 then (

local a = $[1]

local b = $[2]

local c = $[3]

local d = copy a

d.transform = lerp #(a.transform, b.transform, c.transform) #(0.5, 0.5, 0.5)

) else

messageBox "Please select 3 objects!"

)

(

fn lerp matArray weights =

(

local resMat = matrix3 [0,0,0] [0,0,0] [0,0,0] [0,0,0]

for i = 1 to matArray.count do (

local w = weights[i]

local intMat = matrix3 [w,0,0] [0,w,0] [0,0,w] [w,w,w]

resMat += matArray[i] * intMat

)

resMat

)

if selection.count == 3 then (

local a = $[1]

local b = $[2]

local c = $[3]

local d = copy a

d.transform = lerp #(a.transform, b.transform, c.transform) #(0.5, 0.5, 0.5)

) else

messageBox "Please select 3 objects!"

)

denisT

09-21-2010, 12:02 PM

Is there an existing way to lerp between 2 matrix values or do I have to decompose the PRS values, (s)lerp them and rebuilt the matrix each step?

Thanks,

-Johan

there is no lerp for matrices. use lerp for rotation (in quaternions), and average for position and scale.

Thanks,

-Johan

there is no lerp for matrices. use lerp for rotation (in quaternions), and average for position and scale.

JHN

09-21-2010, 12:22 PM

@ Matan : Thanks, I'm using something else since I just need to blend between 2 matrices (making a pose tool for CAT). Will test you code as it looks more compact.

@ Denis : I'm using a slightly modified variant on your code

fn blendMatrix m1: m2: weight:0.5 =

(

fn dotQuat q q_prev =

(

(q.w * q_prev.w + q.x * q_prev.x + q.y * q_prev.y + q.z * q_prev.z) < 0

)

r1 = m1.rotationpart

r2 = m2.rotationpart

if (dotQuat r1 r2) do r1 *=-1

r = slerp (normalize r1) (normalize r2) weight

t = m1.translationpart + (m2.translationpart - m1.translationpart) * weight

s = m1.scalepart + (m2.scalepart - m1.scalepart) * weight

translate (rotate (scale (matrix3 1) s true) r) t -- ignores scale

)

I added the scale averaging, and encapsulated the dotQuat fn.

Thanks!

-Johan

@ Denis : I'm using a slightly modified variant on your code

fn blendMatrix m1: m2: weight:0.5 =

(

fn dotQuat q q_prev =

(

(q.w * q_prev.w + q.x * q_prev.x + q.y * q_prev.y + q.z * q_prev.z) < 0

)

r1 = m1.rotationpart

r2 = m2.rotationpart

if (dotQuat r1 r2) do r1 *=-1

r = slerp (normalize r1) (normalize r2) weight

t = m1.translationpart + (m2.translationpart - m1.translationpart) * weight

s = m1.scalepart + (m2.scalepart - m1.scalepart) * weight

translate (rotate (scale (matrix3 1) s true) r) t -- ignores scale

)

I added the scale averaging, and encapsulated the dotQuat fn.

Thanks!

-Johan

JHN

09-21-2010, 12:53 PM

@Matan, does it work between 2 transforms. I tried:

for i = 1 to 10 do point transform:(lerpM #($[1].transform, $[2].transform) #((i/10.), (1 - (i/10))))

Between 2 objects that are transformed differently, but the results are not good. How does your function work with 2 matrices?

Thanks,

-Johan

for i = 1 to 10 do point transform:(lerpM #($[1].transform, $[2].transform) #((i/10.), (1 - (i/10))))

Between 2 objects that are transformed differently, but the results are not good. How does your function work with 2 matrices?

Thanks,

-Johan

MatanH

09-21-2010, 12:59 PM

it won't work correct if the weights don't sum up to exactly 1.0

here is an example of what you tried to do:

local a = $[1]

local b = $[2]

local n = 10

for i = 1 to n - 1 do (

local c = copy a

local w = 1.0 * i / n

c.transform = lerp #(a.transform, b.transform) #(w, 1.0 - w)

)

EDIT:

just playing around with it, here is another nice test:

(

fn lerp matArray weights =

(

local resMat = matrix3 [0,0,0] [0,0,0] [0,0,0] [0,0,0]

for i = 1 to matArray.count do (

local w = weights[i]

local intMat = matrix3 [w,0,0] [0,w,0] [0,0,w] [w,w,w]

resMat += matArray[i] * intMat

)

resMat

)

local a = teapot transform:(matrix3 [0.543478,1.19095,-0.738627] [-1.22502,0.788501,0.370005] [1.21654,0.836836,2.24443] [204.994,154.378,224.798]) wirecolor:red

local b = teapot transform:(matrix3 [1,0,0] [0,1,0] [0,0,1] [122.507,3.13654,0]) wirecolor:green

local c = teapot transform:(matrix3 [1.06301,0.5229,0.250736] [-0.301877,-0.31541,1.93761] [0.425891,-0.832628,-0.0691843] [288.803,-141.283,52.8861]) wirecolor:blue

local n = 10

for j = 0 to n do (

local w1 = 1.0 * j / n

for i = 0 to n do (

local d = copy a

local w2 = (1.0 - w1) * i / n

local w3 = 1.0 - w1 - w2

d.transform = lerp #(a.transform, b.transform, c.transform) #(w1, w2, w3)

d.wireColor = a.wireColor * w1 + b.wireColor * w2 + c.wireColor * w3

)

)

)

here is an example of what you tried to do:

local a = $[1]

local b = $[2]

local n = 10

for i = 1 to n - 1 do (

local c = copy a

local w = 1.0 * i / n

c.transform = lerp #(a.transform, b.transform) #(w, 1.0 - w)

)

EDIT:

just playing around with it, here is another nice test:

(

fn lerp matArray weights =

(

local resMat = matrix3 [0,0,0] [0,0,0] [0,0,0] [0,0,0]

for i = 1 to matArray.count do (

local w = weights[i]

local intMat = matrix3 [w,0,0] [0,w,0] [0,0,w] [w,w,w]

resMat += matArray[i] * intMat

)

resMat

)

local a = teapot transform:(matrix3 [0.543478,1.19095,-0.738627] [-1.22502,0.788501,0.370005] [1.21654,0.836836,2.24443] [204.994,154.378,224.798]) wirecolor:red

local b = teapot transform:(matrix3 [1,0,0] [0,1,0] [0,0,1] [122.507,3.13654,0]) wirecolor:green

local c = teapot transform:(matrix3 [1.06301,0.5229,0.250736] [-0.301877,-0.31541,1.93761] [0.425891,-0.832628,-0.0691843] [288.803,-141.283,52.8861]) wirecolor:blue

local n = 10

for j = 0 to n do (

local w1 = 1.0 * j / n

for i = 0 to n do (

local d = copy a

local w2 = (1.0 - w1) * i / n

local w3 = 1.0 - w1 - w2

d.transform = lerp #(a.transform, b.transform, c.transform) #(w1, w2, w3)

d.wireColor = a.wireColor * w1 + b.wireColor * w2 + c.wireColor * w3

)

)

)

JHN

09-21-2010, 01:31 PM

I went wrong because my code produced an integer as weight instead of a float. But still your solution is not as good because the scale of the matrix is not avaraged, but get's distorted. So I'm sticking with my (Denis' actually) code. But there's some nice motion design effects to be made with your code!

Thanks,

-Johan

Thanks,

-Johan

eek

09-22-2010, 02:53 PM

local matrices = #((matrix3 1), ((eulerangles 0 45 32) as matrix3), (transMatrix [50,40,10]))

local mc = for each in matrices collect each

local tmp = #()

local t = 0.5

while mc.count > 1 do

(

for i = 1 to (mc.count-1) do

(

append tmp ((slerp mc[i].rotation mc[i+1].rotation t) as matrix3 * transMatrix((1-t) * mc[i].row4 + mc[i+1].row4 * t))

)

mc = tmp

tmp = #()

)

mc[1]

This is a quadratic form of blending between multiple matrices roughly.

local mc = for each in matrices collect each

local tmp = #()

local t = 0.5

while mc.count > 1 do

(

for i = 1 to (mc.count-1) do

(

append tmp ((slerp mc[i].rotation mc[i+1].rotation t) as matrix3 * transMatrix((1-t) * mc[i].row4 + mc[i+1].row4 * t))

)

mc = tmp

tmp = #()

)

mc[1]

This is a quadratic form of blending between multiple matrices roughly.

CGTalk Moderation

09-22-2010, 02:53 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.