Slides
1.2 — Movimiento a través de una curva
1.3 — Sistemas keyframe
1.4 — Deformación de objetos
2.1 — Cinemática directa
2.2 — Cinemática inversa
3.1 — Animación Humana
3.2 — Animación Facial
Tema 1.1 — Interpolación
Ejercicio 1.1.1
Escribe una función de MATLAB para visualizar los polinomios base de Hermite de grado 3.
function plot_hermite_basis() figure; hold on; grid on; % Rango x = 0:0.0001:1; H0 = 2*x.^3 - 3*x.^2 +1 ; plot(x,H0); % Completar... hold off; endSolución
Ejercicio 1.1.2
Calcula el polinomio de Hermite P(x)
tal que P(0) = 1
, P(1) = 1
, P'(0) = 0
, P'(1) = 1
. Implementa una función en MATLAB para visualizar el resultado.
function hermite_interpolation_demo() figure; hold on; % Completar ... plot(x,y); hold off; endSolución
Ejercicio 1.1.3
Calcula el polinomio interpolador de Lagrange de la siguiente tabla. Escribe una función de MATLAB que dibuje cada uno de los polinomios interpoladores y el polinomio resultante.
x -9 -4 -1 7
y 5 2 -2 9
El resultado debe ser algo parecido a esto.
¿Cuál es el valor del primer polinomio interpolador en x=-4
, x=-1
y x=7
?
¿Cuál es el valor del segundo polinomio interpolador en x=-9
, x=-1
y x=7
?
¿Cuál es el valor del tercer polinomio interpolador en x=-9
, x=-4
y x=7
?
¿Cuál es el valor del cuarto polinomio interpolador en x=-9
, x=-4
y x=-1
?
Solución
Ejercicio 1.1.4
Interpolar y dibujar en MATLAB con splines lineales la función f(x) = 1 / x
en los puntos en los que x
vale 1, 2 y 4
.
Solución
Ejercicio 1.1.5
Interpolar y dibujar en MATLAB con splines quadráticas (grado 2) la función f(x)
que pasa por los puntos f(3) = 2.5; f(4.5) = 1; f(7) = 2.5; f(9)=0.5
. Utiliza la función de MATLAB X = linsolve(A,b)
o el operador X = A\b
para resolver el sistema de ecuaciones.
Se trata de un sistema indeterminado, con más incognitas que ecuaciones. ¿Qué se puede hacer en estos casos? Calcula por lo menos 2 posibles soluciones del sistema, y dibuja las splines resultantes en MATLAB.
Solución
Ejercicio 1.1.6
Utilizando como referencia la función bezier_linear()
de más abajo que dibuja una bezier_quadratic()
y bezier_cubic()
que calculen y dibujen curvas cuadráticas y cúbicas.
Modifica el tercer parámetro de la función linspace
y observa como cambian las curvas dibujadas. ¿Qué controla este parámetro?
function placelabel(pt,str)
x = pt(1);
y = pt(2);
h = line(x,y);
h.Marker = '*';
h = text(x,y,str);
h.HorizontalAlignment = 'center';
h.VerticalAlignment = 'bottom';
end
function bezier_linear()
figure;
hold on
pt1 = [ 5;-10];
pt2 = [45; 15];
placelabel(pt1,' pt_1');
placelabel(pt2,' pt_2');
xlim([0 50])
axis equal
% Crea un vector de 100 valores equidistantes entre 0 y 1
t = linspace(0,1,100);
% Evalua la funcion (1-t) * pt1 + t * pt2 en todos los puntos t
pts = kron((1-t),pt1) + kron(t,pt2);
% Metodo alternativo
%pts = [];
%for t=0:0.2:1
% pts = [pts ((1-t) * pt1 + t * pt2)];
%end
plot(pts(1,:), pts(2,:));
hold off;
end
Ejercicio 1.1.7 – Entrega el 8 de Octubre 2019, 23:59
Dibuja en MATLAB un curva cerrada con continuidad C1 creada por 4 curvas cúbicas de Bezier. Utiliza transformaciones del tipo translación y escalado en los puntos de control para cambiar el tamaño la curva dibujada. Aquí tienes un ejemplo del tipo de resultado que puedes conseguir.
Ejercicio 1.1.8 – Entrega el 8 de Octubre 2019, 23:59
Crea una imagen en la que aparezca una letra cualquiera (ejemplo), y cárgala como imagen de fondo de un figure
como se hace en el principio de la función function bezier_over_letter()
que se muestra a continuación. Completa el resto de la función de manera que la silueta de la letra se aproxime mediante curvas de Bezier cúbicas.
Una vez tengas todas curvas necesarias, escálalas para obtener la misma letra más grande y más pequeña.
function bezier_over_letter() cla img = imread('d.jpg'); % actualizar path a imagen image('CData',img,'XData',[-100 100],'YData',[100 -100]) xlim([-100 100]) ylim([-100 100]) axis equal grid on; hold on; % completar hold off; end
Ejercicio 1.1.9 – Entrega el 8 de Octubre 2019, 23:59
Desarrolla una función draw_bezier_surface.m
que dibuje una superficie de Bezier cuadrática.
Tema 1.2 — Movimiento a través de una curva
Ejercicio 1.2.1
Escribe una funcion en MATLAB llamada compute_arc_length_cubic_bezier(pt1, pt2, pt3, pt4, samples)
que calcule mediante Forward Differencing la longitud del arco de una curva cúbica de Bezier. ¿Cómo cambia el resultado en función del parámetro samples
?
Solución
Ejercicio 1.2.2
Escribe una función en MATLAB que dados 4 puntos de control, calcule su curva de Bezier y marque sobre ella: puntos equidistantes con respecto el parámetro t
(tiempo) y con respecto el parámetro s
(longitud del arco). El resultado final debería ser parecido a esto.
Solución
Tema 1.4 — Deformación de objectos
Ejercicio 1.4.1
Descarga este .zip y desarrolla la función warpForward()
para warpear la imagen test3.jpg
de manera que se alinee con la imagen test4.jpg
. Usa la técnica de forward warping.
El resultado que consigues, ¿es el esperado?. Si observas algún artefacto visual, ¿sabes a que se debe?
SoluciónEjercicio 1.4.2
Usa el mismo arquivo inicial que el ejercicio anterior y desarrolla una función warpBackward()
para warpear la imagen test3.jpg
de manera que se alinee con la imagen test4.jpg
, usando la técnica de backward warping.
¿Mejoran los resultados?
SoluciónEjercicio 1.4.3
Completa la función incrementalWarpingForward.m
para crear una animación de morphing entre la imagen test3.jpg y test4.jpg, usando la técnica de forward warping. Después escribe la funcion incrementalWarpingBackward.m
para la técnica backward warping. El resultado debería parecertese a este.
Tema 2.1 — Cinemática directa
Ejercicio 2.1.1
Desarrolla la función plot_skeleton(skeleton, rots)
en MATLAB que dibuje mediante la técnica de Cinemática Directa la estructura jerárquica inicializada a continuación.
function skeleton_demo() close all; trans0 = [0,0]; trans1 = [-1,-1]; % Offset con respecto joint 0 trans2 = [0,-1]; % Offset con respecto joint 1 trans3 = [0,-1]; % Offset con respecto joint 2 rot1 = 0; % Rotacion local del joint 0 rot2 = 0; % Rotacion local del joint 0 rot3 = 0; % Rotacion local del joint 0 skeleton = [trans0; trans1; trans2; trans3]; rots = [rot1 rot2 rot3]; figure; hold on; grid on; axis equal; xlim([-5 5]); ylim([-5 5]); plot_skeleton(skeleton, rots); % Acaba de desarrollar esta función hold off; end
function plot_skeleton(skeleton, rots) rot1 = rots(1); rot2 = rots(2); rot3 = rots(3); % Aplicamos nodo 0 rot0_matrix = [ 1 0 0; 0 1 0; 0 0 1]; trans0_matrix = [1 0 skeleton(1,1); 0 1 skeleton(1,2); 0 0 1]; pos = rot0_matrix * trans0_matrix; scatter(pos(1,3), pos(2,3),300,'o','filled'); % Aplicamos nodo 1 rot1_matrix = [ +cosd(rot1) -sind(rot1) 0; +sind(rot1) +cosd(rot1) 0; 0 0 1 ]; trans1_matrix = [1 0 skeleton(2,1); 0 1 skeleton(2,2); 0 0 1]; old_pos = pos; pos = rot0_matrix * trans0_matrix ... * rot1_matrix * trans1_matrix ; scatter(pos(1,3), pos(2,3),300,'o','filled'); line([pos(1,3),old_pos(1,3)],[pos(2,3),old_pos(2,3)], 'LineWidth', 2); % Desarrolla el código para pintar el resto de la cadena endSolución
Ejercicio 2.1.2
Cambia los valores de los parámetros del vector rots
y observa como cambia la posición de la cadena. Consigue articulaciones parecidas a estas: ejemplo1, ejemplo2, ejemplo3, ejemplo4. Asegúrate de entender cómo afectan los cambios de cada uno de los parámetros en el estado final de la cadena.
Ejercicio 2.1.3
Añade dos eslabones más en la estructura jeráquica del ejercicio anterior.
Tema 2.2 — Cinemática inversa
Ejercicio 2.2.1
Desarrolla una función de Cinemática Inversa run_IK()
que, dado una cadena jerárquica en reposo (vector de desplazamientos en 2D) y un objetivo (una coordenada 2D), calcule el valor de cada uno de los ángulos del cadena de tal forma que el end effector (punta de la cadena) este lo más cerca posible al objetivo. Para ello, utiliza la técnica del Jacobiano explicada en clase, y visualiza en MATLAB cada una de las iteraciones.
Aquí tienes una animación de cómo debería ser el resultado
Recuerda que la parte principal de la función run_IK
es un bucle de este estilo.
while(error(current_position, target) > 0.1) % Dibuja el estado actual plot_skeleton(skeleton, rots) drawnow; % Calcula Jacobiano del estado actual J = compute_jacobian(skeleton, rots); % Calcula posicion actual del end effector % Calcula incrementos de las rotaciones % Actualiza rotaciones endSolución
Tema 3.1 — Caminar
Ejercicio 3.1.1
Descárgate este archivo BVH que contiene el esqueleto báisco. Importalo a Blender. Edítalo con un editor de texto para crear alguna animación sencilla, por ejemplo:
- Añade un movimiento translacional al nodo root durante 10 frames.
- Añade un movimiento rotacional en alguno de sus articulaciones durante 10 frames.
- Añade un eslabón nuevo a su cuerpo en reposo, con 2 DOFs.
Aquí tienes una sencilla animación de lo que tienes que conseguir.
Ejercicio 3.1.2
Edita el archivo del ejercicio anterior, y cambia las línias del tipo CHANNELS 3 Xrotation Yrotation Zrotation
por CHANNELS 3 Zrotation Xrotation Yrotation
. ¿Puedes adivinar qué es lo que estás cambiando? ¿Qué consecuencuas tiene en la animación resultante?
Ejercicio 3.1.3
Descárgate esta escena de Blender y fíjate en las curvas de valores cómo la translación y la rotación de la pelvis (nodo root). Debería parecerse a esto, que coincide con los gráficos correspondientes a la acción de caminar como hemos visto en clase. Intenta modificar las curvas en el Editor de Curvas de Blender, y observa cómo cambia la animación.
Tema 3.2 — Animación Facial
Ejercicio 3.2.1
Descárgate este zip que contiene un set de blendshapes, descomprimelo y guárdalas en un directorio. Descárgate también la función para dibujar mallas en format OBJ read_vertices_and_faces_from_obj_file.m
.
Acaba de implementar la función compute_global_blendshapes()
, para que interpole entre 2 mallas utilizado el método de blendshape global que hemos visto en clase.
function compute_global_blendshapes() close all % Path where you uncompress all .obj blendshape_path = '/Users/URJC/Downloads/tri' % ¡¡Actualiza el path!! % Read OBJ files [V00,F] = read_vertices_and_faces_from_obj_file(strcat(blendshape_path, '/neutral-tri.obj')); % V00 es una matrix vertices de tamaño [numero_vertices x 3] num_vertices = size(V00,1); % Lee número de vertices % Vectoriza malla 00 V00 = vertcat(V00(:,1),V00(:,2),V00(:,3)); % ¡¡¡¡Leer más OBJ aquí!!!! figure; % Creamos un vector t con parametros alpha que utilizaremos t=0:0.2:1; t = [t flip(t)]; iterations = 0; % Loop infinito para ver los resultados while 1 % Iteración actual. Utilizamos módulo para siempre tener un número % de iteración > tamaño del vector de alphas t. iterations = mod(iterations,size(t,2)) + 1; % Alpha correspondiente a la iteración actial alpha = t(iterations); % Stores current viewpoint [az, el] = view; % ¡¡¡¡Calcular blendshape!!!! V_blend = ... % Reshapes from vectorized mesh to [num_vertices,3] V_blend = reshape(V_blend,[num_vertices,3]); % Draws mesh trisurf(F,V_blend(:, 1),... V_blend(:, 2),... V_blend(:, 3),... 'FaceColor',[0.26,0.63,1.0 ],'EdgeColor','none','LineStyle','none','SpecularStrength',0.4); % Sets current viewpoint view (az, el); % Set up lighing light('Position',[-1.0,-1.0,100.0],'Style','infinite'); lighting phong; % Set up axis axis equal axis([-1.5 1.5 0 2 -1 1.5]) drawnow; end endSolución
Ejercicio 3.2.2
¿Qué pasa cuándo asignamos una alpha mayor que 1, utilizando el método global de blendshapes?
Ejercicio 3.2.3
Usando como referencia la función desarrollada en el ejercicio 3.2.1, implementa la función compute_delta_blendshapes()
utilizando el método delta blendshapes presentado en clase. Mezcla más de 2 mallas a la vez. Por ejemplo, consigue una animación donde el personaje abra la boca y cierre los dos ojos. Aquí tienes una animación de lo que tienes que conseguir.
Ejercicio 3.2.4
¿Qué pasa cuándo asignamos una alpha mayor que 1, utilizando el método delta de blendshapes?
Animación por Computador, 2019 — Dan Casas