Jump to content
  • Advertisement
Sign in to follow this  

Transformation lags/overtakes vector when trying to deform along path via HLSL

Recommended Posts

I'm trying to implement animation by deformation along a path in Miku Miku Dance.  This problem is interesting to me, it opens up new options to animators, and it seems like a good way for me to learn more about transformations.  I'm doing my deformation in a HLSL vertex shader, using bones as path nodes, using quaternions to create matrices to rotate my vertices, traveling down the path and rotating as I go.  I don't understand quaternion math, but I found this code online, and it's worked for me other places :)

It's almost right.  I really think I'm doing the right thing.  Almost.  But my angles aren't right.  Demonstrated in the picture (yes, I'm using an actual arrow model to test).

At 90 degree intervals, the angles are correct.  As I go from no transformation to 90 degrees, the transformation lags the vector.  From 90 degrees to 180 degrees, the transformation overtakes the vector.  This is symmetrical; transformation lags the -45 degree vector same as +45 degrees.

Here is the code I've written.  I'm trying to include only relevant bits.  I can include everything if anybody wants, just trying to spare you.  This is for shader model 3.0/DX9.


float4 pos0 : CONTROLOBJECT < string name = PATHMODEL; string item = "0"; >;
//leave at origin, indicates beginning of deformation
float4 pos1 : CONTROLOBJECT < string name = PATHMODEL; string item = "1"; >;
//first node, proceeding from origin
float3 rotateAxis(float3 pos, float3 origin, float3 axis, float angle) {
//rotates pos around origin in axis by angle in rads using quaternion
    pos -= origin;
    float4 q;
    q.xyz = axis*sin(angle/2.0f);
    q.w = cos(angle/2.0f);
    q = normalize(q);
    float3 temp = cross(q.xyz, pos) + q.w * pos;
    pos = (cross(temp, -q.xyz)+dot(q.xyz,pos)*q.xyz+q.w*temp);
    pos += origin;
    return pos;

    float4 wPos = mul( Pos, WorldMatrix );
    float3 vec0 = YVEC;
//primary axis, as vertices travel in positive Y axis they are deformed
    float3 vec1 = normalize(pos1.xyz - pos0.xyz);
    float extent = wPos.y; extent -= pos0.y;
    if (extent > 0.0f) {
        float3 axis = cross(vec0, vec1);
        float angle = (PI*(1.0f-((dot(vec0,vec1)) + 1.0f)/2.0f));
        wPos.xyz = rotateAxis(wPos.xyz, pos0.xyz, axis, angle);
    Out.Pos = mul( wPos, ViewProjMatrix );

Am I misunderstanding the dot product here?  Does my function not do what I think it does?  Something else?  Any help is greatly appreciated.  I'm an amateur, I try to read and learn, but no formal education, no experience, and no people around me studying the same things, and I'm really grateful for the people on this forum that provide help.


Share this post

Link to post
Share on other sites

On a night's rest, it seems to me that I shouldn't be using angle = PI*(1.0f-((dotProd + 1.0f)/2.0f)); but should instead be using angle = acos(dotProd); .  However, this apparently gives me an apparently identical response through angles up to Pi/2 radians, and breaks down when it reaches something like Pi*4/3.  Seems like it's right theoretically, but looks entirely wrong.


The relationship is not a power relationship.  Nevertheless, using the code I provided above, but adding dotProd = 1.0f - pow(1.0f-dotProd, 0.25f); gives me something very close to correct.  Currently I'm just hacking my way through it with this correction, creating a new node at the not-quite-right angle in order to approach the correct path.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!