void render2x(bool fill, short colix, int tension,
                      //top strand segment
                      Point3i p0, Point3i p1, Point3i p2, Point3i p3,
                      //bottom strand segment
                      Point3i p4, Point3i p5, Point3i p6, Point3i p7)
        {
            Point3i[] endPoints = { p2, p1, p6, p5 };
            // stores all points for top+bottom strands of 1 segment
            List<Point3i> points = new List<Point3i>(10);
            int whichPoint = 0;

            int numTopStrandPoints = 2; //first and last points automatically included
            float numPointsPerSegment = 5.0f;//use 5 for mesh

            // could make it so you can set this from script command
            if (fill)
                numPointsPerSegment = 10.0f;

            float interval = (1.0f / numPointsPerSegment);
            float currentInt = 0.0f;

            int x1 = p1.x, y1 = p1.y, z1 = p1.z;
            int x2 = p2.x, y2 = p2.y, z2 = p2.z;
            int xT1 = ((x2 - p0.x) * tension) / 8;
            int yT1 = ((y2 - p0.y) * tension) / 8;
            int zT1 = ((z2 - p0.z) * tension) / 8;
            int xT2 = ((p3.x - x1) * tension) / 8;
            int yT2 = ((p3.y - y1) * tension) / 8;
            int zT2 = ((p3.z - z1) * tension) / 8;
            sLeft[0] = 0;
            pLeft[0].set_Renamed(p1);
            sRight[0] = 1;
            pRight[0].set_Renamed(p2);
            sp = 0;
            g3d.setColix(colix); // set colix here for entire routine

            for (int strands = 2; strands > 0; strands--)
            {
                if (strands == 1)
                {
                    x1 = p5.x; y1 = p5.y; z1 = p5.z;
                    x2 = p6.x; y2 = p6.y; z2 = p6.z;
                    xT1 = ( (x2 - p4.x) * tension) / 8;
                    yT1 = ( (y2 - p4.y) * tension) / 8;
                    zT1 = ( (z2 - p4.z) * tension) / 8;
                    xT2 = ( (p7.x - x1) * tension) / 8;
                    yT2 = ( (p7.y - y1) * tension) / 8;
                    zT2 = ( (p7.z - z1) * tension) / 8;
                    sLeft[0] = 0;
                    pLeft[0].set_Renamed(p5);
                    sRight[0] = 1;
                    pRight[0].set_Renamed(p6);
                    sp = 0;
                }

                points.Add(endPoints[whichPoint++]);
                currentInt = interval;
                do
                {
                    Point3i a = pLeft[sp];
                    Point3i b = pRight[sp];
                    int dx = b.x - a.x;
                    int dy = b.y - a.y;
                    int dist2 = dx * dx + dy * dy;
                    if (dist2 <= 2)
                    {
                        // mth 2003 10 13
                        // I tried drawing short cylinder segments here,
                        // but drawing spheres was faster
                        float s = sLeft[sp];

                        g3d.fillSphereCentered(colix, 3, a);
                        //draw outside edges of mesh

                        if (s < 1.0f - currentInt)
                        { //if first point over the interval
                            Point3i temp = new Point3i();
                            temp.set_Renamed(a);
                            points.Add(temp); //store it
                            currentInt += interval; // increase to next interval
                            if (strands == 2)
                            {
                                numTopStrandPoints++;
                            }
                        }
                        --sp;
                    }
                    else
                    {
                        double s = (sLeft[sp] + sRight[sp]) / 2;
                        double s2 = s * s;
                        double s3 = s2 * s;
                        double h1 = 2 * s3 - 3 * s2 + 1;
                        double h2 = -2 * s3 + 3 * s2;
                        double h3 = s3 - 2 * s2 + s;
                        double h4 = s3 - s2;
                        Point3i pMid = pRight[sp + 1];
                        pMid.x = (int)(h1 * x1 + h2 * x2 + h3 * xT1 + h4 * xT2);
                        pMid.y = (int)(h1 * y1 + h2 * y2 + h3 * yT1 + h4 * yT2);
                        pMid.z = (int)(h1 * z1 + h2 * z2 + h3 * zT1 + h4 * zT2);
                        pRight[sp + 1] = pRight[sp];
                        sRight[sp + 1] = sRight[sp];
                        pRight[sp] = pMid;
                        sRight[sp] = (float)s;
                        ++sp;
                        pLeft[sp].set_Renamed(pMid);
                        sLeft[sp] = (float)s;
                    }
                }
                while (sp >= 0);

                points.Add(endPoints[whichPoint++]);
            } //end of for loop - processed top and bottom strands
            int size = points.Count;
            if (fill)
            {   //RIBBONS
                Point3i t1 = null;
                Point3i b1 = null;
                Point3i t2 = null;
                Point3i b2 = null;
                int top = 1;

                Vector3[] strip = new Vector3[numTopStrandPoints * 2];
                int stIdx = 0;
                for (; top < numTopStrandPoints && (top + numTopStrandPoints) < size; top++)
                {
                    t1 = points[top - 1];
                    b1 = points[numTopStrandPoints + (top - 1)];

                    strip[stIdx++] = new Vector3(t1.X, t1.y, t1.z);
                    strip[stIdx++] = new Vector3(b1.x, b1.y, b1.z);
                }
                if ((numTopStrandPoints * 2) != size)
                {   //BUG(DC09_MAY_2004): not sure why but
                    //sometimes misses triangle at very start of segment
                    //temp fix - will inestigate furture
                    g3d.fillTriangle(p1, p5, t2);
                    g3d.fillTriangle(b2, t2, p5);
                }
                g3d.FillTriangleStrip(strip);
            }
            else
            {   //MESH
                for (int top = 0;
                     top < numTopStrandPoints && (top + numTopStrandPoints) < size; top++)
                {
                    g3d.drawLine(points[top],
                                 points[top + numTopStrandPoints]);
                }
            }
        }