问题
i have two point each point has its own X and Y value and they have the same Z value.
i want a function to draw Cylinder between these two points.
回答1:
For building a cylinder with two given points, you need vector analysis. You are building two perpendicular vectors which are added to each point and scaled with sin/cos multiplied with the radius. It accepts all points (The old code had a bug because it missed the sqrt() for the length). Now it functions correctly and draw the cylinder with gl routines; I tested it in JOGL. For faster drawing move the firstPerpVector/secondPerpVector/points variable to a private final array field and initialize them at the beginning.
Java code:
public float[] getFirstPerpVector(float x, float y, float z) {
float[] result = {0.0f,0.0f,0.0f};
// That's easy.
if (x == 0.0f || y == 0.0f || z == 0.0f) {
if (x == 0.0f)
result[0] = 1.0f;
else if (y == 0.0f)
result[1] = 1.0f;
else
result[2] = 1.0f;
}
else {
// If xyz is all set, we set the z coordinate as first and second argument .
// As the scalar product must be zero, we add the negated sum of x and y as third argument
result[0] = z; //scalp = z*x
result[1] = z; //scalp = z*(x+y)
result[2] = -(x+y); //scalp = z*(x+y)-z*(x+y) = 0
// Normalize vector
float length = 0.0f;
for (float f : result)
length += f*f;
length = (float) Math.sqrt(length);
for (int i=0; i<3; i++)
result[i] /= length;
}
return result;
}
public void drawCylinder(GL gl, float x1, float y1, float z1, float x2, float y2, float z2) {
final int X = 0,
Y = 1,
Z = 2;
// Get components of difference vector
float x = x1-x2,
y = y1-y2,
z = z1-z2;
float[] firstPerp = getFirstPerpVector(x,y,z);
// Get the second perp vector by cross product
float[] secondPerp = new float[3];
secondPerp[X] = y*firstPerp[Z]-z*firstPerp[Y];
secondPerp[Y] = z*firstPerp[X]-x*firstPerp[Z];
secondPerp[Z] = x*firstPerp[Y]-y*firstPerp[X];
// Normalize vector
float length = 0.0f;
for (float f : secondPerp)
length += f*f;
length = (float) Math.sqrt(length);
for (int i=0; i<3; i++)
secondPerp[i] /= length;
// Having now our vectors, here we go:
// First points; you can have a cone if you change the radius R1
final int ANZ = 32; // number of vertices
final float FULL = (float) (2.0f*Math.PI),
R1 = 4.0f; // radius
float[][] points = new float[ANZ+1][3];
for (int i=0; i<ANZ; i++) {
float angle = FULL*(i/(float) ANZ);
points[i][X] = (float) (R1*(Math.cos(angle)*firstPerp[X]+Math.sin(angle)*secondPerp[X]));
points[i][Y] = (float) (R1*(Math.cos(angle)*firstPerp[Y]+Math.sin(angle)*secondPerp[Y]));
points[i][Z] = (float) (R1*(Math.cos(angle)*firstPerp[Z]+Math.sin(angle)*secondPerp[Z]));
}
// Set last to first
System.arraycopy(points[0],0,points[ANZ],0,3);
gl.glColor3f(1.0f,0.0f,0.0f);
gl.glBegin(GL.GL_TRIANGLE_FAN);
gl.glVertex3f(x1,y1,z1);
for (int i=0; i<=ANZ; i++) {
gl.glVertex3f(x1+points[i][X],
y1+points[i][Y],
z1+points[i][Z]);
}
gl.glEnd();
gl.glBegin(GL.GL_TRIANGLE_FAN);
gl.glVertex3f(x2,y2,z2);
for (int i=0; i<=ANZ; i++) {
gl.glVertex3f(x2+points[i][X],
y2+points[i][Y],
z2+points[i][Z]);
}
gl.glEnd();
gl.glBegin(GL.GL_QUAD_STRIP);
for (int i=0; i<=ANZ; i++) {
gl.glVertex3f(x1+points[i][X],
y1+points[i][Y],
z1+points[i][Z]);
gl.glVertex3f(x2+points[i][X],
y2+points[i][Y],
z2+points[i][Z]);
}
gl.glEnd();
}
回答2:
If you cant use gluCylinder() from the GLU library (eg if you ae on OpenGL-ES)
Or you have to make the sides of the cylinder from small flat segments,
How do you draw a cylinder with OpenGLES?
回答3:
This solution assumes you have some generic Camera code that combines a 3D vector and a 4D quaternion into a single utility class. So for two 3D points A and B in world space, the general solution for drawing a cylinder from A to B is:
void draw_cylinder
(
const vector3d& A
,const vector3d& B
,const double radius
)
{
// STEP 1: calculate the distance between the points A and B
double height = (B-A).length();
// STEP 2: put a camera object at point A
camera C(A); // quat rotation assumed to be facing -Z axis
// STEP 3: tell the camera to look directly at point B
C.look_at(B);
// STEP 4: save the current OpenGl matrix state
glPushMatrix();
// STEP 5: give the camera transform to OpenGL
C.apply_transform_model_to_world();
// STEP 6: draw your cylinder from (0,0,0) to (0,0,-height)
gluCylinder
(
pqobj //GLUquadric*
,radius //GLdouble base
,radius //GLdouble top
,height //GLdouble
,8 //GLint slices
,8 //GLint stacks
);
// STEP 7: restore the OpenGl matrix stack
glPopMatrix();
}
回答4:
Found bugs using the currently accepted answer. Ended up coming up with my own. You can do it with some simple maths:
http://www.thjsmith.com/40/cylinder-between-two-points-opengl-c
来源:https://stackoverflow.com/questions/1878257/how-can-i-draw-a-cylinder-that-connects-two-points-in-opengl