【问题标题】:How can I draw a cylinder that connects two points in OpenGL如何在OpenGL中绘制连接两个点的圆柱体
【发布时间】:2010-12-25 02:18:39
【问题描述】:

我有两个点,每个点都有自己的 X 和 Y 值,并且它们具有相同的 Z 值。

我想要一个在这两点之间绘制圆柱体的函数。

【问题讨论】:

  • 我认为你必须更加具体。
  • 有无数个圆柱体包含这两个点。你能描述一下你希望圆柱体如何相对于这些点定向吗?我怀疑你想要一个单位(或用户指定)半径的圆柱体,这两个点在其中心线上的两端。但你需要具体...

标签: c++ opengl 3d


【解决方案1】:

要构建具有两个给定点的圆柱体,您需要进行矢量分析。您正在构建两个垂直向量,它们被添加到每个点并用 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();      
}

【讨论】:

    【解决方案2】:

    如果您不能使用 GLU 库中的 gluCylinder()(例如,如果您使用 OpenGL-ES)

    或者你必须用小的扁平部分制作圆柱体的侧面,
    How do you draw a cylinder with OpenGLES?

    【讨论】:

    • 但我需要一个函数来计算点之间的 X 和 Y 角度并将圆柱体从第一个绘制到另一个
    【解决方案3】:

    此解决方案假定您有一些通用的相机代码,将 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();
    
    }
    

    【讨论】:

      【解决方案4】:

      使用当前接受的答案发现错误。最终想出了我自己的。你可以用一些简单的数学来做到这一点:

      http://www.thjsmith.com/40/cylinder-between-two-points-opengl-c

      【讨论】:

      • 把代码放在你的答案中;不要只是链接到某个网站。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-22
      相关资源
      最近更新 更多