2 advanced topics in modelling with JOGL2 tủ tài liệu bách khoa

50 56 0
2  advanced topics in modelling with JOGL2 tủ tài liệu bách khoa

Đ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

Dr Manuel Carcenac - European University of Lefke Advanced topics in modeling with Java OpenGL - JOGL Spatial orientation: Euler angles, gimbal lock, a practical solution Textures NURBS surfaces Fractal landscape generated with diamond-square algorithm References: http://jogamp.org/ (for JOGL 2.0) http://download.java.net/media/jogl/jogl-2.x-docs/ http://www.glprogramming.com/red/ http://eng.eul.edu.tr/manuel/Course_on_Graphics_in_Java/Course_on_Graphics_in_Java.htm (for practical introduction to JOGL 2.0) Advanced Animation and Rendering Techniques – Theory and Practice Alan Watt, Mark Watt; Addison-Wesley, ACM press http://www.mactech.com/articles/develop/issue_25/schneider.html http://www.oera.net/How2/TextureMaps2.htm http://planetpixelemporium.com/planets.html (for NURBS) (for beautiful free planet textures) (for beautiful free planet textures) Dr Manuel Carcenac - European University of Lefke Spatial orientation: Euler angles, gimbal lock, a practical solution Euler angles: any spatial orientation of an object can be described by angles = degrees of freedom how to get from the absolute coordinate system to the local coordinate system of the object ?  global rotation = succession of rotations around coordinate system axes several possibilities: in which order we rotate around axes x , y , z ?  one possible solution: absolute (x,y,z) rot of angle a around axis z rot of angle b around axis y' (x',y',z) (x'',y',z') local (x'',y'',z'') rot of angle c around axis x'' z z' z'' c b y'' c a a y' y x'' b x' x Dr Manuel Carcenac - European University of Lefke gimbal lock: decoupled degrees of freedom: axes of rotation remain more or less orthogonal  angles remain decoupled = they have independent actions big problem: loss of a degree of freedom: in certain configurations, of the axes of rotation become aligned!  their associated angles are equivalent = they produce the same rotation in space  only effective degrees of freedom left example: b = -  /  a and c both rotate around axis z  once b is fixed, only possible to rotate around z axis with a and c z x'' z' y'' c z'' y' c a y a x' x annoying problem: degrees of freedom partially coupled: b tends toward  /  a and c become increasingly coupled  varying a has an increasing effect on the rotation that should be controled only by c = very disturbing for a human operator (especially to control camera orientation ) Dr Manuel Carcenac - European University of Lefke a practical solution: instead of Euler angles, define directly the local coordinate system of the object with orthogonal unit vectors u , v , w assume u , v , w given initially  how to adjust the space orientation of u , v , w ? incremental approach: start with an inital u , v , w then rotate gradually u , v , w in space  new u , v , w after each incremental rotation δ u' u w' w v' v at each time step, apply small rotations around u , v or w = applied relatively to the object  intuitive for operator  axes of rotation remain practically orthogonal over a time step  remain far away from any gimbal lock configuration Dr Manuel Carcenac - European University of Lefke 3D rotation around a vector: rotation of angle δ around unit vector n : v  v' v' n×v v' δ v v= v n v= = (n v) n v = v - (n v) n  v' = v= + cos δ v + sin δ n×v  v' = cos δ v + (1 - cos δ) (n v) n + sin δ n×v Dr Manuel Carcenac - European University of Lefke application to attitude control of virtual camera: initial orientation of camera: w aiming direction uup up vector = up direction of screen  u orthogonalized relative to w : u = uup - (u.w) w uup u = uup - (uup.w) w w v=w×u real-time control of evolution of camera orientation: we adjust camera orientation in real time = we are in a spacecraft and we control its orientation (attitude control system, attitude rockets)  small rotations over roll , pitch , yaw at each time step u w yaw roll pitch v Dr Manuel Carcenac - European University of Lefke controlling orientation with some keyboard action keys: fast rotation: rotation 10 δ Insert Page Up roll incline left: rot(-δ,w) over u,v Delete Page Down roll incline right: rot(δ,w) over u,v pitch up: rot(δ,v) over u,w  yaw left: rot(δ,u) over v,w    yaw right: rot(-δ,u) over v,w pitch down: rot(-δ,v) over u,w Insert key pressed while other keys used  fast rotation by 10 δ per time step Dr Manuel Carcenac - European University of Lefke extra: position control of virtual camera: how to move the camera?  incremental approach: initial position p small translation over p at each time step translation expressed relatively to camera orientation: move backward - forward:  intuitive for operator translation along w move left - right: translation along v move down - up: translation along u fast move: translation 10 δ Insert Page Up move forward: pp+δw moving mode Delete Page Down move backward: pp-δw  move left: pp-δv   move up: pp+δu  move right: pp+δv move down: pp-δu Delete key pressed while other keys used  moving mode, else rotation mode Insert key pressed while other keys used  fast move by 10 δ per time step Dr Manuel Carcenac - European University of Lefke class V3d: operations on 3D vectors class V3d { double x , y , z; V3d() {} V3d(double x , double y , double z) { this.x = x; void V3d_move(V3d n , double d) { this.x += d * n.x; this.y += d * n.y; this.z += d * n.z; } this.y = y; this.z = z; } // this < this + d * n void V3d_rotate(V3d n , double theta) // this < rotation (theta , n) of this; n unit vector; theta in deg { double c = Math.cos(theta * Math.PI / 180.0) , s = Math.sin(theta * Math.PI / 180.0); double k = (1 - c) * (this.x * n.x + this.y * n.y + this.z * n.z); double x = c * this.x + k * n.x + s * (n.y * this.z - n.z * this.y) , y = c * this.y + k * n.y + s * (n.z * this.x - n.x * this.z) , z = c * this.z + k * n.z + s * (n.x * this.y - n.y * this.x); this.x = x; this.y = y; this.z = z; } void V3d_orthogonalize(V3d b) // this < this - (this b) b { double d = this.x * b.x + this.y * b.y + this.z * b.z; this.x -= d * b.x; this.y -= d * b.y; this.z -= d * b.z; } void V3d_normalize() // this < unit vector (this) { double d = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); if (d < 1.0e-10) { System.out.println("in V3d_normalize: d < 1.0e-10"); this.x /= d; this.y /= d; this.z /= d; } void V3d_vector_product(V3d a , V3d b) // this < a x b { this.x = a.y * b.z - a.z * b.y; this.y = a.z * b.x - a.x * b.z; System.exit(0); } this.z = a.x * b.y - a.y * b.x; } void normal_3_points(V3d p0 , V3d p1 , V3d p2) { x = (p1.y - p0.y) * (p2.z - p0.z) - (p1.z - p0.z) * (p2.y - p0.y); y = (p1.z - p0.z) * (p2.x - p0.x) - (p1.x - p0.x) * (p2.z - p0.z); z = (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x); double d = Math.sqrt( x * x + y * y + z * z); if (d < 1.0e-10) { System.out.println("d < 1.0e-10 in normal_3_points"); x /= d; y /= d; z /= d; } System.exit(0); } } Dr Manuel Carcenac - European University of Lefke class Craft: virtual craft (orientation and position controlled in real time with keyboard) class Craft { V3d p , u , v , w; double dmove , drot; boolean move , fast; Craft( double posx , double posy , double posz , double aimx , double aimy , double aimz , double upx , double upy , double upz , final JFrame f , double dm , double dr) { p = new V3d(posx , posy , posz); w = new V3d(aimx , aimy , aimz); w.V3d_normalize(); u = new V3d(upx , upy , upz); u.V3d_orthogonalize(w); u.V3d_normalize(); v = new V3d(); v.V3d_vector_product(w , u); this.dmove = dm; this.drot = dr; move = false; fast = false; f.addKeyListener(new KeyAdapter() { public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); double d; if (move) d = (fast ? 10 * dmove : dmove); else d = (fast ? 10 * drot : drot); switch (key) { case KeyEvent.VK_LEFT: if (move) p.V3d_move(v , - d); else { v.V3d_rotate(u , d); w.V3d_rotate(u , d); }; break; case KeyEvent.VK_RIGHT: if (move) p.V3d_move(v , d); else { v.V3d_rotate(u , - d); w.V3d_rotate(u , - d); }; break; case KeyEvent.VK_DOWN: if (move) p.V3d_move(u , - d); else { u.V3d_rotate(v , - d); w.V3d_rotate(v , - d); }; break; case KeyEvent.VK_UP: if (move) p.V3d_move(u , d); else { u.V3d_rotate(v , d); w.V3d_rotate(v , d); }; break; case KeyEvent.VK_PAGE_DOWN: if (move) p.V3d_move(w , - d); else { u.V3d_rotate(w , d); v.V3d_rotate(w , d); }; break; case KeyEvent.VK_PAGE_UP: if (move) p.V3d_move(w , d); else { u.V3d_rotate(w , - d); v.V3d_rotate(w , - d); }; break; case KeyEvent.VK_INSERT: fast = true; break; case KeyEvent.VK_DELETE: move = true; break; } f.repaint(); } } ); f.addKeyListener(new KeyAdapter() { public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); switch (key) { case KeyEvent.VK_INSERT: fast = false; break; case KeyEvent.VK_DELETE: move = false; break; } } } ); } } what if we need to use keyPressed and keyReleased for other keys as well ? 10 Dr Manuel Carcenac - European University of Lefke example: interactive cubic NURBS: degree 3, order 4, nc×nc control pts, nc + knots along u and v specific weight w for each control point select with buttons a control point then change its x, y, z, w with sliders control points are displayed as blue dots (red dot for selected one) class Gui { JFrame f; DrawingPanel p; JPanel ps; JSlider skx , sky , skz , skw; JLabel lkx , lky , lkz , lkw; JButton b_left , b_right , b_down , b_up; float[][] xc , yc , zc , wc; float SIZE; int nc , ik , jk; class DrawingPanel extends GLJPanel { public void display(GLAutoDrawable drawable) { //********** DISPLAY //// - CONTROL POINTS for (int i = ; i < nc ; i++) for (int j = ; j < nc ; j++) { if (i == ik && j == jk) gl.glMaterialfv( , new float[] { 1.0f , 0.0f , 0.0f , 1.0f } , 0); else gl.glMaterialfv( , new float[] { 0.0f , 0.0f , 1.0f , 1.0f } , 0); gl.glPushMatrix(); gl.glTranslatef(xc[i][j] , yc[i][j] , zc[i][j]); glu.gluSphere(quad , 1.5f , 10 , 10); gl.glPopMatrix(); } //// - NURBS gl.glMaterialfv( , new float[] { 1.0f , 1.0f , 0.0f , 1.0f } , 0); float[] knots = new float[nc + 4]; knots[0] = 0.0f; knots[1] = 0.0f; knots[2] = 0.0f; knots[3] = 0.0f; for (int k = ; k < nc ; k++) knots[k] = 0.0f + 1.0f * (k - 3) / (nc - 3); knots[nc + 0] = 1.0f; knots[nc + 1] = 1.0f; knots[nc + 2] = 1.0f; knots[nc + 3] = 1.0f; float[] ctrlpts = new float[nc * nc * 4]; for (int i = ; i < nc ; i++) for (int j = ; j < nc ; j++) { ctrlpts[nc * * i + * j + 0] = xc[i][j]; ctrlpts[nc * * i + * j + 1] = yc[i][j]; ctrlpts[nc * * i + * j + 2] = zc[i][j]; ctrlpts[nc * * i + * j + 3] = wc[i][j]; } 36 Dr Manuel Carcenac - European University of Lefke glugl2.gluBeginSurface(nurbs); glugl2.gluNurbsSurface( nurbs , nc + , knots , nc + , knots , nc * , , ctrlpts ,4,4 , GL2.GL_MAP2_VERTEX_4); glugl2.gluEndSurface(nurbs); gl.glFlush(); } } ); } } 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 control points over u and v; at least 4"); nc = Integer.valueOf(s).intValue(); if (nc < 4) { System.out.println("nc < 4"); System.exit(0); } SIZE = 100.0f; xc = new float[nc][nc]; yc = new float[nc][nc]; zc = new float[nc][nc]; wc = new float[nc][nc]; for (int i = ; i < nc ; i++) for (int j = ; j < nc ; j++) { xc[i][j] = 0.0f; yc[i][j] = SIZE * i / (nc - 1); zc[i][j] = SIZE * j / (nc - 1); wc[i][j] = 1.0f; } ik = 0; jk = 0; ps = new JPanel(); ps.setLayout(new GridLayout(0 , 2)); f.getContentPane().add(ps , BorderLayout.EAST); b_left = new JButton(); b_left.setText("select left"); ps.add(b_left); b_left.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ik ; if (ik == -1) ik = nc - 1; skx.setValue((int)xc[ik][jk]); sky.setValue((int)yc[ik][jk]); skz.setValue((int)zc[ik][jk]); skw.setValue((int)(wc[ik][jk] * 10)); f.repaint(); } } ); b_right = new JButton(); b_right.setText("select right"); ps.add(b_right); b_right.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ik++; if (ik == nc) ik = 0; skx.setValue((int)xc[ik][jk]); sky.setValue((int)yc[ik][jk]); skz.setValue((int)zc[ik][jk]); skw.setValue((int)(wc[ik][jk] * 10)); f.repaint(); } } ); b_down = new JButton(); b_down.setText("select down"); ps.add(b_down); b_down.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jk ; if (jk == -1) jk = nc - 1; skx.setValue((int)xc[ik][jk]); sky.setValue((int)yc[ik][jk]); skz.setValue((int)zc[ik][jk]); skw.setValue((int)(wc[ik][jk] * 10)); f.repaint(); } } ); b_up = new JButton(); b_up.setText("select up"); ps.add(b_up); b_up.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { jk++; if (jk == nc) jk = 0; skx.setValue((int)xc[ik][jk]); sky.setValue((int)yc[ik][jk]); skz.setValue((int)zc[ik][jk]); skw.setValue((int)(wc[ik][jk] * 10)); f.repaint(); } } ); 37 Dr Manuel Carcenac - European University of Lefke skx = new JSlider(JSlider.HORIZONTAL , -100 , 100 , 0); lkx = new JLabel(" x of selected control point"); sky = new JSlider(JSlider.HORIZONTAL , -50 , 150 , 0); lky = new JLabel(" y of selected control point"); skz = new JSlider(JSlider.HORIZONTAL , -50 , 150 , 0); lkz = new JLabel(" z of selected control point"); skw = new JSlider(JSlider.HORIZONTAL , , 100 , 10); lkw = new JLabel(" w of selected control point"); skx.addChangeListener( { sky.addChangeListener( { skz.addChangeListener( { skw.addChangeListener( { ps.add(skx); ps.add(lkx); ps.add(sky); ps.add(lky); ps.add(skz); ps.add(lkz); ps.add(skw); ps.add(lkw); xc[ik][jk] = (float)(skx.getValue()); f.repaint(); } } ); yc[ik][jk] = (float)(sky.getValue()); f.repaint(); } } ); zc[ik][jk] = (float)(skz.getValue()); f.repaint(); } } ); wc[ik][jk] = skw.getValue() / 10.0f; f.repaint(); } } ); f.setSize(new Dimension(1000 + 16 , 600 + 38)); } } 38 Dr Manuel Carcenac - European University of Lefke 39 Dr Manuel Carcenac - European University of Lefke 40 Dr Manuel Carcenac - European University of Lefke applying a texture over a NURBS surface: how to define the mapping: ut and vt in function of u , v ?  use a 2D NURBS surface = points of coordinates (ut , vt)  allows specification of deformations (stretching, squeezing) of texture over NURBS surface simple case: linear mapping: degree 1, order 2 control points + = knots along u and v float[] tex_knots = new float[] { 0.0f , 0.0f , 1.0f , 1.0f }; float[] tex_ctrlpts = new float[] { 0.0f , 0.0f , 0.0f , 1.0f , 1.0f , 0.0f , 1.0f , 1.0f }; glugl2.gluBeginSurface(nurbs); glugl2.gluNurbsSurface( nurbs , , tex_knots , , tex_knots , * , , tex_ctrlpts , , , GL2.GL_MAP2_TEXTURE_COORD_2); glugl2.gluNurbsSurface( nurbs , , GL2.GL_MAP2_VERTEX_3); glugl2.gluEndSurface(nurbs); not yet implemented in JOGL 41 Dr Manuel Carcenac - European University of Lefke Fractal landscape generated with diamond-square algorithm starting idea: subdivide each quadrangle into sub quadrangles  generate each of the new points of the finer grid: height of point = middle of the heights of its already generated closest neighbors + random pertubation 1st step: generate points at centers of quadrangles 2nd step: generate points at middles of quadrangles' sides 1st step 2nd step 42 Dr Manuel Carcenac - European University of Lefke levels of subdivision of a grid of points: grid of (2n + 1) × (2n + 1) points  2n × 2n quadrangles n + levels of the grid: k = 0: × points = corners of the whole grid k = 1: × points  quadrangles k = n: (2n + 1) × (2n + 1) points  quadrangle  full grid Ik = , , 2k level-k coordinates of a point at level k : Jk = , , 2k i = 2n-k Ik  its absolute (level-n) coordinates are: j = 2n-k Jk example: n =  × points level-0 coordinates: level-1 coordinates: level-2 coordinates: 43 Dr Manuel Carcenac - European University of Lefke how to perturb the points: square grid of horizontal size H  size of quadrangle of level k is H / 2k roughness = parameter from to function rand()  random number in range [0 , 1]  perturbation = r × (2 rand() -1) × H / 2k assume points at level k are already generated  generate in two steps the new points at level k + first step (diamond step): for every point (Ik+1 , Jk+1) at level k +1 : if point (Ik+1 , Jk+1) center of a level-k quadrangle : z of center point (Ik+1 , Jk+1)  perturbation + middle of z of level-(k+1) points (Ik+1 - 1, Jk+1 - 1) , (Ik+1 + , Jk+1 - 1) , (Ik+1 - 1, Jk+1 + 1) , (Ik+1 + , Jk+1 + 1) second step (square step): for every point (Ik+1 , Jk+1) at level k +1 : if point (Ik+1 , Jk+1) not already generated during first step : z of center point (Ik+1 , Jk+1)  perturbation + middle of z of level-(k+1) points (Ik+1 - 1, Jk+1) , (Ik+1 + , Jk+1) , (Ik+1 , Jk+1 - 1) , (Ik+1 , Jk+1 + 1) Note: Ik+1 , Jk+1 level-(k+1) coordinates  multiply them by 2n-k-1 to obtain the absolute coordinates 44 Dr Manuel Carcenac - European University of Lefke pseudo-code: for k  , , n - 1: for Ik+1  , , 2k+1 : for Jk+1  , , 2k+1 : if Ik+1 odd and Jk+1 odd : z( 2n-k-1 Ik+1 , 2n-k-1 Jk+1 )  z_middle( 2n-k-1 (Ik+1 - 1) , 2n-k-1 (Jk+1 - 1) , 2n-k-1 (Ik+1 + 1) , 2n-k-1 (Jk+1 - 1) , 2n-k-1 (Ik+1 - 1) , 2n-k-1 (Jk+1 + 1) , 2n-k-1 (Ik+1 + 1) , 2n-k-1 (Jk+1 + 1) ) + r (2 rand() -1) H / 2k for Ik+1  , , 2k+1 : for Jk+1  , , 2k+1 : if (Ik+1 odd and Jk+1 even) or (Ik+1 even and Jk+1 odd) : z( 2n-k-1 Ik+1 , 2n-k-1 Jk+1 )  z_middle( 2n-k-1 (Ik+1 - 1) , 2n-k-1 Jk+1 , 2n-k-1 (Ik+1 + 1) , 2n-k-1 Jk+1 , 2n-k-1 Ik+1 , 2n-k-1 (Jk+1 - 1) , 2n-k-1 Ik+1 , 2n-k-1 (Jk+1 + 1) ) + r (2 rand() -1) H / 2k we have generated a grid of points of varying height  non flat, twisted quadrangles flat polygons required for Open GL  subdivide each quadrangle into two triangles 45 Dr Manuel Carcenac - European University of Lefke fractal landscape with quadrangles represented by couples of triangles: class FractalLandscape { int N; double size; double[][] z; // 1

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

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan