Tải bản đầy đủ (.pdf) (50 trang)

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

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.71 MB, 50 trang )

Dr. Manuel Carcenac - European University of Lefke

Advanced topics
in modeling
with Java OpenGL - JOGL 2
Spatial orientation: Euler angles, gimbal lock, a practical solution
Textures
NURBS surfaces
Fractal landscape generated with diamond-square algorithm

References:
/>
(for JOGL 2.0)

/> /> />(for practical introduction to JOGL 2.0)

Advanced Animation and Rendering Techniques – Theory and Practice
Alan Watt, Mark Watt; Addison-Wesley, ACM press
/> /> />
(for NURBS)

(for beautiful free planet textures)
(for beautiful free planet textures)

1


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 3 angles = 3 degrees of freedom

how to get from the absolute coordinate system
to the local coordinate system of the object ?
 global rotation = succession of 3 rotations around coordinate system axes

several possibilities: in which order do 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

2


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, 2 of the 3 axes of rotation become aligned!
 their 2 associated angles are equivalent = they produce the same rotation in space
 only 2 effective degrees of freedom left...
example: b = -  / 2  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  / 2



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...)

3


Dr. Manuel Carcenac - European University of Lefke

a practical solution:
instead of Euler angles,
define directly the local coordinate system of the object
with 3 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

4


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

5


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

6


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

7



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
8


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); }

}


9


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

class Gui: create a virtual craft and use its orientation and position to input gluLookAt
class Gui
{
JFrame f; DrawingPanel p;
Craft craft;
class DrawingPanel extends GLJPanel
{
............
DrawingPanel()
{
super(new GLCapabilities(GLProfile.getDefault()));
this.addGLEventListener(new GLEventListener()
{
............
public void display(GLAutoDrawable drawable) //**** DISPLAY
{
GL2 gl = drawable.getGL().getGL2();
............
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity();
glu.gluLookAt(
(float)craft.p.x , (float)craft.p.y , (float)craft.p.z
, (float)(craft.p.x + craft.w.x) , (float)(craft.p.y + craft.w.y) , (float)(craft.p.z + craft.w.z)
, (float)craft.u.x , (float)craft.u.y , (float)craft.u.z );
............
}
............

} );
}
}

Gui()
{
f = new JFrame(); f.setFocusable(true); f.setVisible(true);
p = new DrawingPanel(); f.getContentPane().add(p , BorderLayout.CENTER);
craft = new Craft(100.0 , 0.0 , 0.0

,

-1.0 , 0.0 , 0.0 ,

0.0 , 0.0 , 1.0 , f , 0.5 , 0.5);

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

11


Dr. Manuel Carcenac - European University of Lefke

Textures
create a texture object from a jpeg file
map the texture over a surface:
 precise at each vertex the texture coordinates




one or several polygons



GLU quadric (sphere, cylinder, disk, partial disk)

 automatic mapping

assign white color to the surface to preserve the colors of the texture
(else: red surface  texture becomes reddish when applied to surface)

creating a texture object:
import texture package:
import com.jogamp.opengl.util.texture.*;

declare texture object:
Texture texture;
true if antialiasing (mipmap)
false if aliasing tolerated
create texture object from image file:
try { texture = TextureIO.newTexture(new File("texture.jpg") , true); }
catch(Exception e) {}

texture == null



error reading the image file


12


Dr. Manuel Carcenac - European University of Lefke

texture coordinate system:
ut parameter: left to right
vt parameter: top to down

example:

 flip image vertically and save image file

earth map (Earth_flipV.jpg)
ut

vt

do not forget to flip vertically your jpeg image, else confusion over coordinates

13


Dr. Manuel Carcenac - European University of Lefke

mapping the texture over polygons:
enable texturing:

texture.enable();


bind texture to GL context:

texture.bind();

define polygon with texture coordinates at each vertex:
between glBegin and glEnd , for each vertex:
gl.glNormal3f(nx , ny , nz);

normal at vertex

gl.glTexCoord2f(ut , vt);

texture coordinates at vertex

gl.glVertex3f(x , y, z);

position of vertex

disable texturing with texture:

texture.disable();

 texture will not be applied over following surface

14


Dr. Manuel Carcenac - European University of Lefke


template for textured polygon(s):
import com.jogamp.opengl.util.texture.*;
..........
class Gui
{ ..........
class DrawingPanel extends GLJPanel
{ ..........
Texture texture;
DrawingPanel()
{ ..........
this.addGLEventListener(new GLEventListener()
{
public void init(GLAutoDrawable drawable)
{ ..........
try { texture = TextureIO.newTexture(new File("texture.jpg") , true); }
catch(Exception e) {}
}
..........
public void display(GLAutoDrawable drawable)
{ ..........
texture.enable(); texture.bind();
gl.glBegin(GL2.GL_);
..........
gl.glNormal3f(nx , ny , nz);
gl.glTexCoord2f(ut , vt);
gl.glVertex3f(x , y, z);
..........
gl.glEnd();
texture.disable();
}

..........
} );
}
}
}

15


Dr. Manuel Carcenac - European University of Lefke

example: Earth_flipV.jpg mapped over a flat quadrangle
.........
Texture tEv;
.........
try { tEv = TextureIO.newTexture(new File("Earth_flipV.jpg") , true); } catch(Exception e) {}
if (tEv == null) { System.out.println("tEv is null"); System.exit(0); }
.........
////------- QUADRANGLE
gl.glMaterialfv(GL.GL_FRONT_AND_BACK , GLLightingFunc.GL_AMBIENT_AND_DIFFUSE
, new float[] { 1.0f , 1.0f , 1.0f , 1.0f } , 0);
tEv.enable();

tEv.bind();

gl.glBegin(GL2.GL_QUADS);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(0.0f , 0.0f);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(1.0f , 0.0f);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(1.0f , 1.0f);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(0.0f , 1.0f);

gl.glEnd();

gl.glVertex3f(0.0f , 0.0f , 0.0f);
gl.glVertex3f(0.0f , 100.0f , 0.0f);
gl.glVertex3f(0.0f , 100.0f , 50.0f);
gl.glVertex3f(0.0f , 0.0f , 50.0f);

tEv.disable();
.........

4th vertex
(ut=0; vt=1)

3rd vertex
(ut=1; vt=1)

1st vertex
(ut=0; vt=0)
2nd vertex
(ut=1; vt=0)

16


Dr. Manuel Carcenac - European University of Lefke

example: Earth_flipV.jpg mapped over a single triangle
.........
Texture tEv;
.........

try { tEv = TextureIO.newTexture(new File("Earth_flipV.jpg") , true); } catch(Exception e) {}
if (tEv == null) { System.out.println("tEv is null"); System.exit(0); }
.........
////------- TRIANGLE
gl.glMaterialfv(GL.GL_FRONT_AND_BACK , GLLightingFunc.GL_AMBIENT_AND_DIFFUSE
, new float[] { 1.0f , 1.0f , 1.0f , 1.0f } , 0);
tEv.enable();

tEv.bind();

gl.glBegin(GL2.GL_TRIANGLES);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(0.0f , 0.0f);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(1.0f , 0.0f);
gl.glNormal3f(1.0f , 0.0f , 0.0f); gl.glTexCoord2f(0.5f , 1.0f);
gl.glEnd();
tEv.disable();
.........

gl.glVertex3f(0.0f , 0.0f , 0.0f);
gl.glVertex3f(0.0f , 100.0f , 0.0f);
gl.glVertex3f(0.0f , 50.0f , 50.0f);

3rd vertex
(ut=0.5; vt=1)

1st vertex
(ut=0; vt=0)
2nd vertex
(ut=1; vt=0)


17


Dr. Manuel Carcenac - European University of Lefke

example: Earth_flipV.jpg mapped over a triangle strip with 4 triangles
.........
Texture tEv;
.........
try { tEv = TextureIO.newTexture(new File("Earth_flipV.jpg") , true); } catch(Exception e) {}
if (tEv == null) { System.out.println("tEv is null"); System.exit(0); }
.........
////------- TRIANGLE STRIP
gl.glMaterialfv(GL.GL_FRONT_AND_BACK , GLLightingFunc.GL_AMBIENT_AND_DIFFUSE
, new float[] { 1.0f , 1.0f , 1.0f , 1.0f } , 0);
tEv.enable();

tEv.bind();

gl.glBegin(GL2.GL_TRIANGLES);
gl.glNormal3f(0.0f , 1.0f , 0.0f); gl.glTexCoord2f(0.0f , 0.0f);
gl.glNormal3f(0.0f , 1.0f , 0.0f); gl.glTexCoord2f(0.5f , 1.0f);
gl.glNormal3f(0.0f , 1.0f , 0.0f); gl.glTexCoord2f(0.0f , 1.0f);

gl.glVertex3f( 0.0f , 0.0f , 0.0f);
gl.glVertex3f( 0.0f , 50.0f , 50.0f);
gl.glVertex3f(43.0f , 25.0f , 50.0f);

gl.glNormal3f(1.0f , 0.0f , 0.0f);
gl.glNormal3f(1.0f , 0.0f , 0.0f);

gl.glNormal3f(1.0f , 0.0f , 0.0f);

gl.glVertex3f(0.0f , 0.0f , 0.0f);
gl.glVertex3f(0.0f , 100.0f , 0.0f);
gl.glVertex3f(0.0f , 50.0f , 50.0f);

gl.glTexCoord2f(0.0f , 0.0f);
gl.glTexCoord2f(1.0f , 0.0f);
gl.glTexCoord2f(0.5f , 1.0f);

gl.glNormal3f(0.0f , 1.0f , 0.0f); gl.glTexCoord2f(1.0f , 0.0f);
gl.glNormal3f(0.0f , 1.0f , 0.0f); gl.glTexCoord2f(1.0f , 1.0f);
gl.glNormal3f(0.0f , 1.0f , 0.0f); gl.glTexCoord2f(0.5f , 1.0f);
gl.glEnd();

gl.glVertex3f( 0.0f , 100.0f , 0.0f);
gl.glVertex3f(-50.0f , 50.0f , 50.0f);
gl.glVertex3f( 0.0f , 50.0f , 50.0f);

tEv.disable();
.........

3rd triangle

1st triangle
2nd triangle

18



Dr. Manuel Carcenac - European University of Lefke

mapping the texture over GLU quadrics:
enable texturing:

texture.enable();

bind texture to GL context:

texture.bind();

enable texturing for quadric object quad:

define quadric:

automatic mapping
according to rules below

glu.gluQuadricTexture(quad , true);

glu.gluSphere(quad , ......);
glu.gluCylinder(quad , ......);
glu.gluDisk(quad , ......);
glu.gluPartialDisk(quad , ......);

disable texturing with texture:

texture.disable();

 texture will not be applied over following surface


automatic mapping over sphere:
z
ut

x

vt

y

flip vertically your jpeg image

19


Dr. Manuel Carcenac - European University of Lefke

automatic mapping over cylinder:

z

ut

x

vt

y


flip vertically and horizontally your jpeg image

automatic mapping over disk / partial disk:
z
ut

x

vt

y

flip vertically your jpeg image

20


Dr. Manuel Carcenac - European University of Lefke

template for textured quadric(s):
import com.jogamp.opengl.util.texture.*;
..........
class Gui
{ ..........
class DrawingPanel extends GLJPanel
{ ..........
Texture texture;
DrawingPanel()
{ ..........
this.addGLEventListener(new GLEventListener()

{
public void init(GLAutoDrawable drawable)
{ ..........
try { texture = TextureIO.newTexture(new File("texture.jpg") , true); }
catch(Exception e) {}
}
..........
public void display(GLAutoDrawable drawable)
{ ..........
texture.enable(); texture.bind(); glu.gluQuadricTexture(quad , true);
glu.gluSphere(quad , ......);
glu.gluCylinder(quad , ......);
glu.gluDisk(quad , ......);
glu.gluPartialDisk(quad , ......);
texture.disable();
}
..........
} );
}
}
}

21


Dr. Manuel Carcenac - European University of Lefke

example: Earth_flipV.jpg mapped over a sphere, a disk, a partial disk
Earth_flipVH.jpg mapped over a cylinder
.........

try { tEv = TextureIO.newTexture(new File("Earth_flipV.jpg")
, true); } catch(Exception e) {}
try { tEvh = TextureIO.newTexture(new File("Earth_flipVH.jpg") , true); } catch(Exception e) {}
.........
tEv.enable(); tEv.bind(); glu.gluQuadricTexture(quad , true);
glu.gluSphere(quad , 30.0f , 50 , 50);
tEv.disable();
.........
tEvh.enable(); tEvh.bind(); glu.gluQuadricTexture(quad , true);
gl.glPushMatrix(); gl.glTranslatef(0.0f , 50.0f , 0.0f);
glu.gluCylinder(quad , 15.0f , 20.0f , 30.0f , 50 , 50);
gl.glPopMatrix();
tEvh.disable();
.........
tEv.enable(); tEv.bind(); glu.gluQuadricTexture(quad , true);
gl.glPushMatrix(); gl.glTranslatef(50.0f , 0.0f , 0.0f);
glu.gluDisk(quad , 5.0f , 15.0f , 20 , 20);
gl.glPopMatrix();
tEv.disable();
.........
tEv.enable(); tEv.bind(); glu.gluQuadricTexture(quad , true);
gl.glPushMatrix(); gl.glTranslatef(50.0f , 40.0f , 0.0f);
glu.gluPartialDisk(quad , 5.0f , 15.0f , 20 , 20 , 0.0f , +135.0f);
gl.glPopMatrix();
tEv.disable();
.........

22



Dr. Manuel Carcenac - European University of Lefke

example: Earth_flipV.jpg , Moon_flipV.jpg , Sun_flipV.jpg , Heaven_flipV.jpg
mapped on spheres ; virtual spacecraft
.........
try { tEv = TextureIO.newTexture(new File("Earth_flipV.jpg") , true);
try { tMv = TextureIO.newTexture(new File("Moon_flipV.jpg") , true);
try { tSv = TextureIO.newTexture(new File("Sun_flipV.jpg")
, true);
try { tHv = TextureIO.newTexture(new File("Heaven_flipV.jpg") , true);
.........
tEv.enable(); tEv.bind(); glu.gluQuadricTexture(quad , true);
glu.gluSphere(quad , 30.0f , 50 , 50);
tEv.disable();
.........
tMv.enable(); tMv.bind(); glu.gluQuadricTexture(quad , true);
gl.glPushMatrix(); gl.glTranslatef(0.0f , 80.0f , 0.0f);
glu.gluSphere(quad , 15.0f , 50 , 50);
gl.glPopMatrix();
tMv.disable();
.........
tSv.enable(); tSv.bind(); glu.gluQuadricTexture(quad , true);
gl.glPushMatrix(); gl.glTranslatef(20000.0f , 0.0f , 0.0f);
glu.gluSphere(quad , 1000.0f , 50 , 50);
gl.glPopMatrix();
tSv.disable();
.........
tHv.enable(); tHv.bind(); glu.gluQuadricTexture(quad , true);
gl.glPushMatrix();
glu.gluSphere(quad , 100000.0f , 50 , 50);

gl.glPopMatrix();
tHv.disable();
.........

}
}
}
}

catch(Exception e) {}
catch(Exception e) {}
catch(Exception e) {}
catch(Exception e) {}

23


Dr. Manuel Carcenac - European University of Lefke

24


Dr. Manuel Carcenac - European University of Lefke

NURBS surfaces
grid of control points along surface parameters u and v :
n_ctrlpts_u control points along u
v

n_ctrlpts_v control points along v


u

"Non Uniform":
knots = help us define intervals for parameters u , v between control points

define non uniform intervals (stretched, squeezed intervals)
 smoothen, sharpen locally the surface

"Rational":
eventually, specific weight for each control point

25


×