[Closed] Normal Transformation, Skinned Model
Hey Guys!
i am trying to figure out how i can transform my normals (for a skinned model) correctly so that when the bones move the normals are transformed accordingly here’s how i am doing it:
(
theFrame = 45
theface = 1075
leg = $_leg
select leg
vertexid = ((getface leg theface).x as integer)
input = at time 0 ((meshop.getfacernormals leg theface)[1])
outputValue = at time theFrame ((meshop.getfacernormals leg theface)[1])
computedValue = [0,0,0]
numberOfBonesPerVertex = skinops.getvertexweightcount theskin vertexid
for i = 1 to numberOfBonesPerVertex do(
boneid = skinops.getvertexweightboneid theskin vertexid i
bonename = skinops.getbonename theskin boneid 1
boneTMAt0 = at time 0 (execute ("$" + bonename +".transform"))
boneTMAtFrame = at time theFrame (execute ("$" + bonename +".transform"))
boneTMAt0 = translate boneTMAt0 (- boneTMAt0.row4)
boneTMAtFrame = translate boneTMAtFrame (- boneTMAtFrame.row4)
weight = skinops.getvertexweight theskin vertexid i
tm = (inverse boneTMAt0) * boneTMAtFrame
weightedNormal = (input * tm) * weight
computedvalue = normalize (computedValue + weightedNormal)
)
format "Normal = %
Output = %
" computedValue outputValue
)
i am multiplying the skinned vertex’s normal (which is the normal for a particular face’s vertex, i.e output of the meshop.getfacernormals function) with the inverse tm of the bone (that influences the particular vertex) at frame 1 (normal is now in bone tm space)
next i am multiplying the normal with the animated transformation matrix of the same bone, finally i multiply it by the weight assigned to the vertex for that bone, I repeat this process for the same vertex for every bone that influences that vertex and then i normalize the sum to obtain the (incorrect) normal , its incorrect because it does not match the normal returned by the edit normal modifier (i am confused which normal is actually correct now!).
*Note: nothing in my scene is scaled (so i do not need to use the inverseTranspose matrix). Also the maxscript i posted above works perfectly if the vertex is rigid (i.e its influenced only by one bone, complications arise for vertices weighted across multiple bones) here is sample input / output (for a vertex weighted between 2 bones, just to show the difference in the result) :
Input = [-0.171326,-0.887662,-0.427439]
My Output = [-0.28916,-0.85693,0.426681]
EN Output = [-0.241229,-0.960267,0.140343] // EM = edit normal modifier same as meshop.getfacernormals
honestly i don’t understand the idea. why do you want to correct normals after the skin deform?
Move the normalize outside of the loop?
computedvalue = [0,0,0]
for i = 1 to numberOfBonesPerVertex do(
-- Calculate weighted normal
computedvalue += weightedNormal
)
computedvalue = normalize computedValue
thanks for the post
i have tried all permutations (i have placed it outside, placed it in both places, removed it completely lol) it just doesnt work for weighted vertices only for rigid ones !
but the thing is when i took these normals into my 3d engine the shading works kind of ok (i think the difference may not be that noticeable!, although the problem still remains as i have not tested it on a uber model yet!)
I need to correct the normals after the skin deform, in my 3d engine. I am using max to figure out the correct algorithm to do so (by comparing with the edit normal modifier and the meshop.getfacernormals).
As i will be exporting the normals per vertex per face only once but as the model animates in my engine i need to be able to calculate the normals correctly at every frame for my pixel shader to work properly (other wise i get animated lighting and artifacts). But the results i get from weighting normals are not the same as edit normal modifier or the meshop.getfacernormals, And still cannot figure out why ! i even checked it with an inverse transpose matrix, which strips of the scaling component, but there was no scaling so the results were the same . I am using the same algorithm in my engine to assign correct vertex position at every frame (based on the motion of the bone) but the algorithm is just not working for normals (what a bummer!!).