Cilindro Generalizadfo
Para este trabalho, use cilindros generalizados e splines para modelar
uma forma interessante. Para isto, deslize uma curva bidimensional (perpendicularmente)
ao longo de um esqueleto (uma curva) definido por uma spline para gerar
uma superficie. A forma final pode ser uma cobra, uma cadeia de caracteres
formada por uma sequencia de macarroes, ou qualquer outra forma parecida
com um tubo. Apos esta faze, voce deve fazer uma animacao com a forma gerada.
Ou seja, mova-a no espaco, modifique a forma dela (isto seria muito interessante)
fazendo uma camera virtual voar sobre ela. Esta animacao deve ser feita
usando recusros so OpenGL e Linguagem C. Pense em movimentos interessantes
que voce pode gerar. Pense tambem em quais texturas, sombreamento, ou outras
caracteristicas de shading interessantes voce pode implementar.
Requerimentos
-
Use splines cubicas de continuidade no minimo C1 (sugere-se Catmull-Rom
splines) para definir o a curva do esqueleto e a curva seccional (a ser
deslizada).
-
Voce deve colocar na interface sliders ou outros tipo de tipos de controle
para controlar o numero de amostras da curva esqueleto bem como da curva
seccional, de maneira que voce faca sua superficie parecer suave (pode
levar alguns segundos para gerar uma figura bem suave com o Mesa).
-
o seu modelo deve ser parametrizado de modo que voce tenha sliders que
controlam a forma de forma continua, isto eh, raio, forma e numero de segmentos
da secao de corte (curva seccional), bem como outros parametros que sejam
relevantes ao seu projeto.
-
Seu programa deve mostrar o esqueleto spline (usando GL_LINE_STRIP), a
forma wire-frame (GL_LINE_LOOP de suas secoes) e a pele (ver abaixo). Coloque
botoes para tornar estas caracteristicas on e off. Use Gouraud Shading
(um vetor normal por vertice) para melhorar a suavidade. OpenGL faz isso
por default. Suas superficies devem ser iluminadas (nao "flat-color").
Voce deve tambem modificar no seu programa a iluminacao default.
-
Voce deve tambem ter uma maneira interativa de girar e transladar o objeto
no ambiente, atraves de sliders, arrastando o mouse (preferivel) ou outro
meio qualquer (apertando tecla, etc).
-
Seu programa deve executar em tempo real (ou proximo disso), ou seja, abaixo
de dois ou tres quadros por segundo para um numero pequeno de amostras
nas curvas.
-
Crie uma ou mais animacoes de pelo menos 100 quadros em cada sequencia
(nao mais que 300, por favor). Se quiser gerar mais que isso, por favor,
entre em contato explicando o motivo. O mais interessante eh que voce mostre
formas interessantes e controlaveis do que gerar uma sequencia grande.
-
Use uma malha de poligonos com boa resolucao.
-
Nomeie cada frame como 00.gif, 01.gif, 02.gif, ... 49.gif, etc. Gere um
gif animado com esta sequencia e
coloque num disquete identificado (o qual deverá ser entregue
no final). Coloque junto o seu código
(comentado).
-
As imagens geradas devem ser de 640x480, em formato gif.
Dicas
-
To draw the generalized cylinder you will need to calculate the world coordinates
of the cylinder's outline at each small step along the spline. Assuming
that the outline has been defined in the xy-plane, to calculate the world
coordinates you will need to rotate (in 3D) the xy-plane so that it becomes
orthogonal to the skeleton spline at that point (ie the skeleton spline
is the normal to the xy-plane, or the z-axis) and then translate it to
the correct position. The suggested method to calculate this rotation is:
-
calculate the rotation axis by taking the cross-product of the spline's
local direction and the z-axis. (when will this
fail? - think about when the gradient of the spline is negative and
you are taking the arcsin.)
-
calculate the angle of rotation using the dot product or magnitude of the
cross product vector.
This may be sufficient for you - however it does not control the rotation
about the z-axis at all and you could find situations where a "kink" appears
in your cylinder - particularly where the rotation angle is close to a
limit (eg +/- 90 for sin). If you want/need to control the spline's rotation
about the z-axis then:
- record the previous outline x-axis direction and also rotate the
outline about the z-axis to keep the new x-axis aligned with the old one.
-
Then put a "skin" on your creation using filled polygons. Once you've got
the above working this is pretty easy. You could use glBegin(GL_TRIANGLE_STRIP)
and remember to specify a normal for each vertex (ie. ... glNormal3 ...
glVertex...). Remember the glEnd() as well!
Idea on implementation: You could think of the vertices
along each cross sectional curve as making a "column" of vertices, and
all the vertices at corresponding positions on each section forming a "row"
of vertices. All the vertices and the triangles connecting them form a
grid that makes up the skin. You should calculate this grid only when necessary
and not each time you redisplay, as an optimization.
Optimization: When you create this grid of points, you
could also calculate your surface normals (OpenGL does not do this for
you!). Then when you are displaying your wireframe or skin, you can
use the precalculated normals.
-
Precisely how you generate your animation is up to you. It could be frame-by-frame,
where you adjust the parameters by hand and hit a SAVE button for each
frame, say, or it could be procedural, where you program in some interesting
motion (slithering, traveling along the track, etc) and sit back and let
your program generate all the images. You can preview the animation with
the "xplay" program, as in Asst1.
-
You'll probably want to use the TIFF output routines from assignment 1.
All these big picture files could use many tens of megabytes, so watch
your disk usage.
Where to Start
This section gives you a vague idea (just a suggestion)
of how to go about doing all this stuff.
-
Implement splines. This is relatively simple plus you can write it
and test it without needing any OpenGL (but you can do it however you like.)
-
Implement Wireframe (by using the grid idea). This requires a bit
more work. First you need to get your cross sectional curve that
you will sweep along your skeleton curve. After you have this, you
will need to multiply the points by a rotation matrix to make the plane
they lie on's normal the same as the spline normal. Store these points
and you you just need to add the GL_LINE_LOOP and you are ready for the
next step.
-
Implement skin. This requires you to have step 2 complete.
To get the skin isn't much of a problem (just use the afformentioned GL_TRIANGLE_STRIP)
the key is to fiddle with the normals and the lighting to make it look
the way you want.
-
Work on getting a nice shape to use for an animation and then all you have
left is your animation.
More Optimizatoins
This part tells you how you could speed up your code.
-
Speeding up spline calculations: Forward Differencing. See page 511
of Foley for more on that. This is purely extra credit, but if you
do it, you should definately tell us during the demo!
-
Quaternions: These aren't actually an optimization as such.
They are just another way of doing the Axis/Angle rotation required for
sweeping a shape along a line. The key to them is that they allow
you to add Axis/Angle rotations easily. They are more used for animation
then just a singular rotation. But, if you implement them correctly,
show us and it will be extra credit.
Examples and Ideas for Generalized Cylinders
These first few are simple but boring:
-
a circle swept along a line makes a cylinder
-
a circle swept along a line and scaled at a constant rate defines a cone
-
a circle swept along a circle defines a torus
Much more interesting:
-
an ellipse swept along a curve with the right scaling defines a fish (sans
fins)
-
if the skeleton curve branches, you could make a tree with tapering branches
and trunk
-
if the curve being swept is a 2-D character outline, and it is swept along
a very short line with the appropriate scaling, you get a beveled 3-D font
-
blades of grass
-
ribbon
-
pasta!
Some Extra Ideas
-
Shapes:
-
realistic snake skin
-
braid
-
woven fabric (model the warp & woof!)
-
knotted rope
-
Medusa
-
Controls:
-
Draw a curve to control the longitudinal envelope (taper).
-
Geometry:
-
Make your Cylinder a set bicubic parametric patches, add in support for
reading files of arbitrary bicubic patches.
-
Other Things:
-
Forward Differencing
-
Quaternions
Other Info on Generalized Cylinders