Skip to content

Commit

Permalink
fixed issue with adaptive delta animation import
Browse files Browse the repository at this point in the history
  • Loading branch information
Tarcontar committed Jul 21, 2021
1 parent b15b560 commit bcd9aea
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 46 deletions.
17 changes: 10 additions & 7 deletions io_mesh_w3d/common/utils/animation_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ def set_keyframe(bone, channel, frame, value):
if is_visibility(channel):
set_visibility(bone, frame, value)
elif is_translation(channel):
print(f'translation : {value}')
set_translation(bone, channel.type, frame, value)
else:
set_rotation(bone, frame, value)
Expand All @@ -81,15 +80,19 @@ def apply_timecoded(bone, channel):


def apply_motion_channel_time_coded(bone, channel):
for dat in channel.data:
set_keyframe(bone, channel, dat.time_code, dat.value)
for datum in channel.data:
set_keyframe(bone, channel, datum.time_code, datum.value)


def apply_motion_channel_adaptive_delta(bone, channel):
data = decode(channel.type, channel.vector_len, channel.num_time_codes, channel.data.scale, channel.data.data)
for i in range(channel.num_time_codes):
set_keyframe(bone, channel, i, data[i])


def apply_adaptive_delta(bone, channel):
data = decode(channel)
print(f'apply channel {channel}')
data = decode(channel.type, channel.vector_len, channel.num_time_codes, channel.scale, channel.data)
for i in range(channel.num_time_codes):
print(data[i])
set_keyframe(bone, channel, i, data[i])


Expand Down Expand Up @@ -118,7 +121,7 @@ def process_motion_channels(context, hierarchy, channels, rig):
if channel.delta_type == 0:
apply_motion_channel_time_coded(obj, channel)
else:
apply_adaptive_delta(obj, channel)
apply_motion_channel_adaptive_delta(obj, channel)


def create_animation(context, rig, animation, hierarchy):
Expand Down
20 changes: 10 additions & 10 deletions io_mesh_w3d/w3d/adaptive_delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,24 +70,24 @@ def set_deltas(bytes, num_bits):
return result


def decode(channel):
def decode(channel_type, vector_len, num_time_codes, scale, data):
scale_factor = 1.0
if channel.data.bit_count == 8:
if data.bit_count == 8:
scale_factor /= 16.0

result = [None] * channel.num_time_codes
result[0] = channel.data.initial_value
result = [None] * num_time_codes
result[0] = data.initial_value

for i, delta_block in enumerate(channel.data.delta_blocks):
delta_scale = channel.scale * scale_factor * DELTA_TABLE[delta_block.block_index]
deltas = get_deltas(delta_block.delta_bytes, channel.data.bit_count)
for i, delta_block in enumerate(data.delta_blocks):
delta_scale = scale * scale_factor * DELTA_TABLE[delta_block.block_index]
deltas = get_deltas(delta_block.delta_bytes, data.bit_count)

for j, delta in enumerate(deltas):
idx = int(i / channel.vector_len) * 16 + j + 1
if idx >= channel.num_time_codes:
idx = int(i / vector_len) * 16 + j + 1
if idx >= num_time_codes:
break

if channel.type == 6:
if channel_type == 6:
# shift from wxyz to xyzw
index = (delta_block.vector_index + 1) % 4
value = result[idx - 1][index] + delta_scale * delta
Expand Down
27 changes: 5 additions & 22 deletions io_mesh_w3d/w3d/structs/compressed_animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ def read(io_stream, vec_index, bits):
block_index=read_ubyte(io_stream),
delta_bytes=[])

print(result.block_index)
result.delta_bytes = read_fixed_list(io_stream, bits * 2, read_byte)
return result

Expand All @@ -160,10 +159,7 @@ def read(io_stream, channel, bits):
bit_count=bits)

count = (channel.num_time_codes + 15) >> 4
print(result.initial_value)
print(count)

print('blocks:')
for _ in range(count):
for j in range(channel.vector_len):
result.delta_blocks.append(AdaptiveDeltaBlock.read(io_stream, j, bits))
Expand Down Expand Up @@ -197,18 +193,14 @@ def read(io_stream):
pivot=read_ushort(io_stream),
vector_len=read_ubyte(io_stream),
type=read_ubyte(io_stream),
scale=read_short(io_stream))
print('channel')
print(result.num_time_codes)
print(result.pivot)
print(result.vector_len)
print(result.type)
print(result.scale)
scale=read_float(io_stream))

result.data = AdaptiveDeltaData.read(io_stream, result, 4)
read_padding(io_stream, 3)
return result

def size(self, include_head=True):
size = const_size(13, include_head)
size = const_size(15, include_head)
size += self.data.size(self.type)
return size

Expand All @@ -218,7 +210,7 @@ def write(self, io_stream):
write_ushort(self.pivot, io_stream)
write_ubyte(self.vector_len, io_stream)
write_ubyte(self.type, io_stream)
write_short(self.scale, io_stream)
write_float(self.scale, io_stream)
self.data.write(io_stream, self.type)
write_padding(io_stream, 3)

Expand Down Expand Up @@ -413,19 +405,13 @@ def read(context, io_stream, chunk_end):

while io_stream.tell() < chunk_end:
chunk_type, chunk_size, _ = read_chunk_head(io_stream)
start_position = io_stream.tell()
print('#####')
if chunk_type == W3D_CHUNK_COMPRESSED_ANIMATION_HEADER:
result.header = CompressedAnimationHeader.read(io_stream)
elif chunk_type == W3D_CHUNK_COMPRESSED_ANIMATION_CHANNEL:
print(result.header.flavor)
if result.header.flavor == TIME_CODED_FLAVOR:
result.time_coded_channels.append(TimeCodedAnimationChannel.read(io_stream))
elif result.header.flavor == ADAPTIVE_DELTA_FLAVOR:
result.adaptive_delta_channels.append(AdaptiveDeltaAnimationChannel.read(io_stream))
#print(io_stream.tell() - (start_position + chunk_size))
while io_stream.tell() < (start_position + chunk_size):
read_byte(io_stream)
else:
skip_unknown_chunk(context, io_stream, chunk_type, chunk_size)
elif chunk_type == W3D_CHUNK_COMPRESSED_BIT_CHANNEL:
Expand All @@ -434,9 +420,6 @@ def read(context, io_stream, chunk_end):
result.motion_channels.append(MotionChannel.read(io_stream))
else:
skip_unknown_chunk(context, io_stream, chunk_type, chunk_size)

if start_position + chunk_size != io_stream.tell():
raise Exception('fucked up!')
return result

def size(self):
Expand Down
6 changes: 3 additions & 3 deletions tests/w3d/cases/structs/test_compressed_animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_write_read(self):
def test_write_read_adaptive_delta(self):
expected = get_compressed_animation(flavor=1)

self.assertEqual(3631, expected.size())
self.assertEqual(3639, expected.size())

io_stream = io.BytesIO()
expected.write(io_stream)
Expand Down Expand Up @@ -108,8 +108,8 @@ def test_chunk_sizes(self):
self.assertEqual(44, ani.header.size(False))

self.assertEqual(24, list_size(ani.time_coded_channels, False))
self.assertEqual(34, list_size(ani.adaptive_delta_channels, False))
self.assertEqual(36, list_size(ani.adaptive_delta_channels, False))
self.assertEqual(20, list_size(ani.time_coded_bit_channels, False))
self.assertEqual(24, list_size(ani.motion_channels, False))

self.assertEqual(154, ani.size())
self.assertEqual(156, ani.size())
14 changes: 12 additions & 2 deletions tests/w3d/cases/test_adaptive_delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,21 @@ def test_set_deltas_8bit(self):

self.assertEqual(expected, actual)

def test_decode(self):
def test_decode_channel_ad(self):
channel = get_adaptive_delta_animation_channel(type=0)
expected = [4.3611, 15.5264, 29.4832, 49.0226, 68.5621]

actual = decode(channel.type, channel.vector_len, channel.num_time_codes, channel.scale, channel.data)

self.assertEqual(len(expected), len(actual))
for i, value in enumerate(expected):
self.assertAlmostEqual(value, actual[i], 3)

def test_decode_motion_channel_ad(self):
channel = get_motion_channel(type=0, delta_type=1, num_time_codes=5)
expected = [4.3611, 4.6254, 4.9559, 5.4186, 5.8812]

actual = decode(channel)
actual = decode(channel.type, channel.vector_len, channel.num_time_codes, channel.data.scale, channel.data.data)

self.assertEqual(len(expected), len(actual))
for i, value in enumerate(expected):
Expand Down
4 changes: 2 additions & 2 deletions tests/w3d/helpers/compressed_animation.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def get_adaptive_delta_animation_channel(type, num_bits=4):
channel = AdaptiveDeltaAnimationChannel(
pivot=3,
type=type,
scale=2,
scale=3.14,
num_time_codes=5,
data=None)

Expand Down Expand Up @@ -253,7 +253,7 @@ def compare_adaptive_delta_animation_channels(self, expected, actual):
self.assertEqual(expected.pivot, actual.pivot)
self.assertEqual(expected.vector_len, actual.vector_len)
self.assertEqual(expected.type, actual.type)
self.assertEqual(expected.scale, actual.scale)
self.assertAlmostEqual(expected.scale, actual.scale, 5)
self.assertEqual(expected.num_time_codes, actual.num_time_codes)
compare_adaptive_delta_datas(
self, expected.data, actual.data, expected.type)
Expand Down
1 change: 1 addition & 0 deletions version_history.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ v0.6.6
- do not crash on animation import if channels reference non existing bones but inform user instead
- inform user on export if a mesh has no vertices and skip it
- Bugfix: do not crash if mesh has more shader structs than vertex materials
- Bugfix: read scale as float instead of short in 'AdaptiveDeltaAnimationChannel'

v0.6.5 (26.3.21)
- cancel export if a mesh and a bone share the same name and mesh is not configured properly
Expand Down

0 comments on commit bcd9aea

Please sign in to comment.