Object Modelling
R. Mukundan Department of Computer Science and Software Engineering University of Canterbury, .
Drawing Polygonal Lines
Copyright By PowCoder代写 加微信 powcoder
glColor3f(1, 0, 0); glLineWidth(4); glBegin(GL_LINES);
glVertex3f(0, -5, 0.01);
glVertex3f(0, 5, 0.01);
When drawing a line on a polygon, use a small depth offset to avoid depth fighting.
glBegin(GL_LINE_STRIP); for(int i = 0; i < 5; i++) {
glVertex3f(x[i], y[i], z[i]);
glBegin(GL_LINE_LOOP); for(int i = 0; i < 5; i++) {
glVertex3f(x[i], y[i], z[i]);
Drawing Polygonal Lines
Drawing a circle of radius 5 units:
glLineWidth(4);
float toRadians = M_PI / 180.0;
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 36; i++)
angle = 10 * i * toRadians;
glVertex3f(5*cos(angle), 5*sin(angle), 0);
Drawing smooth (antialiased) lines:
(Include the following code in “initialize” function)
glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
Drawing Polygonal Lines
glBegin(GL_LINE_LOOP);
for (int i = 0; i < 6; i++)
angle = 60 * i * toRadians; glVertex3f(5*cos(angle), 5*sin(angle), 0); angle = angle + 30 * toRadians; glVertex3f(3*cos(angle), 3*sin(angle), 0);
} glEnd();
You may draw circles and polygonal shapes using gluDisk()
gluDisk(q, 5, 5.5, 36, 2);
gluDisk(q, 5, 5.5, 3, 2);
gluDisk(q, 5, 5.5, 7, 2);
General Polygon Definition
A polygon defined using OpenGL primitive type GL_POLYGON
will be rendered correctly only if it is a planar and convex
glColor3f(0, 1, 1); glBegin(GL_POLYGON);
glVertex3f(x0, y0, z0); glVertex3f(x1, y1, z1); glVertex3f(x2, y2, z2); glVertex3f(x3, y3, z3); glVertex3f(x4, y4, z4); glVertex3f(x5, y5, z5); ...
• Convex polygon
• Correctly rendered
• Non-convex polygon • Incorrectly rendered
Vertex sequence: V0, V1,... Vn-1
A general polygon may have to be subdivided into triangles and
quads and rendered using corresponding primitive types..
Primitive Types for Triangulation
The following primitive types are useful for subdividing polygonal regions into triangles or quads:
GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, GL_QUAD_STRIP Advantages:
Provides a compact representation of a subdivision in terms of vertices of polygonal lines (usually specified using for-loops)
No need to define each triangle of quad individually. Avoids repetition of vertices.
V1 V2 V V2 V V2
V0 V1 V1 V
Vn-1 P Triangle fan
0 n-1 W1 W2
Quad strip
W0 W Triangle strip
n = size of the V (or W) array.
Triangle Fan
This primitive type is useful for triangulating a polygon from a single point (central vertex), P.
glBegin(GL_TRIANGLE_FAN); normal(...);
glVertex3f(px, py, pz);
glVertex3f(x0, y0, z0); glVertex3f(x1, y1, z1); glVertex3f(x2, y2, z2); glVertex3f(x3, y3, z3); glVertex3f(x4, y4, z4); glVertex3f(x5, y5, z5); ...
Vertex Sequence
Central vertex
Open vs. closed polygons:
Vn-1 V0 V1 COSC363
Primitive definition: P,V0,V1 ,...Vn-1
Primitive definition: P,V0,V1 ,...Vn-1 ,V0
Triangle Fan (Examples)
Vertex Sequence
Central vertex
V11 V23 ::
Polygon Strips
Triangle and quad strips are convenient primitive types for the construction of surfaces between two polygonal chains (“slices”) with the same number of vertices.
One polygonal chain is usually a translated version of the other
V2 W W1 W2
Vertex Sequence V0
glBegin(GL_TRIANGLE_STRIP);
for (int i = 0; i < n; i++) {
glVertex3f(vx[i], vy[i], vz[i]);
glVertex3f(wx[i], wy[i], wz[i]);
Quad strip
Triangle strip
glBegin(GL_QUAD_STRIP);
for (int i = 0; i < n; i++) {
glVertex3f(vx[i], vy[i], vz[i]);
glVertex3f(wx[i], wy[i], wz[i]);
Vn-1 W1 W2
Triangle Strip: VV
Polygon Strips
glBegin(GL_TRIANGLE_STRIP);
glVertex3f(vx[0], vy[0],
glVertex3f(wx[0], wy[0],
Vn-1 glVertex3f(vx[1], vy[1], glVertex3f(wx[1], wy[1], glVertex3f(vx[2], vy[2], glVertex3f(wx[2], wy[2],
wz[0]); Triangle V W V
vz[1]); 0 0 1 wz[1]); Triangle W0V1W1 vz[2]); Triangle V1W1V2 wz[2]); Triangle W1V2W2
Triangle strip
Quad Strip
... glEnd();
glBegin(GL_QUAD_STRIP); glVertex3f(vx[0], vy[0], vz[0]); glVertex3f(wx[0], wy[0], wz[0]); glVertex3f(vx[1], vy[1], vz[1]); glVertex3f(wx[1], wy[1], wz[1]); glVertex3f(vx[2], vy[2], vz[2]); glVertex3f(wx[2], wy[2], wz[2]); ...
Quad strip
Vn-1 W1 W2
Quad W0V0V1W1 Quad W1V1V2W2
Note: First quad formed when W1 is processed.
Quad Strip
Rendering in 3D space requires normal vector definitions to be associated with the vertices of the quad strip
V Vi-1V 1i
glBegin(GL_QUAD_STRIP); for (int i = 1; i < n; i++) {
normal(vx[i-1], vy[i-1], vz[i-1],
wx[i-1], wy[i-1], wz[i-1],
wx[i], wy[i], wz[i]);
if(i==1) {
glVertex3f(vx[0], vy[0], vz[0]);
glVertex3f(wx[0], wy[0], wz[0]);
glVertex3f(vx[i], vy[i], vz[i]);
glVertex3f(wx[i], wy[i], wz[i]);
Each face’s normal vector is associated with a pair of corresponding vertices (except for the first quad).
Quad Strip
The order in which vertices are input to the normal() function will depend on the vertex definition of the quad
glBegin(GL_QUAD_STRIP); for (int i = 1; i < n; i++) {
normal(vx[i-1], vy[i-1], vz[i-1],
vx[i], vy[i], vz[i],
wx[i], wy[i], wz[i]);
if(i == 1) {
glVertex3f(vx[0], vy[0], vz[0]);
glVertex3f(wx[0], wy[0], wz[0]);
glVertex3f(vx[i], vy[i], vz[i]);
glVertex3f(wx[i], wy[i], wz[i]);
Quad Strip
Using face normal definitions in a quad strip will result in discontinuities in shades of colour rendered on the surface, and will clearly show the underlying polygonal structure.
The following surface is constructed using quad strips between consecutive slices, with face normal vectors associated with vertices as shown on previous slides.
Quad Strip Examples
A polygonal line V on the xz-plane is given by vertices (x[i], 0, z[i]), and is translated along the z direction by a distance d to get another polygonal line
W. The vertices of W are given by (x[i], 0, z[i] + d ) (x[i], 0, z[i])
Common normal vector
glNormal3f(0, 1, 0);
glBegin(GL_QUAD_STRIP);
for (int i = 0; i < n; i++) { glVertex3f(x[i], 0, z[i]); glVertex3f(x[i], 0, z[i]+d);
} glEnd();
A polygonal curve V on the xz-plane is given by vertices (x[i], 0, z[i]), and is translated along the y direction by a distance h to get another polygonal curve W. The vertices of W are given by (x[i], h, z[i])
glBegin(GL_QUAD_STRIP);
for (int i = 0; i < n; i++) { glVertex3f(x[i], 0, z[i]); glVertex3f(x[i], h, z[i]);
} glEnd();
Quad Strip Examples
A set of points (x[i], y[i], 0) on the xy plane form a circle V. This circle is translated along the z direction by a distance d to get another circle W. The vertices of W are given by (x[i], y[i], d )
w1 v1 w0 v0
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glBegin(GL_QUAD_STRIP);
for (int i = 0; i < 18; i++) {
glVertex3f(x[i], y[i], 0);
glVertex3f(x[i], y[i], d);
To get a closed surface, we must add the initial pair of points to the quad strip
glBegin(GL_QUAD_STRIP);
for (int i = 0; i < 18; i++) {
glVertex3f(x[i], y[i], 0);
glVertex3f(x[i], y[i], d);
glVertex3f(x[0], y[0], 0);
glVertex3f(x[0], y[0], d);
Modelling Surfaces in 3D
In many surface modelling applications, a polygonal line Vi is transformed into Wi, and the points connected by a triangle or quad strip. The transformation is repeated multiple times (with the Wi polygon as the new Vi ) to generate different layers (slices) of a 3D model.
A translation
along y-direction
A translation along z-direction
A scale transformation and a rotation
Surfaces generated by repeatedly transforming a COSC363 polygonal element are known as Sweep Surfaces.
Sweep Surface With Multiple Slices
Transform the points on V to W
Generate a quad strip between V and W
(including normal vectors)
Update V by copying the coordinates of
points in W to V
Update W by transforming V
Generate a quad strip between V and W (including normal vectors)
Repeat the above steps till the required number of slices are generated. Render the surface by assigning normal vectors to points and enabling lighting.
Sweep Surfaces
Main Steps
for (int slice = 0; slice < nslices; slice++) {
for (int i = 0; i < npoints; i++)
wx[i] = vx[i] * cos(angle) + vz[i] * sin(angle);
wy[i] = vy[i];
wz[i] = vz[i] * cos(angle) - vx[i] * sin(angle);
} glBegin(GL_QUAD_STRIP);
for (int i = 0; i < npoints; i++)
glVertex3f(vx[i], vy[i], vz[i]);
glVertex3f(wx[i], wy[i], wz[i]);
for (int i = 0; i < npoints; i++)
vx[i] = wx[i];
vy[i] = wy[i];
vz[i] = wz[i];
Transformation of VtoW
Quad strip construction
Updating V for next iteration
Sweep Surfaces
In general, the vertices of a polygonal line V may be transformed using a combination of rotation, scaling and translation.
We require the coordinates of points on W, and therefore we cannot use OpenGL transformation functions.
Surfaces of revolution are commonly generated using a
rotation about the y-axis by an angle :
(x, y, z) (xi, yi, zi)
Rotation about x axis:
Rotation about y axis:
Useful Formulae
𝑦′ =𝑦𝑐𝑜𝑠𝜃−𝑧𝑠𝑖𝑛𝜃 𝑧′ =𝑦𝑠𝑖𝑛𝜃+𝑧𝑐𝑜𝑠𝜃
Rotation about z axis:
𝑥′ =𝑥𝑐𝑜𝑠𝜃−𝑦𝑠𝑖𝑛𝜃 𝑦′ =𝑥𝑠𝑖𝑛𝜃+𝑦𝑐𝑜𝑠𝜃 𝑧′ = 𝑧
Surface of Revolution
A surface of revolution is obtained by revolving a polygonal curve (base curve) about an axis.
The points on the curve V are rotated about an axis to get the W curve.
Base Curve
x Example 1
VW i-1 i-1
for(int j = 0; j < nSlices; j++) {
for(int i = 0; i < N; i++) {
wx[i] = cos(angStep)*vx[i] + sin(angStep)*vz[i]; wy[i] = vy[i];
wz[i] = -sin(angStep)*vx[i] + cos(angStep)*vz[i];
glBegin(GL_QUAD_STRIP); for(int i = 0; i < N; i++) {
glVertex3f(vx[i], vy[i], vz[i]);
glVertex3f(wx[i], wy[i], wz[i]);
Surface of Revolution
Only rotation
for(int i = 0; i < N; i++) {
vx[i] = wx[i];
vy[i] = wy[i];
vz[i] = wz[i];
//Update vertices
The above code is used only for wireframe rendering. Normal vectors are not computed.
Surface of Revolution
The only transformation between slices V and W is a rotation.
We can rotate the normal vectors computed at points on V to get
the normal vectors at the corresponding points on W
Since the base curve is a 2D curve on a principal plane, the
normal vectors at its vertices can be easily computed. Vertex
normals provide a smooth rendering of a surface. Rotation
Unit direction vector (ux , uy) Perpendicular vector (uy , -ux)
Vertex normal (sum of perp vectors)
ni mi Wi
Base curve
ni is the vertex normal at Vi mi is the vertex normal at Wi
Vi Rotation Wi ni Rotation mi
Surface of Revolution
Assumption: Coordinatesandnormalvectorsatpointsonthebasecurvearegiven.
for(int j = 0; j < nSlices; j++) { //Transform verts and normals for(int i = 0; i < N; i++) {
wx[i] = cos(angStep)*vx[i] + sin(angStep)*vz[i]; wy[i] = vy[i];
wz[i] = -sin(angStep)*vx[i] + cos(angStep)*vz[i]; mx[i] = cos(angStep) * nx[i] + sin(angStep) * nz[i]; my[i] = ny[i];
mz[i] = -sin(angStep) *
nx[i] + cos(angStep) * nz[i];
//Generate quad strip
glBegin(GL_QUAD_STRIP);
for(int i = 0; i < N; i++)
{ glNormal3f(nx[i], ny[i], nz[i]); glVertex3f(vx[i], vy[i], vz[i]); glNormal3f(mx[i], my[i], mz[i]); glVertex3f(wx[i], wy[i], wz[i]);
} glEnd();
for(int i = 0; i < N; i++) { //Update verts and normals
vx[i] = wx[i]; vy[i] = wy[i]; nx[i] = mx[i]; ny[i] = my[i];
vz[i] = wz[i]; nz[i] = mz[i];
Computing Texture Coordinates
Texture coordinates for Vi :
Texture coordinates for Wi :
Texture Mapped Quad Strip
i/(n-1), 0 i/(n-1), 1
glBegin(GL_QUAD_STRIP); for(inti=0; i
Particle Update
Iterate over the entire list and update each particle’s attributes based on ‘t’.
Remove particles that have exceeded lifetime.
void update () {
list
particle p;
//Remove particles that have passed lifetime
if (!parList.empty()) {
p = parList.front();
if (p.t > T) parList.pop_front();
//Update parameters
for (it = parList.begin(); it != parList.end(); it++) { (it->t)++;
for (int i = 0; i < 3; i++)
(it->pos[i]) += (it->dir[i]) * speed;
it->size = …;
it->delta = …; COSC363
Particle Update
Timer Callback
void timer(int value)
counter++;
if (counter % m == 0) newParticle(); update();
glutTimerFunc(30, timer, 0); glutPostRedisplay();
void display()
Particle List
Particle Rendering
A particle may be rendered as a set of texture mapped quads. Two quads mutually perpendicular to each other, are commonly used.
Sample textures
Texture mapped Quads Without Blending
Particle Model With Blending
Particle Rendering
A particle may be rendered using a set of basic primitives Triangle Fan
Edge vertices: glColor4f(1, 1, 1, 0); Central vertex: glColor4f(1, 0, 0, 1);
Particle Model Without Blending
Particle Model With Blending
Particle Rendering
Blending: The particle’s colour (source or foreground) must be blended with the colour of the fragment (destination or background) at the position where the particle is rendered.
The alpha value of source is commonly used for blending:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); output: s+(1- )d
The source colour itself may be used for blending (if alpha channel is not available):
glBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR); output: ss+(1-s)d
Source + Destination:
glBlendFunc(GL_ONE, GL_ONE);
output: s + d
No blending
glBlendFunc(GL_ONE, GL_ZERO);
output: s
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com