From 6704fc8b20d81a2f228f91b335a222dbbe0e1cb0 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Fri, 7 Jul 2017 02:18:40 +0200 Subject: [PATCH] d3drm: Initial support for storing animation keys. Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3drm/d3drm_private.h | 23 +++++ dlls/d3drm/frame.c | 187 ++++++++++++++++++++++++++++++++++++- dlls/d3drm/meshbuilder.c | 2 +- dlls/d3drm/tests/d3drm.c | 11 +-- 4 files changed, 211 insertions(+), 12 deletions(-) diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h index 1ce29e592ef..067c0e6ffeb 100644 --- a/dlls/d3drm/d3drm_private.h +++ b/dlls/d3drm/d3drm_private.h @@ -208,6 +208,24 @@ struct d3drm_material struct color_rgb ambient; }; +struct d3drm_animation_key +{ + D3DVALUE time; + union + { + D3DVECTOR position; + D3DVECTOR scale; + D3DRMQUATERNION rotate; + } u; +}; + +struct d3drm_animation_keys +{ + struct d3drm_animation_key *keys; + SIZE_T count; + SIZE_T size; +}; + struct d3drm_animation { struct d3drm_object obj; @@ -217,6 +235,9 @@ struct d3drm_animation IDirect3DRM *d3drm; IDirect3DRMFrame3 *frame; D3DRMANIMATIONOPTIONS options; + struct d3drm_animation_keys position; + struct d3drm_animation_keys scale; + struct d3drm_animation_keys rotate; }; struct d3drm_wrap @@ -282,4 +303,6 @@ static inline void d3drm_set_color(D3DCOLOR *color, float r, float g, float b, f d3drm_color_component(b), d3drm_color_component(a)); } +BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size) DECLSPEC_HIDDEN; + #endif /* __D3DRM_PRIVATE_INCLUDED__ */ diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c index f6b0a1fe14e..6d2dc141ae8 100644 --- a/dlls/d3drm/frame.c +++ b/dlls/d3drm/frame.c @@ -3095,6 +3095,9 @@ static ULONG WINAPI d3drm_animation2_Release(IDirect3DRMAnimation2 *iface) { d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj); IDirect3DRM_Release(animation->d3drm); + HeapFree(GetProcessHeap(), 0, animation->rotate.keys); + HeapFree(GetProcessHeap(), 0, animation->scale.keys); + HeapFree(GetProcessHeap(), 0, animation->position.keys); HeapFree(GetProcessHeap(), 0, animation); } @@ -3288,11 +3291,126 @@ static HRESULT WINAPI d3drm_animation1_SetOptions(IDirect3DRMAnimation *iface, D return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options); } +static SIZE_T d3drm_animation_lookup_key(const struct d3drm_animation_key *keys, + SIZE_T count, D3DVALUE time) +{ + SIZE_T start = 0, cur = 0, end = count; + + while (start < end) + { + cur = start + (end - start) / 2; + + if (time == keys[cur].time) + return cur; + + if (time < keys[cur].time) + end = cur; + else + start = cur + 1; + } + + return cur; +} + +static SIZE_T d3drm_animation_get_index_min(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time) +{ + SIZE_T i; + + i = d3drm_animation_lookup_key(keys, count, time); + while (i > 0 && keys[i - 1].time == time) + --i; + + return i; +} + +static SIZE_T d3drm_animation_get_index_max(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time) +{ + SIZE_T i; + + i = d3drm_animation_lookup_key(keys, count, time); + while (i < count - 1 && keys[i + 1].time == time) + ++i; + + return i; +} + +static SIZE_T d3drm_animation_get_insert_position(const struct d3drm_animation_keys *keys, D3DVALUE time) +{ + if (!keys->count || time < keys->keys[0].time) + return 0; + + if (time >= keys->keys[keys->count - 1].time) + return keys->count; + + return d3drm_animation_get_index_max(keys->keys, keys->count, time); +} + +static const struct d3drm_animation_key *d3drm_animation_get_range(const struct d3drm_animation_keys *keys, + D3DVALUE time_min, D3DVALUE time_max, SIZE_T *count) +{ + SIZE_T min, max; + + if (!keys->count || time_max < keys->keys[0].time + || time_min > keys->keys[keys->count - 1].time) + return NULL; + + min = d3drm_animation_get_index_min(keys->keys, keys->count, time_min); + max = d3drm_animation_get_index_max(&keys->keys[min], keys->count - min, time_max); + + *count = max - min + 1; + + return &keys->keys[min]; +} + static HRESULT WINAPI d3drm_animation2_AddKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key) { - FIXME("iface %p, key %p.\n", iface, key); + struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface); + struct d3drm_animation_keys *keys; + SIZE_T index; - return E_NOTIMPL; + TRACE("iface %p, key %p.\n", iface, key); + + if (!key || key->dwSize != sizeof(*key)) + return E_INVALIDARG; + + switch (key->dwKeyType) + { + case D3DRMANIMATION_POSITIONKEY: + keys = &animation->position; + break; + case D3DRMANIMATION_SCALEKEY: + keys = &animation->scale; + break; + case D3DRMANIMATION_ROTATEKEY: + keys = &animation->rotate; + break; + default: + return E_INVALIDARG; + } + + index = d3drm_animation_get_insert_position(keys, key->dvTime); + + if (!d3drm_array_reserve((void **)&keys->keys, &keys->size, keys->count + 1, sizeof(*keys->keys))) + return E_OUTOFMEMORY; + + if (index < keys->count) + memmove(&keys->keys[index + 1], &keys->keys[index], sizeof(*keys->keys) * (keys->count - index)); + keys->keys[index].time = key->dvTime; + switch (key->dwKeyType) + { + case D3DRMANIMATION_POSITIONKEY: + keys->keys[index].u.position = key->u.dvPositionKey; + break; + case D3DRMANIMATION_SCALEKEY: + keys->keys[index].u.scale = key->u.dvScaleKey; + break; + case D3DRMANIMATION_ROTATEKEY: + keys->keys[index].u.rotate = key->u.dqRotateKey; + break; + } + ++keys->count; + + return D3DRM_OK; } static HRESULT WINAPI d3drm_animation2_AddRotateKey(IDirect3DRMAnimation2 *iface, D3DVALUE time, D3DRMQUATERNION *q) @@ -3484,9 +3602,70 @@ static HRESULT WINAPI d3drm_animation2_ModifyKey(IDirect3DRMAnimation2 *iface, D static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max, DWORD *key_count, D3DRMANIMATIONKEY *keys) { - FIXME("iface %p, time min %.e, time max %.e, count %p, keys %p.\n", iface, time_min, time_max, key_count, keys); + struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface); + const struct d3drm_animation_key *key; + SIZE_T count, i; - return E_NOTIMPL; + TRACE("iface %p, time min %.8e, time max %.8e, key_count %p, keys %p.\n", + iface, time_min, time_max, key_count, keys); + + if (!key_count) + return D3DRMERR_BADVALUE; + + *key_count = 0; + + if ((key = d3drm_animation_get_range(&animation->rotate, time_min, time_max, &count))) + { + if (keys) + { + for (i = 0; i < count; ++i) + { + keys[i].dwSize = sizeof(*keys); + keys[i].dwKeyType = D3DRMANIMATION_ROTATEKEY; + keys[i].dvTime = key[i].time; + keys[i].dwID = 0; /* FIXME */ + keys[i].u.dqRotateKey = key[i].u.rotate; + } + keys += count; + } + *key_count += count; + } + + if ((key = d3drm_animation_get_range(&animation->position, time_min, time_max, &count))) + { + if (keys) + { + for (i = 0; i < count; ++i) + { + keys[i].dwSize = sizeof(*keys); + keys[i].dwKeyType = D3DRMANIMATION_POSITIONKEY; + keys[i].dvTime = key[i].time; + keys[i].dwID = 0; /* FIXME */ + keys[i].u.dvPositionKey = key[i].u.position; + } + keys += count; + } + *key_count += count; + } + + if ((key = d3drm_animation_get_range(&animation->scale, time_min, time_max, &count))) + { + if (keys) + { + for (i = 0; keys && i < count; ++i) + { + keys[i].dwSize = sizeof(*keys); + keys[i].dwKeyType = D3DRMANIMATION_SCALEKEY; + keys[i].dvTime = key[i].time; + keys[i].dwID = 0; /* FIXME */ + keys[i].u.dvScaleKey = key[i].u.scale; + } + keys += count; + } + *key_count += count; + } + + return *key_count ? D3DRM_OK : D3DRMERR_NOSUCHKEY; } static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl = diff --git a/dlls/d3drm/meshbuilder.c b/dlls/d3drm/meshbuilder.c index e8e7f7e0f23..bb376787856 100644 --- a/dlls/d3drm/meshbuilder.c +++ b/dlls/d3drm/meshbuilder.c @@ -260,7 +260,7 @@ char templates[] = { "}" }; -static BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size) +BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size) { SIZE_T new_capacity, max_capacity; void *new_elements; diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c index 5fea2f04597..f19558e2484 100644 --- a/dlls/d3drm/tests/d3drm.c +++ b/dlls/d3drm/tests/d3drm.c @@ -6885,11 +6885,8 @@ static void test_animation(void) /* Key management. */ hr = IDirect3DRMAnimation_AddPositionKey(animation, 0.0f, 1.0f, 0.0f, 0.0f); -todo_wine ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr); -if (hr == S_OK) -{ hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f); ok(SUCCEEDED(hr), "Failed to add scale key, hr %#x.\n", hr); @@ -6940,6 +6937,8 @@ if (hr == S_OK) { ok(keys[i].dwSize == sizeof(*keys), "%u: unexpected dwSize value %u.\n", i, keys[i].dwSize); + todo_wine + { switch (keys[i].dwKeyType) { case D3DRMANIMATION_ROTATEKEY: @@ -6955,6 +6954,7 @@ if (hr == S_OK) ok(0, "%u: unknown key type %d.\n", i, keys[i].dwKeyType); } } + } /* No keys in this range. */ count = 10; @@ -6970,17 +6970,14 @@ if (hr == S_OK) count = 10; hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 0.0f, &count, NULL); ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr); - ok(hr == S_OK, "Failed to get animation keys, hr %#x.\n", hr); ok(count == 4, "Unexpected key count %u.\n", count); hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, NULL, NULL); ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr); /* Time is 0-based. */ - count = 123; hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, NULL, NULL); ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr); - ok(count == 123, "Unexpected key count %u.\n", count); count = 10; hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, &count, NULL); @@ -7018,7 +7015,7 @@ if (hr == S_OK) key.dwKeyType = D3DRMANIMATION_POSITIONKEY; hr = IDirect3DRMAnimation2_AddKey(animation2, &key); ok(SUCCEEDED(hr), "Failed to add key, hr %#x.\n", hr); -} + IDirect3DRMAnimation2_Release(animation2); IDirect3DRMAnimation_Release(animation);