92 StartFrame(options.StartFrame),
93 EndFrame(options.EndFrame),
94 ReduceAnimation(options.ReduceAnimation),
95 ReduceAnimationPercent(options.ReduceAnimationPercent),
96 CompressAnimation(options.CompressAnimation),
97 CompressAnimationFlavor(options.CompressAnimationFlavor),
98 CompressAnimationTranslationError(options.CompressAnimationTranslationError),
99 CompressAnimationRotationError(options.CompressAnimationRotationError),
100 FrameRate(framerate),
140 StartFrame(options.StartFrame),
141 EndFrame(options.EndFrame),
142 ReduceAnimation(options.ReduceAnimation),
143 ReduceAnimationPercent(options.ReduceAnimationPercent),
144 CompressAnimation(options.CompressAnimation),
145 CompressAnimationFlavor(options.CompressAnimationFlavor),
146 CompressAnimationTranslationError(options.CompressAnimationTranslationError),
147 CompressAnimationRotationError(options.CompressAnimationRotationError),
148 FrameRate(framerate),
172void MotionClass::init(
void)
176 NumFrames = (EndFrame - StartFrame + 1);
186 if (MotionMatrix ==
NULL) {
190 EulerDelta =
new Point3 * [BasePose->Num_Nodes()];
191 if (EulerDelta ==
NULL) {
192 throw (ErrorClass(
"Out of Memory"));
195 for (i=0; i<BasePose->Num_Nodes(); i++) {
196 MotionMatrix[i] =
new Matrix3[NumFrames];
197 if (MotionMatrix[i] ==
NULL) {
198 throw (ErrorClass(
"Out of Memory"));
204 for (j=0; j<NumFrames; j++) {
205 MotionMatrix[i][j] = Matrix3(1);
209 for (i=0; i<BasePose->Num_Nodes(); i++) {
210 EulerDelta[i] =
new Point3[NumFrames];
211 if (EulerDelta[i] ==
NULL) {
212 throw (ErrorClass(
"Out of Memory"));
218 for (j=0; j<NumFrames; j++) {
219 EulerDelta[i][j] = Point3(0,0,0);
226 VisData =
new BooleanVectorClass[BasePose->Num_Nodes()];
228 for (i=0; i<BasePose->Num_Nodes(); i++) {
229 VisData[i].Resize(NumFrames);
234 for (j=0; j<NumFrames; j++) {
235 VisData[i][j] =
true;
242 BinMoveData =
new BooleanVectorClass[BasePose->Num_Nodes()];
244 for (i=0; i<BasePose->Num_Nodes(); i++) {
245 BinMoveData[i].Resize(NumFrames);
250 for (j=0; j<NumFrames; j++) {
251 BinMoveData[i][j] =
false;
262 NodeValidFlags.Resize(BasePose->Num_Nodes());
264 for (i=0; i<BasePose->Num_Nodes(); i++) {
265 NodeValidFlags[i] = 0;
271 for (i=0; i < NumFrames; i++) {
274 compute_frame_motion(i);
299 for (i=0; i<BasePose->Num_Nodes(); i++) {
300 if (MotionMatrix[i])
delete[] MotionMatrix[i];
303 delete[] MotionMatrix;
306 for (i=0; i<BasePose->Num_Nodes(); i++) {
307 if (EulerDelta[i])
delete[] EulerDelta[i];
318 delete[] BinMoveData;
338void MotionClass::compute_frame_motion(
int frame)
345 TimeValue frametime = (StartFrame + frame) * GetTicksPerFrame();
352 if (RootNode !=
NULL) {
355 tree =
new HierarchySaveClass(RootList,frametime,*Meter,
"NoName",
false,BasePose,Offset);
359 throw (ErrorClass(
"Out of memory!"));
365 for (
int tindex=0; tindex<tree->
Num_Nodes(); tindex++) {
371 int bindex = BasePose->Find_Named_Node(tree->
Get_Node_Name(tindex));
391 Matrix3 basetm = BasePose->Get_Node_Relative_Transform(bindex);
393 INode *tree_node = tree->
Get_Node(tindex);
395 Matrix3 motion = thistm *
Inverse(basetm);
399 set_motion_matrix(bindex,frame,motion);
405 float ex = my_eulers.Get_Angle(0);
406 float ey = my_eulers.Get_Angle(1);
407 float ez = my_eulers.Get_Angle(2);
409 set_eulers(bindex,frame,ex,ey,ez);
414 INode * node = tree->
Get_Node(tindex);
417 vis = (node->GetVisibility(frametime) > 0.0f);
421 set_visibility(bindex,frame,vis);
426 bool binary_move =
false;
434 TimeValue frametime_prev = frametime - GetTicksPerFrame();
435 TimeValue frametime_mid = (frametime + frametime_prev) / 2;
442 c = node->GetTMController()->GetPositionController();
453 smat1 = node->GetParentTM(frametime_prev);
454 c->GetValue(frametime_prev, &smat1, iValid, CTRL_RELATIVE);
457 smat2 = node->GetParentTM(frametime_mid);
458 c->GetValue(frametime_mid, &smat2, iValid, CTRL_RELATIVE);
461 smat3 = node->GetParentTM(frametime);
462 c->GetValue(frametime, &smat3, iValid, CTRL_RELATIVE);
464 if ((smat1 == smat2) && (!(smat2 == smat3))) {
466 DebugPrint(_T(
"Binary Move on Translation\n"));
469 if (
false == binary_move) {
470 c = node->GetTMController()->GetRotationController();
475 smat1 = node->GetParentTM(frametime_prev);
476 c->GetValue(frametime_prev, &smat1, iValid, CTRL_RELATIVE);
479 smat2 = node->GetParentTM(frametime_mid);
480 c->GetValue(frametime_mid, &smat2, iValid, CTRL_RELATIVE);
483 smat3 = node->GetParentTM(frametime);
484 c->GetValue(frametime, &smat3, iValid, CTRL_RELATIVE);
486 if ((smat1 == smat2) && (!(smat2 == smat3))) {
497 set_binary_movement(bindex, frame, binary_move);
521void MotionClass::set_motion_matrix(
int node,
int frame,
const Matrix3 & motion)
525 assert(node < BasePose->Num_Nodes());
526 assert(frame < NumFrames);
528 MotionMatrix[node][frame] = motion;
529 NodeValidFlags[node] = 1;
545Matrix3 MotionClass::get_motion_matrix(
int node,
int frame)
549 assert(node < BasePose->Num_Nodes());
550 assert(frame < NumFrames);
552 return MotionMatrix[node][frame];
568void MotionClass::set_eulers(
int node,
int frame,
float x,
float y,
float z)
599 px = get_eulers(node,frame - 1)[0];
600 py = get_eulers(node,frame - 1)[1];
601 pz = get_eulers(node,frame - 1)[2];
604 double mag0 = (x - px) * (x - px) + (y - py) * (y - py) + (z - pz) * (z - pz);
605 double mag1 = (x2 - px) * (x2 - px) + (y2 - py) * (y2 - py) + (z2 - pz) * (z2 - pz);
614 EulerDelta[node][frame].x = x;
615 EulerDelta[node][frame].y = y;
616 EulerDelta[node][frame].z = z;
617 NodeValidFlags[node] = 1;
633Point3 MotionClass::get_eulers(
int node,
int frame)
636 EulerDelta[node][frame].x,
637 EulerDelta[node][frame].y,
638 EulerDelta[node][frame].z
655void MotionClass::set_visibility(
int node,
int frame,
bool visible)
657 VisData[node][frame] = visible;
658 NodeValidFlags[node] = 1;
674bool MotionClass::get_visibility(
int node,
int frame)
676 return VisData[node][frame];
692void MotionClass::set_binary_movement(
int node,
int frame,
bool visible)
694 BinMoveData[node][frame] = visible;
711bool MotionClass::get_binary_movement(
int node,
int frame)
713 return BinMoveData[node][frame];
736 if (CompressAnimation) {
744 if (!save_header(csave)) {
748 if (!save_channels(csave)) {
777 if (CompressAnimation) {
783 W3dCompressedAnimHeaderStruct aheader;
789 aheader.
Flavor = CompressAnimationFlavor;
791 switch (CompressAnimationFlavor) {
804 if (csave.
Write(&aheader,
sizeof(aheader)) !=
sizeof(aheader)) {
821 W3dAnimHeaderStruct aheader;
828 if (csave.
Write(&aheader,
sizeof(aheader)) !=
sizeof(aheader)) {
856 int NumNodes = BasePose->Num_Nodes();
860 for (
int nodeidx = 0; nodeidx < BasePose->Num_Nodes(); nodeidx++) {
867 if (NodeValidFlags[nodeidx]) {
869 float identity[] = { 0.0f,0.0f,0.0f,1.0f };
871 VectorChannelClass xchan (nodeidx, NumFrames,
ANIM_CHANNEL_X, 1, identity);
872 VectorChannelClass ychan (nodeidx, NumFrames,
ANIM_CHANNEL_Y, 1, identity);
873 VectorChannelClass zchan (nodeidx, NumFrames,
ANIM_CHANNEL_Z, 1, identity);
874 VectorChannelClass xrchan(nodeidx, NumFrames,
ANIM_CHANNEL_XR, 1, identity);
875 VectorChannelClass yrchan(nodeidx, NumFrames,
ANIM_CHANNEL_YR, 1, identity);
876 VectorChannelClass zrchan(nodeidx, NumFrames,
ANIM_CHANNEL_ZR, 1, identity);
877 VectorChannelClass qchan (nodeidx, NumFrames,
ANIM_CHANNEL_Q, 4, identity);
879 xchan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
880 ychan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
881 zchan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
882 xrchan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
883 yrchan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
884 zrchan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
885 qchan.SetSaveOptions(CompressAnimation, CompressAnimationFlavor, CompressAnimationTranslationError, CompressAnimationRotationError, ReduceAnimation, ReduceAnimationPercent);
888 vischan.Set_Bits(VisData[nodeidx]);
890 BitChannelClass binmovechan(nodeidx, NumFrames, 0, 0);
891 binmovechan.Set_Bits(BinMoveData[nodeidx]);
893 for (
int frameidx = 0; frameidx < NumFrames; frameidx++) {
896 Matrix3 tm = get_motion_matrix(nodeidx,frameidx);
897 Point3 eulers = get_eulers(nodeidx,frameidx);
900 Point3 old_tran = tm.GetTrans();
907 DecomposeMatrix(tm,tran,rot,
scale);
921 xchan.Set_Vector(frameidx,vec);
927 ychan.Set_Vector(frameidx,vec);
933 zchan.Set_Vector(frameidx,vec);
939 xrchan.Set_Vector(frameidx,vec);
945 yrchan.Set_Vector(frameidx,vec);
951 zrchan.Set_Vector(frameidx,vec);
961 qchan.Set_Vector(frameidx,vec);
966 vischan.Set_Bit(frameidx,get_visibility(nodeidx,frameidx));
970 binmovechan.Set_Bit(frameidx, get_binary_movement(nodeidx, frameidx));
975 if (!vischan.Is_Empty()) {
977 if (!xchan.Is_Empty()) xchan.ClearInvisibleData(&vischan);
978 if (!ychan.Is_Empty()) ychan.ClearInvisibleData(&vischan);
979 if (!zchan.Is_Empty()) zchan.ClearInvisibleData(&vischan);
980 if (!qchan.Is_Empty()) qchan.ClearInvisibleData(&vischan);
984 if (!xchan.Is_Empty()) {
986 xchan.Save(csave, &binmovechan );
988 if (!ychan.Is_Empty()) {
990 ychan.Save(csave, &binmovechan );
992 if (!zchan.Is_Empty()) {
994 zchan.Save(csave, &binmovechan );
1003 if (!qchan.Is_Empty()) {
1005 qchan.Save(csave, &binmovechan);
1008 if (!vischan.Is_Empty()) {
1010 vischan.Save(csave, CompressAnimation);
Color scale(const Color &a, const Color &b)
#define W3D_CURRENT_HANIM_VERSION
@ ANIM_FLAVOR_ADAPTIVE_DELTA
#define W3D_CURRENT_COMPRESSED_HANIM_VERSION
@ W3D_CHUNK_COMPRESSED_ANIMATION_HEADER
@ W3D_CHUNK_COMPRESSED_ANIMATION
@ W3D_CHUNK_ANIMATION_HEADER
uint32 Write(const void *buf, uint32 nbytes)
bool Begin_Chunk(uint32 id)
static void rprintf(char *,...)
static void printf(char *,...)
static void updatebar(float position, float total)
Matrix3 Get_Node_Relative_Transform(int node) const
int Num_Nodes(void) const
const char * Get_Node_Name(int node) const
INode * Get_Node(int node) const
bool Save(ChunkSaveClass &csave)
MotionClass(IScene *scene, INode *rootnode, HierarchySaveClass *basepose, W3dExportOptionsStruct &options, int framerate, Progress_Meter_Class *meter, HWND MaxHwnd, char *name, Matrix3 &offset=Matrix3(1))
WWINLINE Quaternion Inverse(const Quaternion &a)
Matrix3 Cleanup_Orthogonal_Matrix(Matrix3 &mat)
void Set_W3D_Name(char *set_name, const char *src)