Slides

Tema 1.1 — Interpolación

Ejercicios

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;
end                    
Solució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;
end
Solució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 de Bezier de con sólo dos puntos de control, escribe dos nuevas funciones 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

Ejercicios

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

Ejercicios

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ón

Ejercicio 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ón

Ejercicio 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

Ejercicios

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

end
Solució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

Ejercicios

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

end
Solución

Tema 3.1 — Caminar

Ejercicios

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:

  1. Añade un movimiento translacional al nodo root durante 10 frames.
  2. Añade un movimiento rotacional en alguno de sus articulaciones durante 10 frames.
  3. 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

Ejercicios

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
end
Solució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.

Solución

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