问题
How do you draw a cylinder with OpenGLES?
回答1:
You'll need to do it via object loading. You can't call on 3D shape primitives using Open GL ES.
Look through Jeff Lamarche's blog, there's lots of really good resources on how to object load there. link text
回答2:
First step is to write a subroutine that draws a triangle. I'll leave that up to you. Then just draw a series of triangles the make up the shape of a cylinder. The trick is to approximate a circle with a polygon with a large number of sides like 64. Here's some pseudo-code off the top of my head.
for (i = 0; i < 64; i++)
{
angle = 360 * i / 63; // Or perhaps 2 * PI * i / 63
cx[i] = sin(angle);
cy[i] = cos(angle);
}
for (i = 0; i < 63; i++)
{
v0 = Vertex(cx[i], cy[i], 0);
v1 = Vertex(cx[i + 1], cy[i + 1], 0);
v2 = Vertex(cx[i], cy[i], 1);
v3 = Vertex(cx[i + 1], cy[i + 1], 1);
DrawTriangle(v0, v1, v2);
DrawTriangle(v1, v3, v2);
// If you have it: DrawQuad(v0, v1, v3, v2);
}
There is almost certainly a mistake in the code. Most likely is that I've screwed up the winding order in the triangle draws so you could end up with only half the triangles apparently visible or a very odd case with only the back visible.
Performance will soon want you drawing triangle strips and fans for efficiency, but this should get you started.
回答3:
You can indeed draw a cylinder in OpenGL ES by calculating the geometry of the object. The open source GLUT|ES project has geometry drawing routines for solids (cylinders, spheres, etc.) within its glutes_geometry.c source file. Unfortunately, these functions use the glBegin() and glEnd() calls, which aren't present in OpenGL ES.
Code for a partially working cylinder implementation for OpenGL ES can be found in the forum thread here.
回答4:
I hope this can help you, this is my implementation of a cylinder in OpenGLES 2.0 for Android
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class Cylinder {
public Cylinder(int n) {
this.numOfVertex = n;
float[] vertex = new float[3 * (n + 1) * 2];
byte[] baseIndex = new byte[n];
byte[] topIndex = new byte[n];
byte[] edgeIndex = new byte[n*2 + 2];
double perAngle = 2 * Math.PI / n;
for (int i = 0; i < n; i++) {
double angle = i * perAngle;
int offset = 6 * i;
vertex[offset + 0] = (float)(Math.cos(angle) * radious) + cx;
vertex[offset + 1] = -height;
vertex[offset + 2] = (float)(Math.sin(angle) * radious) + cy;
vertex[offset + 3] = (float)(Math.cos(angle) * radious) + cx;
vertex[offset + 4] = height;
vertex[offset + 5] = (float)(Math.sin(angle) * radious) + cy;
topIndex[i] = (byte)(2*i);
baseIndex[i] = (byte)(2*i +1);
edgeIndex[2*i + 1] = baseIndex[i];
edgeIndex[2*i] = topIndex[i];
}
edgeIndex[2*n] = topIndex[0];
edgeIndex[2*n+1] = baseIndex[0];
ByteBuffer vbb = ByteBuffer
.allocateDirect(vertex.length * 4)
.order(ByteOrder.nativeOrder());
mFVertexBuffer = vbb.asFloatBuffer();
mFVertexBuffer.put(vertex);
mFVertexBuffer.position(0);
normalBuffer = mFVertexBuffer;
mCircleBottom = ByteBuffer.allocateDirect(baseIndex.length);
mCircleBottom.put(baseIndex);
mCircleBottom.position(0);
mCircleTop = ByteBuffer.allocateDirect(topIndex.length);
mCircleTop.put(topIndex);
mCircleTop.position(0);
mEdge = ByteBuffer.allocateDirect(edgeIndex.length);
mEdge.put(edgeIndex);
mEdge.position(0);
}
public void draw(GL10 gl)
{
gl.glCullFace(GL10.GL_BACK);
gl.glEnable(GL10.GL_CULL_FACE);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mFVertexBuffer);
gl.glNormalPointer(GL10.GL_FLOAT, 0, normalBuffer);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glPushMatrix();
gl.glColor4f(1f, 0, 0, 0);
gl.glDrawElements( GL10.GL_TRIANGLE_STRIP, numOfVertex * 2 + 2, GL10.GL_UNSIGNED_BYTE, mEdge);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glColor4f(0.9f, 0, 0, 0);
gl.glDrawElements( GL10.GL_TRIANGLE_FAN, numOfVertex, GL10.GL_UNSIGNED_BYTE, mCircleTop);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glTranslatef(0, 2*height, 0);
gl.glRotatef(-180, 1, 0, 0);
gl.glColor4f(0.9f,0, 0, 0);
gl.glDrawElements( GL10.GL_TRIANGLE_FAN, numOfVertex , GL10.GL_UNSIGNED_BYTE, mCircleBottom);
gl.glPopMatrix();
}
private FloatBuffer mFVertexBuffer;
private FloatBuffer normalBuffer;
private ByteBuffer mCircleBottom;
private ByteBuffer mCircleTop;
private ByteBuffer mEdge;
private int numOfVertex;
private int cx = 0;
private int cy = 0;
private int height = 1;
private float radious = 1;
}
回答5:
You can draw a cylinder procedurally by calculating the geometry. On top of that though, you should make it so that it supports triangle stripping and you also need to calculate the mapping coordinates and possibly the normals too. So it will take a bit of thinking to do from scratch.
I have created a module for Unity3D in C# that does exactly this and allows you to tweak the parameters. You should be able to easily convert to C or C++ as the geometry calculation is the same everywhere. Watch the video to see what it's about and download the code from GitHub.
来源:https://stackoverflow.com/questions/1056504/how-do-you-draw-a-cylinder-with-opengles