Problem with cal3d derived

Scripting in Blender with Python, and working on the API

Moderators: jesterKing, stiv

Post Reply
MangoFusion
Posts: 0
Joined: Wed Nov 19, 2003 4:10 pm

Problem with cal3d derived

Post by MangoFusion »

I've noticed a slight oddity in the cal3d exporter code. (which is used by many other exporters).

Specifically, this function :

Code: Select all

def blender_bone2matrix(head, tail, roll):
  # Convert bone rest state (defined by bone.head, bone.tail and bone.roll)
  # to a matrix (the more standard notation).
  # Taken from blenkernel/intern/armature.c in Blender source.
  # See also DNA_armature_types.h:47.
  
  target = [0.0, 1.0, 0.0]
  delta  = [tail[0] - head[0], tail[1] - head[1], tail[2] - head[2]]
  nor    = vector_normalize(delta)
  axis   = vector_crossproduct(target, nor)
  
  if vector_dotproduct(axis, axis) > 0.0000000000001:
    axis    = vector_normalize(axis)
    theta   = math.acos(vector_dotproduct(target, nor))
    bMatrix = matrix_rotate(axis, theta)
    
  else:
    if vector_crossproduct(target, nor) > 0.0: updown =  1.0
    else:                                      updown = -1.0
    
    # Quoted from Blender source : "I think this should work ..."
    bMatrix = [
      [updown, 0.0, 0.0, 0.0],
      [0.0, updown, 0.0, 0.0],
      [0.0, 0.0, 1.0, 0.0],
      [0.0, 0.0, 0.0, 1.0],
      ]
  
  rMatrix = matrix_rotate(nor, roll)
  return matrix_multiply(rMatrix, bMatrix)
Take a look at the "vector_crossproduct" line. This function returns a vector, but the if statement appears to expect a scalar float.

Really, it should be calling "vector_dotproduct". This is also what happens in the original code.

For comparison, here is the original function in the blender code :

Code: Select all

void make_boneMatrixvr (float outmatrix[][4],float delta[3], float roll)
/*	Calculates the rest matrix of a bone based
	On its vector and a roll around that vector */
{
	float	nor[3],axis[3],target[3]={0,1,0};
	float	theta;
	float	rMatrix[3][3], bMatrix[3][3], fMatrix[3][3];

	VECCOPY (nor,delta);
	Normalise (nor);

	/*	Find Axis & Amount for bone matrix*/
	Crossf (axis,target,nor);

	if (Inpf(axis,axis) > 0.0000000000001) {
		/* if nor is *not* a multiple of target ... */
		Normalise (axis);
		theta=(float) acos (Inpf (target,nor));

		/*	Make Bone matrix*/
		VecRotToMat3(axis, theta, bMatrix);
	}
	else {
		/* if nor is a multiple of target ... */
		float updown;

		/* point same direction, or opposite? */
		updown = ( Inpf (target,nor) > 0 ) ? 1.0 : -1.0;

		/* I think this should work ... */
		bMatrix[0][0]=updown; bMatrix[0][1]=0.0;    bMatrix[0][2]=0.0;
		bMatrix[1][0]=0.0;    bMatrix[1][1]=updown; bMatrix[1][2]=0.0;
		bMatrix[2][0]=0.0;    bMatrix[2][1]=0.0;    bMatrix[2][2]=1.0;
	}

	/*	Make Roll matrix*/
	VecRotToMat3(nor, roll, rMatrix);
	
	/*	Combine and output result*/
	Mat3MulMat3 (fMatrix,rMatrix,bMatrix);
	Mat4CpyMat3 (outmatrix,fMatrix);
}

ascotan
Posts: 0
Joined: Thu May 29, 2003 10:32 pm
Location: Maryland, U.S.

Post by ascotan »

Yes it prob should be dot product. Inpf() is the dot product function in arthib.c. Inpf is danish for dot :roll: (Gotta love easy to figure out function names).

der_ton
Posts: 0
Joined: Mon Oct 20, 2003 1:02 am

Post by der_ton »

Wow, thanks, I use that code for my exporter too and never saw that. Hmm, why does it work anyway? I've never seen that that affects the output. In what cases does it make a difference?

MangoFusion
Posts: 0
Joined: Wed Nov 19, 2003 4:10 pm

Post by MangoFusion »

I'm not entirely certain; But of course, it effects if the "updown" value if negative or not.
The name, and the comment ("point same direction, or opposite?") implies it has something to do with the bone matrix pointing "up" or "down", so i would guess that it inverts the rotation/translation?

The typo'd statement appears to return True all the time, so updown would always be 1.0

Post Reply