49#define FILTER_TABLE_SIZE (256)
50#define FILTER_TABLE_GEN_START (16)
51#define FILTER_TABLE_GEN_SIZE (FILTER_TABLE_SIZE - FILTER_TABLE_GEN_START)
72static bool table_valid =
false;
86 VectorLen(vectorlength),
92 ReduceAnimation(
false),
93 ReduceAnimationPercent(0),
94 CompressAnimation(
false),
95 CompressAnimationFlavor(0),
96 CompressAnimationTranslationError(0.0f),
97 CompressAnimationRotationError(0.0f)
100 assert(VectorLen > 0);
101 IdentVect =
new float32[VectorLen];
102 Data =
new float32[MaxFrames * VectorLen];
106 memcpy(IdentVect,identvect,VectorLen *
sizeof(
float32));
107 memset(Data,0,MaxFrames * VectorLen *
sizeof(
float32));
114 if (
false == table_valid) {
146 assert(frameidx >= 0);
147 assert(frameidx < MaxFrames);
149 for (
int vi=0; vi<VectorLen; vi++) {
150 set_value(frameidx,vi,vector[vi]);
153 if (!is_identity(vector)) {
160 assert(frameidx >= 0);
161 assert(frameidx < MaxFrames);
163 return &(Data[frameidx * VectorLen]);
171 channelsize += packetsize * MaxFrames;
172 channelsize -=
sizeof(
uint32);
189 for (
int fcount=0; fcount < MaxFrames; fcount++, fidx += (VectorLen+1) ) {
194 pivec = &chn->
Data[ fidx ];
195 pfvec = (
float32 *) (pivec + 1);
201 bool binary_move = binmov->
Get_Bit( fcount );
204 if (fcount != Begin) {
216 for (
int vidx=0; vidx < VectorLen; vidx++) {
218 pfvec[vidx] = get_value(fcount,vidx);
224 VectorChannelClass::compress( chn );
228 float original_channelsize = channelsize;
230 channelsize =
sizeof(W3dTimeCodedAnimChannelStruct);
232 channelsize -=
sizeof(
uint32);
234 float percent = (((float)channelsize) / original_channelsize) * 100.0f;
239 if (csave.
Write(chn,channelsize) != channelsize) {
274 unsigned char d0 : 4;
275 unsigned char d1 : 4;
276 unsigned char d2 : 4;
277 unsigned char d3 : 4;
278 unsigned char d4 : 4;
279 unsigned char d5 : 4;
280 unsigned char d6 : 4;
281 unsigned char d7 : 4;
282 unsigned char d8 : 4;
283 unsigned char d9 : 4;
304float VectorChannelClass::test_compress(
int filter_index,
float scale,
float value1,
float *indata,
float *outdata)
315 float last_value = value1;
317 for(
int data_idx=0; data_idx < 16; data_idx++) {
323 int best_factor = 100;
324 float least_error = 999999999.9f;
325 for (
float try_factor = -8.0f; try_factor < 8.0f; try_factor+=1.0f) {
326 float temp = (try_factor *
filter) + last_value;
327 temp-=indata[data_idx];
329 if (temp < least_error) {
331 best_factor = try_factor;
334 assert(best_factor <= 7);
335 assert(best_factor >=-8);
337 float dfactor = best_factor;
339 outdata[data_idx] = (dfactor *
filter) + last_value;
342 float delta = outdata[data_idx] - indata[data_idx];
345 error+= (delta * delta);
347 last_value = outdata[data_idx];
350 return( sqrt(error) );
365float VectorChannelClass::compress(
int filter_index,
float scale,
float value1,
float *indata,
unsigned char *pPacket,
float *outdata)
375 *pPacket = filter_index;
378 float last_value = value1;
380 for(
int data_idx=0; data_idx < 16; data_idx++) {
386 int best_factor = 100;
387 float least_error = 999999999.9f;
388 for (
float try_factor = -8.0f; try_factor < 8.0f; try_factor+=1.0f) {
389 float temp = (try_factor *
filter) + last_value;
390 temp-=indata[data_idx];
392 if (temp < least_error) {
394 best_factor = try_factor;
397 assert(best_factor <= 7);
398 assert(best_factor >=-8);
400 float dfactor = best_factor;
402 outdata[data_idx] = (dfactor *
filter) + last_value;
404 int pi = data_idx>>1;
409 pPacket[pi]|=best_factor;
414 pPacket[pi]|=best_factor;
420 error+=fabs(outdata[data_idx] - indata[data_idx]);
422 last_value = outdata[data_idx];
433 uint32 channelsize =
sizeof(W3dAdaptiveDeltaAnimChannelStruct);
435 int numpackets = (MaxFrames + 15) / 16;
436 channelsize += packetsize * numpackets * VectorLen;
437 channelsize -=
sizeof(char);
438 channelsize += VectorLen *
sizeof(float);
440 W3dAdaptiveDeltaAnimChannelStruct * chn = (W3dAdaptiveDeltaAnimChannelStruct *)malloc(channelsize);
449 chn->NumFrames = MaxFrames;
451 chn->VectorLen = VectorLen;
454 memset(&chn->Data[0], channelsize - (
sizeof(W3dAdaptiveDeltaAnimChannelStruct) -
sizeof(
char)), 0x00);
456 assert(VectorLen <= 4);
458 float *initial = (
float *)&chn->Data[0];
462 for (
int i=0; i < VectorLen; i++) {
463 work[i] = initial[i] = get_value(0, i);
466 float original_packet[16];
467 float decompressed_packet[16];
469 float last_value=0.0f;
475 for (
int fidx=1; fidx < MaxFrames; fidx++) {
476 for (i=0; i<VectorLen; i++) {
478 delta = fabs( get_value(fidx, i) - get_value(fidx - 1, i));
489 for (i=0; i < numpackets; i++) {
490 for (
int vi=0; vi<VectorLen; vi++) {
491 last_value = work[vi];
493 int temp_frame = frame;
495 for(
int gi=0; gi<16; gi++) {
497 if (temp_frame < MaxFrames) {
498 last_value = original_packet[gi] = get_value(temp_frame, vi);
501 original_packet[gi] = last_value;
511 float least_error = 999999999.9f;
512 last_value = work[vi];
516 float temp_error = test_compress(try_filter,
scale, last_value, original_packet, decompressed_packet);
518 if (temp_error < least_error) {
519 best_filter = try_filter;
520 least_error = temp_error;
531 unsigned char * pPacket;
533 pPacket = (
unsigned char *) &chn->Data[0];
534 pPacket+= (VectorLen *
sizeof(float));
538 compress(best_filter,
scale, last_value, original_packet, pPacket, decompressed_packet);
541 work[vi] = decompressed_packet[15];
549 float rawsize =
sizeof(W3dAnimChannelStruct);
550 rawsize += (VectorLen *
sizeof(
float32) * (MaxFrames)) -
sizeof(
float32);
552 float percent = ((float)channelsize) / rawsize;
561 if (csave.
Write(chn,channelsize) != channelsize) {
580 if (IsEmpty)
return true;
588 if (CompressAnimation) {
596 switch (CompressAnimationFlavor)
600 return(SaveTimeCoded(csave, binmov));
607 return(SaveAdaptiveDelta(csave, binmov));
627 channelsize += VectorLen *
sizeof(
float32) * (MaxFrames) -
sizeof(
float32);
641 for (
int fcount=0; fcount < End-Begin+1; fcount++) {
642 for (
int vidx=0; vidx < VectorLen; vidx++) {
644 int writeidx = fcount * VectorLen + vidx;
646 chn->
Data[writeidx] = get_value(Begin + fcount,vidx);
650 if (csave.
Write(chn,channelsize) != channelsize) {
670 ReduceAnimation = reduce;
671 ReduceAnimationPercent = reduce_percent;
672 CompressAnimation = compress;
673 CompressAnimationFlavor = flavor;
674 CompressAnimationTranslationError = Terr;
675 CompressAnimationRotationError =
DEG_TO_RAD(Rerr);
688 assert(VectorLen <= 8);
690 bool prev_state = vis->
Get_Bit( 0 );
694 for (
int idx=0; idx < MaxFrames; idx++) {
696 bool cur_state = vis->
Get_Bit( idx );
698 if (cur_state != prev_state) {
699 prev_state = cur_state;
703 if (
false == cur_state) {
711void VectorChannelClass::set_value(
int framenum,
int vindex,
float32 val)
713 assert(framenum >= 0);
714 assert(framenum < MaxFrames);
716 assert(vindex < VectorLen);
718 Data[framenum * VectorLen + vindex] = val;
721float32 VectorChannelClass::get_value(
int framenum,
int vindex)
723 assert(framenum >= 0);
724 assert(framenum < MaxFrames);
726 assert(vindex < VectorLen);
728 return Data[framenum * VectorLen + vindex];
731bool VectorChannelClass::is_identity(
float32 * vec)
733 const double ERROR_TOLERANCE = 0.00005 * 0.00005;
736 for (
int vi=0; vi<VectorLen; vi++) {
737 dist += (vec[vi] - IdentVect[vi])*(vec[vi] - IdentVect[vi]);
741 if (dist < ERROR_TOLERANCE) {
748void VectorChannelClass::compute_range(
void)
751 while ((Begin < MaxFrames) && (is_identity(
Get_Vector(Begin)))) {
756 while ((End >= 0) && (is_identity(
Get_Vector(End)))) {
775 dst = (
uint32 *) &c->
Data[ packet_size * packet_idx ];
776 src = (
uint32 *) &c->Data[ packet_size * (packet_idx + 1) ];
778 uint32 copy_length = (c->NumTimeCodes - (packet_idx + 1)) * packet_len;
782 memcpy(dst, src, copy_length);
803 double Terr = CompressAnimationTranslationError;
804 double Rerr = CompressAnimationRotationError;
816 uint32 idx = find_useless_packet( c, Terr );
820 remove_packet( c, idx );
833 uint32 idx = find_useless_packet( c, Rerr );
837 remove_packet( c, idx );
848 uint32 idx = find_useless_packetQ( c, Rerr );
852 remove_packet( c, idx );
866 if (ReduceAnimation) {
867 if (ReduceAnimationPercent) {
869 float pct = ReduceAnimationPercent;
876 if (pct <= 0.0f)
return;
877 if (pct >= 1.0f)
return;
885 if (maxFrames < 2) maxFrames = 2;
899 while(maxFrames < c->NumTimeCodes) {
901 uint32 idx = find_least_useful_packet( c );
903 remove_packet( c, idx );
911 while(maxFrames < c->NumTimeCodes) {
913 uint32 idx = find_least_useful_packetQ( c );
915 remove_packet( c, idx );
946#define MAX_VECTOR_SIZE 8
958 float32 *pVecSrc, *pVecDst, *pVecOriginal;
959 uint32 *pTcSrc, *pTcDst, *pTcOriginal;
964 pTcSrc = (
uint32 *) &c->
Data[ try_idx * packet_size ];
965 pVecSrc = (
float32 *) pTcSrc+1;
968 pTcOriginal = (
uint32 *) &c->
Data[ (try_idx + 1) * packet_size ];
969 pVecOriginal = (
float32 *) pTcOriginal+1;
972 pTcDst = (
uint32 *) &c->
Data[ (try_idx + 2 ) * packet_size ];
973 pVecDst = (
float32 *) pTcDst+1;
986 float32 tStart = ((*pTcSrc) & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
987 float32 tRecreate = *pTcOriginal;
989 float32 tRatio = (tRecreate - tStart) / (tEnd - tStart);
993 tempvec[ idx ] =
WWMath::Lerp(pVecSrc[idx], pVecDst[idx], tRatio);
999 bool close_enough =
true;
1001 for (idx=0; idx < c->
VectorLen; idx++) {
1005 delta = fabs(pVecOriginal[idx] - tempvec[idx]);
1007 if (delta > tolerance) {
1008 close_enough =
false;
1017 if (
true == close_enough) {
1018 return (try_idx + 1);
1034 bool identical =
true;
1042 delta = fabs(pVecDst[idx] - pVecSrc[idx]);
1044 if (delta > tolerance) {
1051 if (identical)
return( 1 );
1082 float32 *pVecSrc, *pVecDst, *pVecOrg;
1083 uint32 *pTcSrc, *pTcDst, *pTcOrg;
1088 pTcSrc = (
uint32 *) &c->
Data[ try_idx * packet_size ];
1089 pVecSrc = (
float32 *) pTcSrc+1;
1092 pTcOrg = (
uint32 *) &c->
Data[ (try_idx + 1) * packet_size ];
1093 pVecOrg = (
float32 *) pTcOrg+1;
1096 pTcDst = (
uint32 *) &c->
Data[ (try_idx + 2 ) * packet_size ];
1097 pVecDst = (
float32 *) pTcDst+1;
1110 float32 tStart = ((*pTcSrc) & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
1113 float32 tRatio = (tRecreate - tStart) / (tEnd - tStart);
1117 qSrc.Set(pVecSrc[0],pVecSrc[1],pVecSrc[2],pVecSrc[3]);
1120 qOrg.Set(pVecOrg[0],pVecOrg[1],pVecOrg[2],pVecOrg[3]);
1123 qDst.Set(pVecDst[0],pVecDst[1],pVecDst[2],pVecDst[3]);
1125 Quaternion
q =
Slerp( qSrc, qDst, tRatio );
1127 Quaternion Delta(1);
1130 double angle = acosf( fabs( Delta.W ) ) * 2.0;
1132 if (angle <= tolerance ) {
1133 return (try_idx + 1);
1154 qSrc.Set(pVecSrc[0], pVecSrc[1], pVecSrc[2], pVecSrc[3]);
1157 qDst.Set(pVecDst[0], pVecDst[1], pVecDst[2], pVecDst[3]);
1159 Quaternion Delta(1);
1162 double angle = acosf( fabs( Delta.W ) ) * 2.0;
1164 if (angle <= tolerance ) {
1195 double leasterror = 9999999.0f;
1201 float32 *pVecSrc, *pVecDst, *pVecOriginal;
1202 uint32 *pTcSrc, *pTcDst, *pTcOriginal;
1207 pTcSrc = (
uint32 *) &c->
Data[ try_idx * packet_size ];
1208 pVecSrc = (
float32 *) pTcSrc+1;
1211 pTcOriginal = (
uint32 *) &c->
Data[ (try_idx + 1) * packet_size ];
1212 pVecOriginal = (
float32 *) pTcOriginal+1;
1215 pTcDst = (
uint32 *) &c->
Data[ (try_idx + 2 ) * packet_size ];
1216 pVecDst = (
float32 *) pTcDst+1;
1229 float32 tStart = ((*pTcSrc) & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
1230 float32 tRecreate = *pTcOriginal;
1232 float32 tRatio = (tRecreate - tStart) / (tEnd - tStart);
1236 tempvec[ idx ] =
WWMath::Lerp(pVecSrc[idx], pVecDst[idx], tRatio);
1245 for (idx=0; idx < c->
VectorLen; idx++) {
1249 tmp = pVecOriginal[idx] - tempvec[idx];
1251 delta += (tmp * tmp);
1255 delta = sqrtf( delta );
1257 if (delta < leasterror)
1263 ret_idx =(try_idx + 1);
1307 double leasterror = 9999999.0f;
1313 float32 *pVecSrc, *pVecDst, *pVecOrg;
1314 uint32 *pTcSrc, *pTcDst, *pTcOrg;
1319 pTcSrc = (
uint32 *) &c->
Data[ try_idx * packet_size ];
1320 pVecSrc = (
float32 *) pTcSrc+1;
1323 pTcOrg = (
uint32 *) &c->
Data[ (try_idx + 1) * packet_size ];
1324 pVecOrg = (
float32 *) pTcOrg+1;
1327 pTcDst = (
uint32 *) &c->
Data[ (try_idx + 2 ) * packet_size ];
1328 pVecDst = (
float32 *) pTcDst+1;
1341 float32 tStart = ((*pTcSrc) & ~W3D_TIMECODED_BINARY_MOVEMENT_FLAG);
1344 float32 tRatio = (tRecreate - tStart) / (tEnd - tStart);
1348 qSrc.Set(pVecSrc[0],pVecSrc[1],pVecSrc[2],pVecSrc[3]);
1351 qOrg.Set(pVecOrg[0],pVecOrg[1],pVecOrg[2],pVecOrg[3]);
1354 qDst.Set(pVecDst[0],pVecDst[1],pVecDst[2],pVecDst[3]);
1356 Quaternion
q =
Slerp( qSrc, qDst, tRatio );
1358 Quaternion Delta(1);
1361 double angle = acosf( fabs( Delta.W ) ) * 2;
1363 if (angle < leasterror ) {
1365 ret_idx = (try_idx + 1);
Color scale(const Color &a, const Color &b)
@ ANIM_FLAVOR_ADAPTIVE_DELTA
#define W3D_TIMECODED_BINARY_MOVEMENT_FLAG
@ W3D_CHUNK_COMPRESSED_ANIMATION_CHANNEL
@ W3D_CHUNK_ANIMATION_CHANNEL
WWINLINE int Get_Bit(int frame) const
uint32 Write(const void *buf, uint32 nbytes)
bool Begin_Chunk(uint32 id)
static void printf(char *,...)
VectorChannelClass(uint32 id, int maxframes, uint32 flags, int vectorlength, float32 *identvec)
float * Get_Vector(int frameidx)
void ClearInvisibleData(BitChannelClass *vis)
void SetSaveOptions(bool compress, int flavor, float Terr, float Rerr, bool reduce, int reduce_percent)
void Set_Vector(int framenumber, float32 *vector)
bool Save(ChunkSaveClass &csave, BitChannelClass *binmov)
~VectorChannelClass(void)
static float Lerp(float a, float b, float lerp)
#define FILTER_TABLE_SIZE
#define FILTER_TABLE_GEN_START
#define FILTER_TABLE_GEN_SIZE
void Slerp(Quaternion &res, const Quaternion &p, const Quaternion &q, float alpha)
WWINLINE Quaternion Inverse(const Quaternion &a)
struct @125103322152314045032077201241336000106237244067 AdaptiveDeltaPacketStruct
#define PACKETS_ALL_USEFUL