00001
00002 #include "NiVMDTool.h"
00003
00004
00005 using namespace jbxl;
00006 using namespace jbxwl;
00007
00008
00009 static std::string _VMDJointName[] =
00010 {
00011
00012 "全ての親", "センター",
00013 "下半身", "上半身", "上半身2", "首", "頭", "頭先",
00014 "両目", "左目", "右目", "左胸", "右胸",
00015
00016 "左肩", "左腕", "左腕捩", "左ひじ", "左手捩", "左手首", "左手先",
00017 "右肩", "右腕", "右腕捩", "右ひじ", "右手捩", "右手首", "右手先",
00018
00019
00020 "左足", "左ひざ", "左足IK", "左足首", "左つま先", "左つま先IK",
00021 "右足", "右ひざ", "右足IK", "右足首", "右つま先", "右つま先IK"
00022 };
00023
00024
00025
00026 static std::string _VMDJointName_eng[] =
00027 {
00028 "parent", "center",
00029 "lower body", "upper body", "upper body2", "neck", "head", "skull",
00030 "eyes", "eye_L", "eye_R", "bust_L", "bust_R",
00031
00032 "shoulder_L", "arm_L", "arm twist_L", "elbow_L", "wrist twist_L", "wrist_L", "c wrist l",
00033 "shoulder_R", "arm_R", "arm twist_R", "elbow_R", "wrist twist_R", "wrist_R", "c wrist r",
00034
00035 "leg_L", "knee_L", "leg_IK_L", "ankle_L", "toe_L", "toe_IK_L",
00036 "leg_R", "knee_R", "leg_IK_R", "ankle_R", "toe_R", "toe_IK_R"
00037 };
00038
00039
00040
00046 std::string jbxwl::VMDJointName(int n)
00047 {
00048 std::string str = "";
00049
00050 if (n>=0 && n<VMD_JOINT_NUM) {
00051 str = _VMDJointName[n];
00052 }
00053
00054 return str;
00055 }
00056
00057
00058
00064 int jbxwl::VMDJointNum(char* name)
00065 {
00066 for (int i=0; i<VMD_JOINT_NUM; i++) {
00067 if (!strcmp(name, _VMDJointName[i].c_str()) || !strcmp(name, _VMDJointName_eng[i].c_str())) {
00068 return i;
00069 }
00070 }
00071 return -1;
00072 }
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 static int _VMD2NiJointNum[] =
00127 {
00128 -1, 0,
00129 1, 2, 3, 4, 5, 6,
00130 -1, 7, 8, 9, 10,
00131 11, 12, -1, 13, -1, 14, 15,
00132 17, 18, -1, 19, -1, 20, 21,
00133 23, 24, 25, 26, 27, -1,
00134 28, 29, 30, 31, 32, -1
00135 };
00136
00137
00138
00142 int jbxwl::VMD2NiJointNum(int joint)
00143 {
00144 if (joint<0 || joint>=VMD_JOINT_NUM) return -1;
00145
00146 return _VMD2NiJointNum[joint];
00147 }
00148
00149
00150
00152
00153
00154 CNiVMDTool::CNiVMDTool(void)
00155 {
00156 memset(&vmd_header, 0, sizeof(VMDFileHeader));
00157
00158 vmd_frames = NULL;
00159 vmd_datnum = 0;
00160 dmy_frames = NULL;
00161 dmy_frmnum = 0;
00162 joints_num = VMD_JOINT_NUM;
00163
00164 rate_frame = VMD_FARME_RATE/30.0;
00165 A2TPose.setRotation(37.0/180.0*PI, 1.0, 0.0, 0.0, 1.0);
00166
00167 posVect = (Vector<double>*)malloc(sizeof(Vector<double>)*VMD_JOINT_NUM);
00168 rotQuat = (Quaternion<double>*)malloc(sizeof(Quaternion<double>)*VMD_JOINT_NUM);
00169 }
00170
00171
00172
00173 CNiVMDTool::~CNiVMDTool(void)
00174 {
00175 DEBUG_INFO("DESTRUCTOR: CNiVMDTool\n");
00176
00177 free_data();
00178 }
00179
00180
00181
00182 void CNiVMDTool::free_data(void)
00183 {
00184 if (dmy_frames!=NULL) ::freeFramesData(dmy_frames, dmy_frmnum);
00185 if (vmd_frames!=NULL) ::free(vmd_frames);
00186
00187 vmd_frames = NULL;
00188 vmd_datnum = 0;
00189 dmy_frames = NULL;
00190 dmy_frmnum = 0;
00191
00192 clear_data();
00193 }
00194
00195
00196
00197 void CNiVMDTool::clear_data(void)
00198 {
00199 CBaseFrameTool::free_data();
00200 }
00201
00202
00203
00204
00206
00207
00213 BOOL CNiVMDTool::readFile(FILE* fp)
00214 {
00215 if (fp==NULL) return FALSE;
00216
00217 clear_data();
00218
00219 vmd_datnum = 0;
00220 vmd_header = readFileHeader(fp);
00221 if (vmd_header.data_num==0) return FALSE;
00222
00223 vmd_frames = readJointsData(fp, vmd_header.data_num);
00224 if (vmd_frames==NULL) return FALSE;
00225 vmd_datnum = vmd_header.data_num;
00226
00227
00228 joints_num = VMD_JOINT_NUM;
00229 if (jointsData!=NULL) ::free(jointsData);
00230 jointsData = (NiJointData*)malloc(sizeof(NiJointData)*joints_num);
00231 if (jointsData==NULL) {
00232 clear_data();
00233 return FALSE;
00234 }
00235 clearJointsData(joints_num);
00236
00237 if (posVect==NULL) posVect = (Vector<double>*)malloc(sizeof(Vector<double>)*VMD_JOINT_NUM);
00238 if (rotQuat==NULL) rotQuat = (Quaternion<double>*)malloc(sizeof(Quaternion<double>)*VMD_JOINT_NUM);
00239 if (posVect==NULL || rotQuat==NULL) {
00240 clear_data();
00241 return FALSE;
00242 }
00243 clearVectorData(VMD_JOINT_NUM);
00244
00245 return TRUE;
00246 }
00247
00248
00249
00255 VMDFileHeader CNiVMDTool::readFileHeader(FILE* fp)
00256 {
00257 VMDFileHeader fhd;
00258
00259 fread(fhd.header, 30, 1, fp);
00260 fread(fhd.name, 20, 1, fp);
00261 fread(&fhd.data_num, 4, 1, fp);
00262
00263 if (strcmp(VMD_FILE_HD_ID2, fhd.header)) {
00264 fhd.data_num = 0;
00265 }
00266
00267 return fhd;
00268 }
00269
00270
00271
00278 VMDJointData CNiVMDTool::readJointData(FILE* fp)
00279 {
00280 VMDJointData frame;
00281
00282 fread(frame.name, 15, 1, fp);
00283 fread(&frame.frm_num, 96, 1, fp);
00284
00285 return frame;
00286 }
00287
00288
00289
00296 VMDJointData* CNiVMDTool::readJointsData(FILE* fp, unsigned int& frmnum)
00297 {
00298 VMDJointData* motion_data = (VMDJointData*)malloc(frmnum*sizeof(VMDJointData));
00299 if (motion_data==NULL) return NULL;
00300 memset(motion_data, 0, frmnum*sizeof(VMDJointData));
00301
00302
00303 unsigned int num = 0;
00304 while(num<frmnum) {
00305 motion_data[num] = readJointData(fp);
00306 if (feof(fp)) break;
00307 num++;
00308 }
00309
00310 frmnum = num;
00311 if (frmnum==0) {
00312 ::free(motion_data);
00313 motion_data = NULL;
00314 }
00315
00316 return motion_data;
00317 }
00318
00319
00320
00330 NiFrameData* CNiVMDTool::getFramesData(void)
00331 {
00332 joints_num = VMD_JOINT_NUM;
00333
00335 if (framesData!=NULL) clear_data();
00336 framesData = convert2FrameData(vmd_frames, vmd_datnum, frames_num);
00337 if (framesData==NULL) return NULL;
00338
00339 calcJointRotation();
00341
00342
00343 for (unsigned int i=0; i<frames_num; i++) {
00344
00345 for (int j=0; j<framesData[i].jnum; j++) {
00346 int n = VMD2NiJointNum(framesData[i].jdat[j].joint);
00347 framesData[i].jdat[j].joint = n;
00348 }
00349 }
00350
00351
00352 dmy_frmnum = (int)(framesData[frames_num-1].frmn*rate_frame);
00353 dmy_frames = makeFramesData(dmy_frmnum, 0, NULL);
00354 if (dmy_frames==NULL) {
00355 dmy_frmnum = frames_num;
00356 return framesData;
00357 }
00358
00359 for (unsigned int i=0; i<dmy_frmnum; i++) {
00360 dmy_frames[i].jnum = joints_num;
00361 dmy_frames[i].msec = (int)(i*(100.0/(rate_frame*3.0)));
00362 }
00363 if (rate_frame!=1.0) {
00364 for (unsigned int i=0; i<frames_num; i++) {
00365 framesData[i].frmn = (int)(framesData[i].frmn*rate_frame);
00366 framesData[i].msec = (int)(framesData[i].msec/rate_frame);
00367 }
00368 }
00369
00370 start_time = framesData[0].msec;
00371 stop_time = framesData[frames_num-1].msec;
00372 exec_time = stop_time - start_time;
00373
00374 return dmy_frames;
00375 }
00376
00377
00378
00388 NiFrameData* CNiVMDTool::convert2FrameData(VMDJointData* motion_data, unsigned int datanum, unsigned int& framenum)
00389 {
00390 framenum = 0;
00391 if (motion_data==NULL || datanum<=0) return NULL;
00392
00393
00394 VMDJointData swap_motion;
00395 unsigned int k = datanum - 1;
00396 while (k>0) {
00397 unsigned int j = 0;
00398 for (unsigned int i=0; i<k; i++) {
00399 if (motion_data[i].frm_num>motion_data[i+1].frm_num) {
00400 swap_motion = motion_data[i];
00401 motion_data[i] = motion_data[i+1];
00402 motion_data[i+1] = swap_motion;
00403 j = i;
00404 }
00405 }
00406 k = j;
00407 }
00408
00409
00410 unsigned int uniq_frame = 1;
00411
00412 unsigned int frm_num = motion_data[0].frm_num;
00413 for (unsigned int i=1; i<datanum; i++) {
00414 if (frm_num!=motion_data[i].frm_num) {
00415 uniq_frame++;
00416 frm_num = motion_data[i].frm_num;
00417 }
00418 }
00419
00420 NiFrameData* ni_joints = makeFramesData((int)uniq_frame, joints_num, NULL);
00421 if (ni_joints==NULL) return NULL;
00422 framenum = uniq_frame;
00423
00424
00425 unsigned int datacnt = 0;
00426 for (unsigned int i=0; i<uniq_frame; i++) {
00427 frm_num = motion_data[datacnt].frm_num;
00428 ni_joints[i].frmn = frm_num;
00429 ni_joints[i].msec = (int)(frm_num*33.3333333333333);
00430
00431 while (frm_num==motion_data[datacnt].frm_num) {
00432 int joint = VMDJointNum(motion_data[datacnt].name);
00433 if (joint>=0) {
00434 NiJointData* jdat = &(ni_joints[i].jdat[joint]);
00435 jdat->joint = joint;
00436 jdat->index = i;
00437 jdat->vect.x = -motion_data[datacnt].posz*(double)VMD_GRID_UNIT;
00438 jdat->vect.y = motion_data[datacnt].posx*(double)VMD_GRID_UNIT;
00439 jdat->vect.z = motion_data[datacnt].posy*(double)VMD_GRID_UNIT;
00440 jdat->quat.x = motion_data[datacnt].qutz;
00441 jdat->quat.y = -motion_data[datacnt].qutx;
00442 jdat->quat.z = -motion_data[datacnt].quty;
00443 jdat->quat.s = motion_data[datacnt].qutw;
00444 if (jdat->quat.s<0.0) jdat->quat = - jdat->quat;
00445 jdat->quat.normalize();
00446
00447
00448 if (jdat->vect.x!=0.0 || jdat->vect.y!=0.0 || jdat->vect.z!=0.0) {
00449 jdat->vect.c = 1.0;
00450 }
00451 if (jdat->quat.x!=0.0 || jdat->quat.y!=0.0 || jdat->quat.z!=0.0 || jdat->quat.s!=0.0) {
00452 jdat->quat.c = 1.0;
00453 }
00454 }
00455
00456 datacnt++;
00457 if (datacnt==datanum) break;
00458 }
00459 }
00460
00461
00462 return ni_joints;
00463 }
00464
00465
00466
00472 void CNiVMDTool::calcJointRotation(void)
00473 {
00474 if (framesData==NULL || frames_num<=0) return;
00475
00476 if (posVect==NULL) posVect = (Vector<double>*)malloc(sizeof(Vector<double>)*VMD_JOINT_NUM);
00477 if (rotQuat==NULL) rotQuat = (Quaternion<double>*)malloc(sizeof(Quaternion<double>)*VMD_JOINT_NUM);
00478 if (posVect==NULL || rotQuat==NULL) return;
00479 clearVectorData(VMD_JOINT_NUM);
00480
00481 NiJointData prevJoint[VMD_JOINT_NUM];
00482 for (int j=0; j<VMD_JOINT_NUM; j++) {
00483 prevJoint[j].joint = -1;
00484 prevJoint[j].index = -1;
00485 prevJoint[j].vect.init(-1.0);
00486 prevJoint[j].quat.init(-1.0);
00487 }
00488
00489
00490 for (unsigned int i=0; i<frames_num; i++) {
00491
00492 NiJointData* jdata = framesData[i].jdat;
00493
00494 jdata[VMD_CENTER].vect.c = 1.0;
00495 jdata[VMD_CENTER].quat.c = 1.0;
00496
00497 for (int j=0; j<framesData[i].jnum; j++) {
00498
00499 if (jdata[j].joint>=0) {
00500 posVect[j] = jdata[j].vect;
00501 rotQuat[j] = jdata[j].quat;
00502 if (posVect[j].c<0.0) posVect[j] = prevJoint[j].vect;
00503 if (rotQuat[j].c<0.0) rotQuat[j] = prevJoint[j].quat;
00504 }
00505
00506 else {
00507 posVect[j] = prevJoint[j].vect;
00508 rotQuat[j] = prevJoint[j].quat;
00509 }
00510 }
00511
00513 calcJointIK(i);
00515
00516
00517 for (int j=0; j<framesData[i].jnum; j++) {
00518 if (jdata[j].joint>=0) {
00519 prevJoint[j] = jdata[j];
00520 }
00521 }
00522
00523
00524 rotQuat[VMD_L_WRIST] = rotQuat[VMD_L_WRIST]*rotQuat[VMD_L_WRIST_TW];
00525 rotQuat[VMD_L_ELBOW] = rotQuat[VMD_L_ELBOW]*rotQuat[VMD_L_ARM_TW];
00526 rotQuat[VMD_R_WRIST] = rotQuat[VMD_R_WRIST]*rotQuat[VMD_R_WRIST_TW];
00527 rotQuat[VMD_R_ELBOW] = rotQuat[VMD_R_ELBOW]*rotQuat[VMD_R_ARM_TW];
00528
00529 rotQuat[VMD_L_EYE] = rotQuat[VMD_L_EYE]*rotQuat[VMD_EYES];
00530 rotQuat[VMD_R_EYE] = rotQuat[VMD_R_EYE]*rotQuat[VMD_EYES];
00531
00533 rotQuat[VMD_L_WRIST] = A2TPose*rotQuat[VMD_L_WRIST]*~A2TPose;
00534 rotQuat[VMD_L_ELBOW] = A2TPose*rotQuat[VMD_L_ELBOW]*~A2TPose;
00535 rotQuat[VMD_L_ARM] = rotQuat[VMD_L_ARM]*~A2TPose;
00536
00537 rotQuat[VMD_R_WRIST] = ~A2TPose*rotQuat[VMD_R_WRIST]*A2TPose;
00538 rotQuat[VMD_R_ELBOW] = ~A2TPose*rotQuat[VMD_R_ELBOW]*A2TPose;
00539 rotQuat[VMD_R_ARM] = rotQuat[VMD_R_ARM]*A2TPose;
00540
00541
00542 rotQuat[VMD_L_ANKLE_IK].set(1.0, 0.0, 0.0, 0.0, 1.0);
00543 rotQuat[VMD_R_ANKLE_IK].set(1.0, 0.0, 0.0, 0.0, 1.0);
00544
00545
00546
00547
00548
00549 for (int j=0; j<framesData[i].jnum; j++) {
00550 jdata[j].joint = prevJoint[j].joint;
00551 jdata[j].index = prevJoint[j].index;
00552 jdata[j].vect = posVect[j];
00553 jdata[j].quat = rotQuat[j];
00554 }
00555 }
00556
00557 return;
00558 }
00559
00560
00561
00562 void CNiVMDTool::calcJointIK(int fnum)
00563 {
00564
00565 Vector<double> vect_Y(0.0, 1.0, 0.0, 1.0);
00566 Vector<double> vect_Z(0.0, 0.0,-1.0, 1.0);
00567 Vector<double> cnt_vect_Y = VectorRotation(vect_Y, rotQuat[VMD_CENTER]);
00568 Vector<double> cnt_vect_Z = VectorRotation(vect_Z, rotQuat[VMD_CENTER]);
00569
00570
00571 Vector<double> l_leg_vect = VectorRotation(cnt_vect_Z, rotQuat[VMD_L_HIP]);
00572 Vector<double> r_leg_vect = VectorRotation(cnt_vect_Z, rotQuat[VMD_R_HIP]);
00573
00574
00575 Vector<double> l_ank_vect = vect_Y*0.10 + vect_Z*0.83;
00576 Vector<double> r_ank_vect = -vect_Y*0.10 + vect_Z*0.83;
00577
00578
00579 Vector<double> l_end_vect = cnt_vect_Y*0.10 + l_leg_vect*0.83;
00580 Vector<double> r_end_vect = -cnt_vect_Y*0.10 + r_leg_vect*0.83;
00581
00582
00583 Vector<double> l_ik_vect = l_ank_vect + posVect[VMD_L_ANKLE_IK] - posVect[VMD_CENTER] - l_end_vect;
00584 Vector<double> r_ik_vect = r_ank_vect + posVect[VMD_R_ANKLE_IK] - posVect[VMD_CENTER] - r_end_vect;
00585
00586
00587 l_ik_vect = VectorRotation(l_ik_vect, ~rotQuat[VMD_CENTER]);
00588 r_ik_vect = VectorRotation(r_ik_vect, ~rotQuat[VMD_CENTER]);
00589
00590
00591 Vector<double> l_vect[3], r_vect[3];
00592 Quaternion<double> l_quat[3], r_quat[3];
00593
00594
00595 l_vect[0].set(0.0, 0.0, 0.0);
00596 r_vect[0].set(0.0, 0.0, 0.0);
00597
00598 l_vect[1] = -l_leg_vect*0.58;
00599 r_vect[1] = -r_leg_vect*0.58;
00600 l_vect[2] = -l_leg_vect*1.18;
00601 r_vect[2] = -r_leg_vect*1.18;
00602
00603
00604 l_vect[1] = VectorRotation(l_vect[1], ~rotQuat[VMD_CENTER]);
00605 r_vect[1] = VectorRotation(r_vect[1], ~rotQuat[VMD_CENTER]);
00606 l_vect[2] = VectorRotation(l_vect[2], ~rotQuat[VMD_CENTER]);
00607 r_vect[2] = VectorRotation(r_vect[2], ~rotQuat[VMD_CENTER]);
00608
00610 calcLegIK_CCD(l_vect, l_ik_vect, l_quat, 50);
00611 calcLegIK_CCD(r_vect, r_ik_vect, r_quat, 50);
00613
00614
00615 if (rotQuat[VMD_L_HIP].c>0.0) rotQuat[VMD_L_HIP] = l_quat[2]*rotQuat[VMD_L_HIP];
00616 else rotQuat[VMD_L_HIP] = l_quat[2];
00617 if (rotQuat[VMD_R_HIP].c>0.0) rotQuat[VMD_R_HIP] = r_quat[2]*rotQuat[VMD_R_HIP];
00618 else rotQuat[VMD_R_HIP] = r_quat[2];
00619
00620 framesData[fnum].jdat[VMD_L_HIP].joint = VMD_L_HIP;
00621 framesData[fnum].jdat[VMD_R_HIP].joint = VMD_R_HIP;
00622 framesData[fnum].jdat[VMD_L_HIP].index = fnum;
00623 framesData[fnum].jdat[VMD_R_HIP].index = fnum;
00624
00625
00626 rotQuat[VMD_L_KNEE] = l_quat[1];
00627 rotQuat[VMD_R_KNEE] = r_quat[1];
00628
00629 double dot = vect_Y*rotQuat[VMD_L_KNEE].getVector();
00630 if (dot>=0.0) {
00631 framesData[fnum].jdat[VMD_L_KNEE].joint = VMD_L_KNEE;
00632 framesData[fnum].jdat[VMD_L_KNEE].index = fnum;
00633 }
00634 else {
00635 framesData[fnum].jdat[VMD_L_KNEE].joint = -1;
00636 framesData[fnum].jdat[VMD_L_KNEE].index = -1;
00637 }
00638
00639 dot = vect_Y*rotQuat[VMD_R_KNEE].getVector();
00640 if (dot>=0.0) {
00641 framesData[fnum].jdat[VMD_R_KNEE].joint = VMD_R_KNEE;
00642 framesData[fnum].jdat[VMD_R_KNEE].index = fnum;
00643 }
00644 else {
00645 framesData[fnum].jdat[VMD_R_KNEE].joint = -1;
00646 framesData[fnum].jdat[VMD_R_KNEE].index = -1;
00647 }
00648
00649 return;
00650 }
00651
00652
00653
00657 void CNiVMDTool::calcLegIK_CCD(Vector<double>* vect, Vector<double> ik_vect, Quaternion<double>* quat, int rpmax)
00658 {
00659 Vector<double> vect_Y(0.0, 1.0, 0.0, 1.0);
00660 Vector<double> effect, target;
00661 Quaternion<double> rot;
00662
00663 for (int j=0; j<3; j++) quat[j].init();
00664
00665 for (int i=0; i<rpmax; i++) {
00666
00667 int cnt = 0;
00668 for (int j=1; j<3; j++) {
00669
00670 if (i==0 && j==1) {
00671 rot.setRotation((double)PI_DIV2, vect_Y);
00672 }
00673 else {
00674 effect = vect[0] - vect[j];
00675 target = ik_vect - vect[j];
00676 rot = V2VQuaternion(effect, target);
00677 }
00678
00679
00680 if (rot.c>0.0) {
00681 rot.normalize();
00682 if (rot.s<1.00-Zero_Eps) {
00683
00684 quat[j] = quat[j]*rot;
00685 for (int k=0; k<j; k++) {
00686 vect[k] = VectorRotation(vect[k]-vect[j], rot) + vect[j];
00687 }
00688 }
00689 else cnt++;
00690 }
00691 else cnt++;
00692 }
00693 if (cnt==2) break;
00694 }
00695
00696 return;
00697 }
00698
00699
00700
00713 NiJointData* CNiVMDTool::getJointsData(int frmnum, int fps)
00714 {
00715 clearJointsData(joints_num);
00716
00717 frmnum = (int)((double)frmnum*VMD_FARME_RATE/(double)fps);
00718
00719
00720 for (int j=0; j<joints_num; j++) {
00721
00722 int n = framesData[0].jdat[j].joint;
00723 if (n>=0) {
00724 unsigned int st_index = 0;
00725 unsigned int en_index = 0;
00726
00727 while (en_index<frames_num && framesData[en_index].frmn<frmnum) en_index++;
00728 if (en_index==frames_num) break;
00729
00730 if (en_index==0 || (framesData[en_index].frmn==frmnum && en_index==framesData[en_index].jdat[j].index)) {
00731 jointsData[j].vect = framesData[en_index].jdat[j].vect;
00732 jointsData[j].quat = framesData[en_index].jdat[j].quat;
00733 }
00734 else {
00735 st_index = framesData[en_index-1].jdat[j].index;
00736 while (en_index<frames_num && en_index!=framesData[en_index].jdat[j].index) en_index++;
00737
00738 if (en_index==frames_num) {
00739 jointsData[j].vect = framesData[st_index].jdat[j].vect;
00740 jointsData[j].quat = framesData[st_index].jdat[j].quat;
00741 }
00742 else {
00743 NiJointData st_joint = framesData[st_index].jdat[j];
00744 NiJointData en_joint = framesData[en_index].jdat[j];
00745 double tparam = ((double)(frmnum - framesData[st_index].frmn))/(framesData[en_index].frmn - framesData[st_index].frmn);
00746 jointsData[j].vect = BSplineInterp4 (st_joint.vect, en_joint.vect, tparam);
00747 jointsData[j].quat = SlerpQuaternion(st_joint.quat, en_joint.quat, tparam);
00748 }
00749 }
00750
00751 jointsData[j].joint = n;
00752 jointsData[j].index = frmnum;
00753 jointsData[j].vect.c = 1.0;
00754 jointsData[j].quat.c = 1.0;
00755 }
00756 }
00757
00758 return jointsData;
00759 }
00760
00761