1. Trang chủ
  2. » Giáo Dục - Đào Tạo

3 advanced topics in animation presented with JOGL2 tủ tài liệu bách khoa

32 58 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 32
Dung lượng 1,87 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Advanced topicsin animation kinematic animation: time interpolation of degrees of freedom dynamic animation: time integration of degrees of freedom dynamic animation: all-pairs n-body pr

Trang 1

Advanced topics

in animation

kinematic animation: time interpolation of degrees of freedom dynamic animation: time integration of degrees of freedom dynamic animation: all-pairs n-body problem and gravitation

(for practical introduction to JOGL 2.0)

Advanced Animation and Rendering Techniques – Theory and Practice

Alan Watt, Mark Watt; Addison-Wesley, ACM press

Michael Thomas Flanagan's Java Scientific and Numerical Library

http://www.ee.ucl.ac.uk/~mflanaga/java/index.html

http://www.ee.ucl.ac.uk/~mflanaga/java/CubicSpline.html (for cubic spline interpolation)

http://farside.ph.utexas.edu/teaching/329/lectures/node35.html for Runge-Kutta method

http://www.ast.cam.ac.uk/~sverre/web/pages/nbody.htm

for n-body problem

http://www.scholarpedia.org/article/N-body_simulations_(gravitational)

Trang 2

kinematic animation: time interpolation of degrees of freedom

cubic spline interpolation:

install Flanagan's scientific library:

put flanagan.jar into folder C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext

♦ add to system variable CLASSPATH (already exists, was created for JOGL)

Computer  Properties  Advanced system settings  Environment Variables

edit system variable CLASSPATH (already exists, was created for JOGL)

 add at the end of it:

;C:\Program Files\Java\jdk1.6.0_23\jre\lib\ext\flanagan.jar

import statement:

import flanagan.interpolation.*;

cubic spline with Nk control points ( tk , xk ) :

double[] xk = new double[Nk];

double[] tk = new double[Nk];

CubicSpline csx = new CubicSpline(tk , xk);

interpolation of function x(t) :

double x = csx.interpolate(t);

for every control point k , csx.interpolate(tk[k]) yields value xk[k]

Trang 3

example: interpolated curve with interactive selection and modification of control points

.

import flanagan.interpolation.*;

public class P

{ public static void main(String[] arg)

{ Gui gui = new Gui(); } }

class Gui

{

JFrame f; DrawingPanel p;

JPanel ps; JSlider skx , sky , skz , skt; JLabel lkx , lky , lkz , lkt;

int Nk = 8; int ks = 0; // ks = k of selected key

double[] xk = new double[Nk] , yk = new double[Nk] , zk = new double[Nk] , tk = new double[Nk];

GLU glu; GLUquadric quad;

float[] RED = new float[] { 1.0f , 0.0f , 0.0f , 1.0f } , GREEN = new float[] { 0.0f , 1.0f , 0.0f , 1.0f }

, WHITE = new float[] { 1.0f , 1.0f , 1.0f , 1.0f };

, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE , (k == ks ? RED : GREEN) , 0);

gl.glPushMatrix(); gl.glTranslatef((float)xk[k] , (float)yk[k] , (float)zk[k]);

glu.gluSphere(quad , 2.0f , 10 , 10);

gl.glPopMatrix();

}

Trang 4

//// - INTERPOLATED POINTS

gl.glMaterialfv(GL.GL_FRONT_AND_BACK

, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE , WHITE , 0);

CubicSpline csx = new CubicSpline(tk , xk)

, csy = new CubicSpline(tk , yk)

Trang 5

Gui()

{

f = new JFrame(); f.setFocusable(true); f.setVisible(true);

p = new DrawingPanel(); f.getContentPane().add(p , BorderLayout.CENTER);

f.addMouseListener(new MouseAdapter()

{ public void mouseClicked(MouseEvent e)

{ int bt = e.getButton();

switch (bt)

{ case MouseEvent.BUTTON1: ks ; if (ks == -1) ks = Nk - 1; break;

case MouseEvent.BUTTON3: ks++; if (ks == Nk) ks = 0; break; }

skx = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(skx);

lkx = new JLabel(" x of selected key"); ps.add(lkx);

sky = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(sky);

lky = new JLabel(" y of selected key"); ps.add(lky);

skz = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(skz);

lkz = new JLabel(" z of selected key"); ps.add(lkz);

skt = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(skt);

lkt = new JLabel(" t of selected key"); ps.add(lkt);

skx.addChangeListener( { xk[ks] = -L/2+L*skx.getValue()/1000; f.repaint(); } } ); sky.addChangeListener( { yk[ks] = -L/2+L*sky.getValue()/1000; f.repaint(); } } ); skz.addChangeListener( { zk[ks] = -L/2+L*skz.getValue()/1000; f.repaint(); } } ); skt.addChangeListener(

Trang 7

example: interpolated trajectory of a ball: interactive creation of key frames over time followed by spline driven animation

.

import flanagan.interpolation.*;

public class P

{ public static void main(String[] arg)

{ Gui gui = new Gui();

boolean perform_anim = false;

synchronized void write_perform_anim(boolean value) { perform_anim = value; }

synchronized boolean read_perform_anim() { return perform_anim; }

long dt_real = System.currentTimeMillis() - t_start;

if (dt_real < dt) try {Thread.sleep(dt - dt_real);} catch(InterruptedException ee){}

else System.out.println("PC too slow; please increase dt"); }

}

Trang 8

class DrawingPanel extends GLJPanel

{

GLU glu; GLUquadric quad;

float[] RED = new float[] { 1.0f , 0.0f , 0.0f , 1.0f } , GREEN = new float[] { 0.0f , 1.0f , 0.0f , 1.0f } , WHITE = new float[] { 1.0f , 1.0f , 1.0f , 1.0f };

, GLLightingFunc.GL_AMBIENT_AND_DIFFUSE , (k == nk - 1 ? RED : GREEN) , 0);

gl.glPushMatrix(); gl.glTranslatef((float)xk[k] , (float)yk[k] , (float)zk[k]);

CubicSpline csx = new CubicSpline(tk , xk)

, csy = new CubicSpline(tk , yk)

Trang 9

Gui()

{

f = new JFrame(); f.setFocusable(true); f.setVisible(true);

p = new DrawingPanel(); f.getContentPane().add(p , BorderLayout.CENTER);

String s = JOptionPane.showInputDialog(f , "number of ctrl pts over " + T + "s ; at least 3");

Nk = Integer.valueOf(s).intValue(); if (Nk<3) { System.out.println("Nk < 3"); System.exit(0); }

nk = 0;

xk = new double[Nk]; yk = new double[Nk]; zk = new double[Nk]; tk = new double[Nk];

ps = new JPanel(); ps.setLayout(new GridLayout(0 , 2));

f.getContentPane().add(ps , BorderLayout.EAST);

skx = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(skx);

lkx = new JLabel(" x of new key"); ps.add(lkx);

sky = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(sky);

lky = new JLabel(" y of new key"); ps.add(lky);

skz = new JSlider(JSlider.HORIZONTAL , 0 , 1000 , 0); ps.add(skz);

lkz = new JLabel(" z of new key"); ps.add(lkz);

skx.addChangeListener(new ChangeListener()

{ public void stateChanged(ChangeEvent e)

{ if (nk > 0) { xk[nk - 1] = L * skx.getValue() / 1000; f.repaint(); } } } );

sky.addChangeListener(new ChangeListener()

{ public void stateChanged(ChangeEvent e)

{ if (nk > 0) { yk[nk - 1] = L * sky.getValue() / 1000; f.repaint(); } } } );

{ public void actionPerformed(ActionEvent e)

{ if (nk < Nk) JOptionPane.showMessageDialog(f , "you have not yet recorded all the keys!"); else write_perform_anim(true); } } );

f.setSize(new Dimension(1000 + 16 , 600 + 38));

}

}

Trang 11

example : angles of an articulated structure: interactive creation of key frames over time followed by spline driven animation

.

import flanagan.interpolation.*;

public class P

{ public static void main(String[] arg)

{ Gui gui = new Gui();

JFrame f; DrawingPanel p; JPanel ps;

JSlider[] ska = new JSlider[Na]; JButton b_new_key , b_perform_anim;

boolean perform_anim = false;

synchronized void write_perform_anim(boolean value) { perform_anim = value; }

synchronized boolean read_perform_anim() { return perform_anim; }

long dt_real = System.currentTimeMillis() - t_start;

if (dt_real < dt) try {Thread.sleep(dt - dt_real);} catch(InterruptedException ee){}

else System.out.println("PC too slow; please increase dt"); }

}

Trang 12

class DrawingPanel extends GLJPanel

float[] ai = new float[Na];

for (int a = 0 ; a < Na ; a++) ai[a] = (float)(ak[a][nk - 1]);

articulated_arm(gl , glu , quad , ai);

}

//// - ANIMATED ARM

if (read_perform_anim())

{

CubicSpline[] csa = new CubicSpline[Na];

for (int a = 0 ; a < Na ; a++) csa[a] = new CubicSpline(tk , ak[a]);

float[] ai = new float[Na];

for (int a = 0 ; a < Na ; a++) ai[a] = (float)(csa[a].interpolate(time));

articulated_arm(gl , glu , quad , ai);

Trang 13

Gui()

{

f = new JFrame(); f.setFocusable(true); f.setVisible(true);

p = new DrawingPanel(); f.getContentPane().add(p , BorderLayout.CENTER);

String s = JOptionPane.showInputDialog(f , "n of ctrl pts over " + T + "s ; at least 3");

Nk = Integer.valueOf(s).intValue(); if (Nk<3) { System.out.println("Nk<3"); System.exit(0); }

nk = 0;

ak = new double[Na][Nk]; tk = new double[Nk];

ps = new JPanel(); ps.setLayout(new GridLayout(0 , 1));

f.getContentPane().add(ps , BorderLayout.EAST);

for (int a = 0 ; a < Na ; a++)

{ ska[a] = new JSlider(JSlider.HORIZONTAL , 0 , 90 , 0); ps.add(ska[a]);

{ public void actionPerformed(ActionEvent e)

{ if (nk < Nk) JOptionPane.showMessageDialog(f , "you have not yet recorded all the keys!"); else write_perform_anim(true); } } );

f.setSize(new Dimension(800 + 16 , 600 + 38));

}

Trang 14

void articulated_arm(GL2 gl , GLU glu , GLUquadric quad , float[] ai)

{

gl.glMaterialfv(GL.GL_FRONT_AND_BACK , GLLightingFunc.GL_AMBIENT_AND_DIFFUSE , new float[] { 1.0f , 1.0f , 0.0f , 1.0f } , 0);

gl.glRotatef(ai[0] , 0.0f , 0.0f , 1.0f); gl.glRotatef( 90 - ai[1] , 1.0f , 0.0f , 0.0f);

Trang 16

dynamic animation: time integration of degrees of freedom

example: balls under the influence of gravity and bouncing off the floor

.

public class P

{ public static void main(String[] arg)

{ Gui gui = new Gui();

this.x = x; this.y = y; this.z = z;

this.vx = vx; this.vy = vy; this.vz = vz; }

}

class Gui

{

JFrame f; DrawingPanel p;

int N; Ball[] ball;

double V = 30.0 , DELTA = 10.0 , ALPHA = 0.9; //// V in m/s; DELTA in degrees; ALPHA <= 1.0 void animation()

{

double delta_t = 0.05; long dt = (long)(delta_t * 1000);

while (true)

{ long t_start = System.currentTimeMillis();

for (int i = 0 ; i < N ; i++)

long dt_real = System.currentTimeMillis() - t_start;

if (dt_real < dt) try {Thread.sleep(dt - dt_real);} catch(InterruptedException ee){}

else System.out.println("PC too slow; please increase dt"); }

Trang 17

float[] RED = new float[] { 1.0f , 0.0f , 0.0f , 1.0f } , GREEN = new float[] { 0.0f , 1.0f , 0.0f , 1.0f }

, BLUE = new float[] { 0.0f , 0.0f , 1.0f , 1.0f }, WHITE = new float[] { 1.0f , 1.0f , 1.0f , 1.0f };

class DrawingPanel extends GLJPanel

Trang 18

Gui()

{

f = new JFrame(); f.setFocusable(true); f.setVisible(true);

p = new DrawingPanel(); f.getContentPane().add(p , BorderLayout.CENTER);

String s = JOptionPane.showInputDialog(f , "number of balls; at least 1");

N = Integer.valueOf(s).intValue(); if (N < 1) { System.out.println("N < 1"); System.exit(0); } ball = new Ball[N];

for (int i = 0 ; i < N ; i++)

{ double v = V * (0.2 * Math.random() + 0.8);

double a = 2 * Math.PI * Math.random();

double b = DELTA * (Math.PI / 180) * Math.random();

ball[i] = new Ball( (i%3==0 ? RED : i%3==1 ? GREEN : BLUE)

Trang 20

dynamic animation: all-pairs n-body problem and gravitation

all-pairs n-body problem:

n bodies fully interacting with each other:

position pi and velocity vi of body i :

time derivative of the system's global state:

i j

i

i i

vz vy vx z y x

v

p pv

pv pv

D

pv pv

dt d

1 n

0

1 n 0

Trang 21

time integration:

global state s(t) is known at time t

Euler method:

inaccurate + numerical instability: errors pile up over time

second-order Runge-Kutta method:

accurate + numerically stable = excellent

fourth-order Runge-Kutta method is often preferred

D

D1=

( ) ( s t D Δt / 2 , t Δt / 2 )

Trang 22

m v

v p

dt

d t

i i

ε

i j

i j

p p

p p G

Trang 23

case study: collision of two galaxies - simulation parameters and initial state:

total mass of the two galaxies = 4×1042 kg

initial diameter of each galaxy H = 1021 m

Trang 24

class encapsulating the simulation parameters:

class Para

{

static double G = 6.67384e-11;

static double M = 4.0e42; // total mass of the two galaxies

static double H = 1.0e21; // diameter of each galaxy

static double EPS = H / 100;

static double DX = H; // distance between the two galaxies over X axis

static double DY = H; // distance between the two galaxies over Y axis

static double V = 350.0 * 1.e3; // velocity between the two galaxies along X axis

static double DT = 1.0e5 * 31536000; // 100,000 years

}

Trang 25

classes describing the state of the n-body system:

PositionVelocity(double x , double y ,double z , double vx , double vy , double vz)

{ this.x = x; this.y = y; this.z = z;

this.vx = vx; this.vy = vy; this.vz = vz; }

Trang 26

initialization of the state:

if (i < n / 2) { gal_x = - Para.DX / 2; gal_y = - Para.DY / 2; gal_z = 0.0;

gal_vx = Para.V / 2; gal_vy = 0.0; gal_vz = 0.0; }

else { gal_x = Para.DX / 2; gal_y = Para.DY / 2; gal_z = 0.0;

gal_vx = - Para.V / 2; gal_vy = 0.0; gal_vz = 0.0; }

m[i] = Para.M / n;

do

{

pv[i] = new PositionVelocity( gal_x + Para.H * ( -0.5 + Math.random())

, gal_y + Para.H * ( -0.5 + Math.random())

, gal_z + Para.H * ( -0.5 + Math.random())

, gal_vx , gal_vy , gal_vz);

h = Math.sqrt( (pv[i].x - gal_x) * (pv[i].x - gal_x)

+ (pv[i].y - gal_y) * (pv[i].y - gal_y)

+ (pv[i].z - gal_z) * (pv[i].z - gal_z));

}

while (h > Para.H / 2);

dpv[i] = new PositionVelocity();

pv_[i] = new PositionVelocity();

}

}

Trang 27

time integration with Runge-Kutta:

pv1[i].x = pv0[i].x + dpv[i].x * k;

pv1[i].y = pv0[i].y + dpv[i].y * k;

pv1[i].z = pv0[i].z + dpv[i].z * k;

pv1[i].vx = pv0[i].vx + dpv[i].vx * k;

pv1[i].vy = pv0[i].vy + dpv[i].vy * k;

pv1[i].vz = pv0[i].vz + dpv[i].vz * k;

}

}

D 1 s(t) + D

1 × t / 2

D 2 s(t) + D 2 × t

Trang 28

time derivatives of positions and velocities:

//// calculate dpv for pv = state.pv or state.pv_

void derivatives_positions_velocities(PositionVelocity[] pv)

{

double pipjx , pipjy , pipjz , d2 , q;

for (int i = 0 ; i < n ; i++)

Ngày đăng: 09/11/2019, 07:20

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w