2009-12-10 148 views
0

我有兩個點,每個點都有其自己的X和Y值,並且它們具有相同的Z值。如何繪製連接OpenGL中兩個點的圓柱體

我想要一個函數在這兩點之間繪製圓柱體。

+0

我認爲您將必須更加具體。 – bmargulies 2009-12-10 02:19:40

+0

有無數個圓柱包含這兩點。你能描述一下你希望氣缸相對於點的方向嗎?我懷疑你需要一個單元(或用戶指定的)半徑的圓柱體,它的兩端都在其中心線上。但你需要具體... – 2009-12-15 04:34:08

回答

0

如果你不能從GLU庫(例如,如果你洛根。基於OpenGL-ES)使用gluCylinder()

或者你必須從小平段使氣缸的兩側,
How do you draw a cylinder with OpenGLES?

+0

但我需要一個函數來計算點之間的X和Y角度,並從第一個到另一個繪製柱面 – trrrrrrm 2009-12-10 02:26:53

2

對於用兩個給定點構建圓柱體,您需要矢量分析。您正在構建兩個垂直向量,這些向量被添加到每個點,並且按照sin/cos乘以半徑進行縮放。 它接受所有點(舊代碼有一個錯誤,因爲它錯過了長度的sqrt())。 現在它功能正常,並用gl例程繪製圓柱體;我在JOGL中測試過它。 要獲得更快的繪製,請將firstPerpVector/secondPerpVector/points變量移至私有最終數組字段,並在開始時對它們進行初始化。

Java代碼:

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();  
} 
0

此解決方案假定您已經結合了3D矢量和4D四元數成一個單一的實用工具類,一些通用的攝像頭的代碼。因此,對於世界空間中的兩個3D點A和B,從A到B繪製柱面的一般解決方案是:

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(); 

}