|
From: Press, S. <sha...@ai...> - 2003-02-19 22:47:56
|
I have managed to add Tetrahedron, Pyramid and Frustum to the primitive
shapes in my copy of Visual Python.
The terahedron and pyramid a pretty simple to do as they are a specific form
of the cone shape.
In the cone.cpp file there is a section devoted to calculating the level of
detail for the shape. The idea is that closer shapes are drawn with a lot of
detail while distant shapes require less. Depending on the size and location
of the cone it can be drawn with 20 panels down to 5 panels. The number of
panels is passed to the cyl_model object which returns the vertices required
to draw the shape.
To draw a pyramid, simply drop the level of details code and just pass 5 to
the cyl_model::get(n) method. This will return the vertices of a cube. Of
course a cube isn't what was asked for but some extra work is done. The tip
of the cone is calculated by passing a vector (2,0,0) to the mct.project
method. This point is the middle of the base, moved two units along the
x-axis. Inside the projection loop every second vertex is replaced by the
tip vertex, which when rendered makes the faces of the shape meet at the
tip. This results in a cone/pyramid/tetrahedron depending on the number of
faces required. For tetrahedron simply use the 4 vertices rather than 5 for
a pyramid.
As for the actual rendering by openGL, the array of vertices is used to draw
GL_TRIANGLE_STRIP geometries. This is a pretty flexible and efficient way to
do it, as GL_QUAD_STRIP geometries require some extra vertex calculations.
In the case of a cone the triangle strip vertecies go
v1 |\ |\v3
| \ | \
| \ | \
v0 | \|v2\|
etc (hopefully this crude ascii diagram comes out ok)
OpenGl fills in both sides of the triangle ie v0,v1,v2 and v1,v2,v3 are
filled when drawn.
Of course when drawing a cone/pyramid/tetrahedron there is obvious
redundancy as v1==v3==v5 etc. A more efficient method would be to use
GL_TRIANGLE_FAN which has a central point for all triangles and the vertices
for the base points eg tip would be v0 and v1, v2, v3 etc would be the base
points. The triangles would the be (v0,v1,v2), (v0,v2,v3) etc Using this
method would cut the calculating/drawing time for cones etc in half.
The final rendering is for the base. This is done using the GL_POLYGON
geometry which fills in a shape enclosed by points v0,v2,v4 etc ie the
triangle base points.
The frustum was a little more frustrating to get right. In the end I made a
copy of cylmodel.h and called it frustmodel.h. I then modifed the method
that returns the vertices of the cylinder to set the top vertices at half
the radius of the bottom ones. Trying to do this inside the frustum
projection loop in frustum.cpp caused some bizzare results.
I had hoped to avoid making almost identical copies of other modules as this
adds to code bloat, but for the moment this will do.
I haven't added any new attributes to the shapes, instead relying on the
ones provided. That means that the size of the base of the
pyramid/tetrahedon uses the radius attribute and is the distance from the
mid point of the base to the corner vertex. For the frustum the radius at
the top is fixed to be half the radius of the base.
BTW As I remarked in my first post frustum is not a good name for this
shape, at least internally, as it causes compile errors due to the clash
with the frustum methods used to handle the camera in openGl. I've called it
frustm in the short term but does anyone have a better suggestion?
|