Instanced Matrxies and Pipes

Dear All,
I’ve been tasked with drawing lots of pipes. Exciting I know. Basicly I’m being passed an array of points, and I draw the pipes based of those, treating each point as an end point of a pipe. I’m using an instance of a cylinder to do this, and my problem is in creating the matrix for each instance. Basicly I cant figure out why my rotation angles are not turning out right. I basicly need an XY and a YZ rotation angle, which I generate in the following manner :

  TempPipePoint.x = (Temp1->x + Temp2->x)/2;
  TempPipePoint.y = (Temp1->y + Temp2->y)/2;
  TempPipePoint.z = (Temp1->z + Temp2->z)/2;

  float fDx = Temp2->x - Temp1->x;
  float fDy = Temp2->y - Temp1->y;
  float fDz = Temp2->z - Temp1->z;

  TempPipePoint.anglexy = atan2( (fDy), (fDx) ) ;
  TempPipePoint.angleyz = -atan2( (fDz), (fDy) )  ;
  TempPipePoint.length = sqrt( (fDx) * (fDx)  + (fDy) * (fDy) + (fDz) * (fDz) );

  TempPipePoint.isnop = false;


Then I create the matrix as below :

RotX[0] = cos(xyrot );
RotX[1] = -sin(xyrot );

RotX[4] = sin(xyrot);
RotX[5] = cos(xyrot );

RotY[5] = cos(yzrot );
RotY[6] = -sin(yzrot );

RotY[9] = sin(yzrot );
RotY[10] = cos(yzrot );

TempRotationMatrix *= RotX;
TempRotationMatrix *= RotY; // Seperated For debugging, instead of building the entire matrix at once.

This works as I would expect if the pipe points are all on the XY plane, but if I vary the Z cordinates the thing goes haywire, with the exception that it works ok for a pipe that has an end point on the origin, which is a bit odd. Does anyone have an idea what I’m doing wrong?

Here’s one way to draw it. I use this to draw arrows for coordinate system axes and so forth. One problem you might have is matching up cylinder vertices from one to the next due to the basis changing with the major axis of direction. Fixing that is left as an exercise ;-).

I’m sure you could get there with the rotation approach too, but I haven’t played with that.

Hope it helps.

struct Vector3
    float X, Y, Z;

    // ...

    int MajorAxis() const
        float ax = fabs(X);
        float ay = fabs(Y);
        float az = fabs(Z);
        if (ay > ax) 
            return az > ay ? 2 : 1;
            return az > ax ? 2 : 0;

    void TangentVectors(Vector3& Y, Vector3& Z) const
        Vector3 temp(0,0,0);
        switch (MajorAxis())
            case 0:
            case 1: temp.Z = 1; break;
            default: temp.X = 1; break;
        Y = temp.Cross(*this).Normalize();
        Z = this->Cross(Y).Normalize();

void DrawCylinder(const Vector3& from, const Vector3& to, float radius)
    Vector3 delta = to - from;

    float length = delta.Length();
    Vector3 X = delta.Normalize();
    Vector3 Y, Z;
    X.TangentVectors(Y, Z);
    Vector3 T = from;

    float mat[16] = 
        X.X, X.Y, X.Z, 0,
        Y.X, Y.Y, Y.Z, 0,
        Z.X, Z.Y, Z.Z, 0,
        T.X, T.Y, T.Z, 1

        // Draw a cylinder of radius with base at origin, and aligned along the z-axis
        DrawCylinder(radius, length);