28-Utah茶壶算法

参考:https://www.bilibili.com/video/BV1v14y1W7sA

数据:https://github.com/dasch/graphics/blob/master/data/teapot.data

茶壶类

class UTeapot   // 茶壶类
{
public:
    Point3 Vertex[306]; // 306顶点
    Patch  _patch[32];  // 32个曲面
    BicubicBezierPatch Patch; // Bezier曲面
public:
    UTeapot() {};
    ~UTeapot() {};
    void ReadVertext()
    {
        // 茶壶顶点
        std::string strVertex = R"(  1   1.40000   0.00000   2.40000
            2   1.40000  -0.78400   2.40000 
              .....
              .....              
            306   1.42500  -0.79800   0.00000)";


            std::stringstream  stream(strVertex);           
            char strLine[1024];
            int index,res;
            double x, y, z;
            while (stream.getline(strLine, 1024))
            {
                res=sscanf(strLine, "%d  %lf %lf %lf", &index, &x, &y, &z);
                if (res > 0)
                {
                    Vertex[index-1] = Point3(x,y,z);
                }
            }
           

    }
    void ReadPath()
    {
        // 茶壶顶点索引
        std::string indices = R"(  1	  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
                                   .....
 32	270 270 270 270 300 305 306 279 297 303 304 275  96  95  94  93)";


        std::stringstream  stream(indices);
        char strLine[1024];
        int index, res;
        int a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
        while (stream.getline(strLine, 1024))
        {
            res = sscanf(strLine, "%d	%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &index, 
                     &a1, &a2, &a3, &a4, &b1, &b2, &b3, &b4, &c1, &c2, &c3, &c4,&d1, &d2, &d3, &d4);
            if (res > 0)
            {
                _patch[index - 1].ptIndex[0][0] = a1; _patch[index - 1].ptIndex[0][1] = a2; _patch[index - 1].ptIndex[0][2] = a3; _patch[index - 1].ptIndex[0][3] = a4;
                _patch[index - 1].ptIndex[1][0] = b1; _patch[index - 1].ptIndex[1][1] = b2; _patch[index - 1].ptIndex[1][2] = b3; _patch[index - 1].ptIndex[1][3] = b4;
                _patch[index - 1].ptIndex[2][0] = c1; _patch[index - 1].ptIndex[2][1] = c2; _patch[index - 1].ptIndex[2][2] = c3; _patch[index - 1].ptIndex[2][3] = c4;
                _patch[index - 1].ptIndex[3][0] = d1; _patch[index - 1].ptIndex[3][1] = d2; _patch[index - 1].ptIndex[3][2] = d3; _patch[index - 1].ptIndex[3][3] = d4;
            }
        }
    }

    
    void DrawParts(HDC hdc,int nPatchStart,int nPatchEnd) // 绘制茶壶
    {
        Point3 P3[4][4]; // 曲面控制点
        int n=3;//递归深度

        for (int nPatch = nPatchStart; nPatch < nPatchEnd; nPatch++)
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    P3[i][j] = Vertex[_patch[nPatch].ptIndex[i][j] - 1]; // 数组从0开始 -1
                }
            }
            
            Patch.ReadControlPoint(P3);     // 读取控制点
            Patch.DrawCurvedPatch(hdc,n);   // 绘制曲面
            //Patch.DrawControlGrid(hdc);   // 绘制控制网格
        }
    }
    
};

完整代码

// 28-Utah茶壶算法
// 参考 https://www.bilibili.com/video/BV1v14y1W7sA
// 数据 https://github.com/dasch/graphics/blob/master/data/teapot.data

#define UNICODE
#include <Windows.h>
#include <Windowsx.h>
#include <string>
#include <sstream>
#include <istream>
#include <math.h>
#define WINDOW_TEXT L"28-Utah茶壶算法"
#define ROUND(d) int(floor(d)+0.5)  // 四舍五入
#define PI        3.1415926

struct Point2  // 二维点
{
    double x;
    double y;
    double w;  // 齐次坐标
    Point2() :x(0), y(0), w(1) {}
    Point2(double x, double y) :x(x), y(y), w(1) {}

    friend Point2 operator + (Point2 pt0, Point2 pt1)
    {
        return  Point2(pt0.x + pt1.x, pt0.y + pt1.y);
    }

    friend Point2 operator * (Point2 pt, double n)
    {
        return  Point2(pt.x * n, pt.y * n);
    }

    friend Point2 operator * (double n, Point2 pt)
    {
        return  Point2(pt.x * n, pt.y * n);
    }
};

struct Point3 :Point2
{
    double z;
    Point3() :z(0) {}
    Point3(double x, double y, double z) :Point2(x, y), z(z) {}
    friend Point3 operator + (Point3 pt0, Point3 pt1)
    {
        return  Point3(pt0.x + pt1.x, pt0.y + pt1.y, pt0.z + pt1.z);
    }

    friend Point3 operator * (double scalar, const Point3& pt)
    {
        return  Point3(pt.x * scalar, pt.y * scalar, pt.z * scalar);
    }

    friend Point3 operator * (const Point3& pt, double scalar)
    {
        return  Point3(pt.x * scalar, pt.y * scalar, pt.z * scalar);
    }

    double DotProduct(const Point3& p0, const Point3& p1)   // 向量的点积
    {
        return(p0.x * p1.x + p0.y * p1.y + p0.z * p1.z);
    }

    Point3 CrossProduct(const Point3& v0, const Point3& v1) // 向量的叉积
    {
        return Point3(v0.y * v1.z - v0.z * v1.y,
            v0.z * v1.x - v0.x * v1.z,
            v0.x * v1.y - v0.y * v1.x);
    }
};

class Transform3
{
public:
    Point3* _P;          // 顶点数组
    int     _ptNumber;   // 顶点数量
    double  _M[4][4];    // 变换矩阵
public:
    Transform3() :_P(NULL), _ptNumber(0)
    {
        memset(_M, 0, sizeof(_M));
    };
    ~Transform3() {};

    void MultiplyMatrix()  //矩阵相乘
    {
        Point3* PTemp = new Point3[_ptNumber];
        for (int i = 0; i < _ptNumber; i++)
        {
            PTemp[i] = _P[i];
        }
        for (int i = 0; i < _ptNumber; i++)
        {
            _P[i].x = _M[0][0] * PTemp[i].x + _M[0][1] * PTemp[i].y + _M[0][2] * PTemp[i].z + _M[3][0]; // * PTemp[i].w
            _P[i].y = _M[1][0] * PTemp[i].x + _M[1][1] * PTemp[i].y + _M[1][2] * PTemp[i].z + _M[3][1]; // * PTemp[i].w
            _P[i].z = _M[2][0] * PTemp[i].x + _M[2][1] * PTemp[i].y + _M[2][2] * PTemp[i].z + _M[3][2]; // * PTemp[i].w
            _P[i].w = _M[3][0] * PTemp[i].x + _M[3][1] * PTemp[i].y + _M[3][2] * PTemp[i].z + _M[3][3]; // * PTemp[i].w
        }

        delete[]PTemp;
    }

    void SetMatrix(Point3* P, int ptNumber) //顶点数组初始化
    {
        _P = P;
        _ptNumber = ptNumber;
    }
    void Identity()
    {
        _M[0][0] = 1.0, _M[0][1] = 0.0, _M[0][2] = 0.0, _M[0][3] = 0.0;
        _M[1][0] = 0.0, _M[1][1] = 1.0, _M[1][2] = 0.0, _M[1][3] = 0.0;
        _M[2][0] = 0.0, _M[2][1] = 0.0, _M[2][2] = 1.0, _M[2][3] = 0.0;
        _M[3][0] = 0.0, _M[3][1] = 0.0, _M[3][2] = 0.0, _M[3][3] = 1.0;
    }

    void Translate(double tx, double ty, double tz)//平移变换
    {
        Identity();
        _M[3][0] = tx;
        _M[3][1] = ty;
        _M[3][2] = tz;
        MultiplyMatrix();
    }

    void Scale(double sx, double sy, double sz)//缩放变换
    {
        Identity();
        _M[0][0] = sx;
        _M[1][1] = sy;
        _M[2][2] = sz;
        MultiplyMatrix();
    }

    void RotateX(double beta)//绕X轴旋转变换
    {
        Identity();
        beta = beta * PI / 180;
        _M[1][1] = cos(beta), _M[1][2] = -sin(beta);
        _M[2][1] = sin(beta), _M[2][2] = cos(beta);
        MultiplyMatrix();
    }

    void  RotateY(double beta)//绕Y轴旋转变换
    {
        Identity();
        beta = beta * PI / 180;
        _M[0][0] = cos(beta), _M[0][2] = sin(beta);
        _M[2][0] = -sin(beta), _M[2][2] = cos(beta);
        MultiplyMatrix();
    }

};

struct  T2
{
    double u;
    double v;
    T2() :u(0), v(0) {}
    T2(double u, double v) :u(u), v(v) {}

    friend T2 operator+(const T2& t0, const T2& t1)
    {
        return T2(t0.u + t1.u, t0.v + t1.v);
    }

    friend T2 operator/(const T2& t, double n)
    {
        return T2(t.u / n, t.v / n);
    }

};

class Projection  // 透视投影
{
public:
    Point3 Eye;   // 视点
    double R;     // 视点球坐标
    double Phi;   // 
    double Theta; // 
    double D;     // 
    double K[8];  // 透视常数
public:
    Projection()
    {
        R = 1000;
        D = 800;
        Phi = 90;
        Theta = 0;      // 世界坐标z轴正上方 看向原点
        InitialParameter();
    }
    ~Projection() {}

    void InitialParameter() // 初始化参数
    {
        K[0] = sin(PI * Theta / 180);
        K[1] = sin(PI * Phi / 180);
        K[2] = cos(PI * Theta / 180);
        K[3] = cos(PI * Phi / 180);
        K[4] = K[1] * K[2];
        K[5] = K[0] * K[1];
        K[6] = K[2] * K[3];
        K[7] = K[0] * K[3];
        Eye = Point3(R * K[5], R * K[5], R * K[4]);  // 设置视点
    }

    void SetEye(double r, double phi, double theta)   // 设置视点
    {
        R = r;
        Phi = phi;
        Theta = theta;
        InitialParameter();
    }

    Point3 GetEye()
    {
        return Eye;
    }

    Point2 OrthographicProjection(Point3 worldPoint) // 正交投影
    {
        return Point2(worldPoint.x, worldPoint.y);
    }

    Point2 CavalierProjection(Point3 worldPoint)     // 斜等侧投影
    {
        Point2 screenPoint; // 屏幕坐标
        double cota = 1;
        double beta = PI / 4;
        screenPoint.x = worldPoint.x - worldPoint.z * cota * cos(beta);
        screenPoint.y = worldPoint.y - worldPoint.z * cota * cos(beta);
        return screenPoint;
    }

    Point2 CabinetProjection(Point3 worldPoint)      // 斜二侧投影
    {
        Point2 screenPoint; // 屏幕坐标
        double cota = 0.5;
        double beta = PI / 4;
        screenPoint.x = worldPoint.x - worldPoint.z * cota * cos(beta);
        screenPoint.y = worldPoint.y - worldPoint.z * cota * cos(beta);
        return screenPoint;
    }

    Point2 PerspectiveProjection2(Point3 worldPoint) // 二维透视投影
    {
        Point3 viewPoint;  // 观察坐标系
        viewPoint.x = K[2] * worldPoint.x - K[0] * worldPoint.z;
        viewPoint.y = -K[7] * worldPoint.x + K[1] * worldPoint.y - K[6] * worldPoint.z;
        viewPoint.z = -K[5] * worldPoint.x - K[3] * worldPoint.y - K[4] * worldPoint.z + R;

        Point2 screenPoint; // 屏幕坐标
        screenPoint.x = D * viewPoint.x / viewPoint.z;
        screenPoint.y = D * viewPoint.y / viewPoint.z;

        return screenPoint;
    }

};


class  BicubicBezierPatch  // 双三次Bezier曲面
{
public:
    Point3     P[4][4];     // 控制点
    Point3     GridP[4];    // 网格坐标
    Projection Proj;        // 投影

public:
    BicubicBezierPatch() {};
    ~BicubicBezierPatch() {};

    void ReadControlPoint(Point3 p[4][4])      // 读入控制点
    {
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                P[i][j] = p[i][j];
            }
        }


    }

    void DrawCurvedPatch(HDC hdc, int nRecursion) // 绘制递归曲面 nRecursion递归深度
    {
        T2 T[4];
        T[0] = T2(0, 0); T[1] = T2(1, 0);
        T[2] = T2(1, 1); T[3] = T2(0, 1);
        Tessellate(hdc, nRecursion, T);  // 递归函数
    }

    void Draw(HDC hdc) // 绘制四边形
    {

        Point2 point[4];
        for (int i = 0; i < 4; i++)
        {
            point[i] = Proj.PerspectiveProjection2(GridP[i]); // 正投影
        }
        MoveToEx(hdc, ROUND(point[0].x), ROUND(point[0].y), NULL);
        LineTo(hdc, ROUND(point[1].x), ROUND(point[1].y));
        LineTo(hdc, ROUND(point[2].x), ROUND(point[2].y));
        LineTo(hdc, ROUND(point[3].x), ROUND(point[3].y));
        LineTo(hdc, ROUND(point[0].x), ROUND(point[0].y));

    }

    void DrawControlGrid(HDC hdc) // 绘制控制网格
    {

        HPEN redPen = CreatePen(PS_SOLID, 4, RGB(180, 0, 0));
        HPEN bluePen = CreatePen(PS_SOLID, 2, RGB(0, 0, 180));
        HGDIOBJ oldObj = SelectObject(hdc, bluePen);

        Point2 P2[4][4];
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                P2[i][j] = Proj.PerspectiveProjection2(P[i][j]);  // 正投影
            }
        }

        for (int i = 0; i < 4; i++)
        {
            MoveToEx(hdc, ROUND(P2[i][0].x), ROUND(P2[i][0].y), NULL);
            for (int j = 0; j < 4; j++)
            {
                LineTo(hdc, ROUND(P2[i][j].x), ROUND(P2[i][j].y));
            }
        }

        for (int j = 0; j < 4; j++)
        {
            MoveToEx(hdc, ROUND(P2[0][j].x), ROUND(P2[0][j].y), NULL);
            for (int i = 0; i < 4; i++)
            {
                LineTo(hdc, ROUND(P2[i][j].x), ROUND(P2[i][j].y));
            }
        }

        SelectObject(hdc, redPen);
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                Ellipse(hdc, P2[i][j].x + 3, P2[i][j].y + 3, P2[i][j].x - 3, P2[i][j].y - 3);
            }
        }
        SelectObject(hdc, oldObj);
        DeletePen(redPen);
        DeletePen(bluePen);
    }

private:

    void Tessellate(HDC hdc, int nRecursion, T2* t) // 细分曲面
    {
        if (0 == nRecursion)
        {
            MeshGrid(hdc, t);
            Draw(hdc);
            return;
        }
        else
        {
            T2 midP = (t[0] + t[1] + t[2] + t[3]) / 4.0;
            T2 subT[4][4]; // 将定义域一分为四 (四叉树)

            // 左下子曲面
            subT[0][0] = t[0];
            subT[0][1] = T2(midP.u, t[0].v);
            subT[0][2] = midP;
            subT[0][3] = T2(t[0].u, midP.v);
            Tessellate(hdc, nRecursion - 1, subT[0]);

            // 右下子曲面
            subT[1][0] = T2(midP.u, t[1].v);
            subT[1][1] = t[1];
            subT[1][2] = T2(t[1].u, midP.v);
            subT[1][3] = midP;
            Tessellate(hdc, nRecursion - 1, subT[1]);

            // 右下子曲面
            subT[2][0] = midP;
            subT[2][1] = T2(t[2].u, midP.v);
            subT[2][2] = t[2];
            subT[2][3] = T2(midP.u, t[2].v);
            Tessellate(hdc, nRecursion - 1, subT[2]);

            // 左上子曲面
            subT[3][0] = T2(t[3].u, midP.v);
            subT[3][1] = midP;
            subT[3][2] = T2(midP.u, t[3].v);
            subT[3][3] = t[3];
            Tessellate(hdc, nRecursion - 1, subT[3]);


        }
    }

    void MeshGrid(HDC hdc, T2 t[4]) // 计算四边形网格
    {
        double M[4][4];   // 系数矩阵
        M[0][0] = -1.0;  M[0][1] = 3.0;  M[0][2] = -3.0;  M[0][3] = 1.0;
        M[1][0] = 3.0;   M[1][1] = -6.0; M[1][2] = 3.0;   M[1][3] = 0.0;
        M[2][0] = -3.0;  M[2][1] = 3.0;  M[2][2] = 0.0;   M[2][3] = 0.0;
        M[3][0] = 1.0;   M[3][1] = 0.0;  M[3][2] = 0.0;  M[3][3] = 0.0;

        Point3 pTemp[4][4]; // 每次递归 控制点矩阵不变

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                pTemp[i][j] = P[i][j];
            }
        }

        LeftMultiplyMatrix(M, pTemp);          // 控制顶点矩阵左乘系数矩阵
        TransposeMatrix(M);                   // 系数转置矩阵
        RightMultiplyMatrix(pTemp, M);         // 控制顶点矩阵右乘系数矩阵
        double u0, u1, u2, u3, v0, v1, v2, v3;// u,v 参数的幂
        for (int i = 0; i < 4; i++)
        {
            u3 = pow(t[i].u, 3.0); u2 = pow(t[i].u, 2.0); u1 = t[i].u; u0 = 1.0;
            v3 = pow(t[i].v, 3.0); v2 = pow(t[i].v, 2.0); v1 = t[i].v; v0 = 1.0;

            GridP[i] = (u3 * pTemp[0][0] + u2 * pTemp[1][0] + u1 * pTemp[2][0] + u0 * pTemp[3][0]) * v3
                + (u3 * pTemp[0][1] + u2 * pTemp[1][1] + u1 * pTemp[2][1] + u0 * pTemp[3][1]) * v2
                + (u3 * pTemp[0][2] + u2 * pTemp[1][2] + u1 * pTemp[2][2] + u0 * pTemp[3][2]) * v1
                + (u3 * pTemp[0][3] + u2 * pTemp[1][3] + u1 * pTemp[2][3] + u0 * pTemp[3][3]) * v0;
        }
    }

    void LeftMultiplyMatrix(double m[4][4], Point3 p[4][4]) // 控制顶点矩阵左乘系数矩阵
    {
        Point3 pTemp[4][4];//临时矩阵
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                pTemp[i][j] = m[i][0] * p[0][j] + m[i][1] * p[1][j] + m[i][2] * p[2][j] + m[i][3] * p[3][j];
            }

        }

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                p[i][j] = pTemp[i][j];
            }
        }

    }

    void TransposeMatrix(double M[4][4])  // 转置矩阵
    {
        double pTemp[4][4];  // 临时矩阵
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                pTemp[j][i] = M[i][j];
            }
        }

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                M[i][j] = pTemp[i][j];
            }
        }
    }

    void RightMultiplyMatrix(Point3 p[4][4], double m[4][4]) // 控制顶点矩阵右乘系数矩阵
    {
        Point3 pTemp[4][4]; // 临时矩阵
        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                pTemp[i][j] = p[i][0] * m[0][j] + p[i][1] * m[1][j] + p[i][2] * m[2][j] + p[i][3] * m[3][j];

            }

        }

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 4; j++)
            {
                p[i][j] = pTemp[i][j];
            }
        }

    }

};

class  Patch
{
public:
    int ptIndex[4][4]; // 16个控制点索引号   
};


class UTeapot   // 茶壶类
{
public:
    Point3 Vertex[306];
    Patch  _patch[32];
    BicubicBezierPatch Patch; // Bezier曲面
public:
    UTeapot() {};
    ~UTeapot() {};
    void ReadVertext()
    {
        // 茶壶顶点
        std::string strVertex = R"(  1   1.40000   0.00000   2.40000
              2   1.40000  -0.78400   2.40000 
              3   0.78000  -1.40000   2.40000
              4   0.00000  -1.40000   2.40000
              5   1.33750   0.00000   2.53125
              6   1.33750  -0.74900   2.53125
              7   0.74900  -1.33750   2.53125
              8   0.00000  -1.33750   2.53125
              9   1.43750   0.00000   2.53125
             10   1.43750  -0.80500   2.53125
             11   0.80500  -1.43750   2.53125
             12   0.00000  -1.43750   2.53125
             13   1.50000   0.00000   2.40000
             14   1.50000  -0.84000   2.40000
             15   0.84000  -1.50000   2.40000
             16   0.00000  -1.50000   2.40000
             17  -0.78400  -1.40000   2.40000
             18  -1.40000  -0.78400   2.40000
             19  -1.40000   0.00000   2.40000
             20  -0.74900  -1.33750   2.53125
             21  -1.33750  -0.74900   2.53125
             22  -1.33750   0.00000   2.53125
             23  -0.80500  -1.43750   2.53125
             24  -1.43750  -0.80500   2.53125
             25  -1.43750   0.00000   2.53125
             26  -0.84000  -1.50000   2.40000
             27  -1.50000  -0.84000   2.40000
             28  -1.50000   0.00000   2.40000
             29  -1.40000   0.78400   2.40000
             30  -0.78400   1.40000   2.40000
             31   0.00000   1.40000   2.40000
             32  -1.33750   0.74900   2.53125
             33  -0.74900   1.33750   2.53125
             34   0.00000   1.33750   2.53125
             35  -1.43750   0.80500   2.53125
             36  -0.80500   1.43750   2.53125
             37   0.00000   1.43750   2.53125
             38  -1.50000   0.84000   2.40000
             39  -0.84000   1.50000   2.40000
             40   0.00000   1.50000   2.40000
             41   0.78400   1.40000   2.40000
             42   1.40000   0.78400   2.40000
             43   0.74900   1.33750   2.53125
             44   1.33750   0.74900   2.53125
             45   0.80500   1.43750   2.53125
             46   1.43750   0.80500   2.53125
             47   0.84000   1.50000   2.40000
             48   1.50000   0.84000   2.40000
             49   1.75000   0.00000   1.87500
             50   1.75000  -0.98000   1.87500
             51   0.98000  -1.75000   1.87500
             52   0.00000  -1.75000   1.87500
             53   2.00000   0.00000   1.35000
             54   2.00000  -1.12000   1.35000
             55   1.12000  -2.00000   1.35000
             56   0.00000  -2.00000   1.35000
             57   2.00000   0.00000   0.90000
             58   2.00000  -1.12000   0.90000
             59   1.12000  -2.00000   0.90000
             60   0.00000  -2.00000   0.90000
             61  -0.98000  -1.75000   1.87500
             62  -1.75000  -0.98000   1.87500
             63  -1.75000   0.00000   1.87500
             64  -1.12000  -2.00000   1.35000
             65  -2.00000  -1.12000   1.35000
             66  -2.00000   0.00000   1.35000
             67  -1.12000  -2.00000   0.90000
             68  -2.00000  -1.12000   0.90000
             69  -2.00000   0.00000   0.90000
             70  -1.75000   0.98000   1.87500
             71  -0.98000   1.75000   1.87500
             72   0.00000   1.75000   1.87500
             73  -2.00000   1.12000   1.35000
             74  -1.12000   2.00000   1.35000
             75   0.00000   2.00000   1.35000
             76  -2.00000   1.12000   0.90000
             77  -1.12000   2.00000   0.90000
             78   0.00000   2.00000   0.90000
             79   0.98000   1.75000   1.87500
             80   1.75000   0.98000   1.87500
             81   1.12000   2.00000   1.35000
             82   2.00000   1.12000   1.35000
             83   1.12000   2.00000   0.90000
             84   2.00000   1.12000   0.90000
             85   2.00000   0.00000   0.45000
             86   2.00000  -1.12000   0.45000
             87   1.12000  -2.00000   0.45000
             88   0.00000  -2.00000   0.45000
             89   1.50000   0.00000   0.22500
             90   1.50000  -0.84000   0.22500
             91   0.84000  -1.50000   0.22500
             92   0.00000  -1.50000   0.22500
             93   1.50000   0.00000   0.15000
             94   1.50000  -0.84000   0.15000
             95   0.84000  -1.50000   0.15000
             96   0.00000  -1.50000   0.15000
             97  -1.12000  -2.00000   0.45000
             98  -2.00000  -1.12000   0.45000
             99  -2.00000   0.00000   0.45000
            100  -0.84000  -1.50000   0.22500
            101  -1.50000  -0.84000   0.22500
            102  -1.50000   0.00000   0.22500
            103  -0.84000  -1.50000   0.15000
            104  -1.50000  -0.84000   0.15000
            105  -1.50000   0.00000   0.15000
            106  -2.00000   1.12000   0.45000
            107  -1.12000   2.00000   0.45000
            108   0.00000   2.00000   0.45000
            109  -1.50000   0.84000   0.22500
            110  -0.84000   1.50000   0.22500
            111   0.00000   1.50000   0.22500
            112  -1.50000   0.84000   0.15000
            113  -0.84000   1.50000   0.15000
            114   0.00000   1.50000   0.15000
            115   1.12000   2.00000   0.45000
            116   2.00000   1.12000   0.45000
            117   0.84000   1.50000   0.22500
            118   1.50000   0.84000   0.22500
            119   0.84000   1.50000   0.15000
            120   1.50000   0.84000   0.15000
            121  -1.60000   0.00000   2.02500
            122  -1.60000  -0.30000   2.02500
            123  -1.50000  -0.30000   2.25000
            124  -1.50000   0.00000   2.25000
            125  -2.30000   0.00000   2.02500
            126  -2.30000  -0.30000   2.02500
            127  -2.50000  -0.30000   2.25000
            128  -2.50000   0.00000   2.25000
            129  -2.70000   0.00000   2.02500
            130  -2.70000  -0.30000   2.02500
            131  -3.00000  -0.30000   2.25000
            132  -3.00000   0.00000   2.25000
            133  -2.70000   0.00000   1.80000
            134  -2.70000  -0.30000   1.80000
            135  -3.00000  -0.30000   1.80000
            136  -3.00000   0.00000   1.80000
            137  -1.50000   0.30000   2.25000
            138  -1.60000   0.30000   2.02500
            139  -2.50000   0.30000   2.25000
            140  -2.30000   0.30000   2.02500
            141  -3.00000   0.30000   2.25000
            142  -2.70000   0.30000   2.02500
            143  -3.00000   0.30000   1.80000
            144  -2.70000   0.30000   1.80000
            145  -2.70000   0.00000   1.57500
            146  -2.70000  -0.30000   1.57500
            147  -3.00000  -0.30000   1.35000
            148  -3.00000   0.00000   1.35000
            149  -2.50000   0.00000   1.12500
            150  -2.50000  -0.30000   1.12500
            151  -2.65000  -0.30000   0.93750
            152  -2.65000   0.00000   0.93750
            153  -2.00000  -0.30000   0.90000
            154  -1.90000  -0.30000   0.60000
            155  -1.90000   0.00000   0.60000
            156  -3.00000   0.30000   1.35000
            157  -2.70000   0.30000   1.57500
            158  -2.65000   0.30000   0.93750
            159  -2.50000   0.30000   1.12500
            160  -1.90000   0.30000   0.60000
            161  -2.00000   0.30000   0.90000
            162   1.70000   0.00000   1.42500
            163   1.70000  -0.66000   1.42500
            164   1.70000  -0.66000   0.60000
            165   1.70000   0.00000   0.60000
            166   2.60000   0.00000   1.42500
            167   2.60000  -0.66000   1.42500
            168   3.10000  -0.66000   0.82500
            169   3.10000   0.00000   0.82500
            170   2.30000   0.00000   2.10000
            171   2.30000  -0.25000   2.10000
            172   2.40000  -0.25000   2.02500
            173   2.40000   0.00000   2.02500
            174   2.70000   0.00000   2.40000
            175   2.70000  -0.25000   2.40000
            176   3.30000  -0.25000   2.40000
            177   3.30000   0.00000   2.40000
            178   1.70000   0.66000   0.60000
            179   1.70000   0.66000   1.42500
            180   3.10000   0.66000   0.82500
            181   2.60000   0.66000   1.42500
            182   2.40000   0.25000   2.02500
            183   2.30000   0.25000   2.10000
            184   3.30000   0.25000   2.40000
            185   2.70000   0.25000   2.40000
            186   2.80000   0.00000   2.47500
            187   2.80000  -0.25000   2.47500
            188   3.52500  -0.25000   2.49375
            189   3.52500   0.00000   2.49375
            190   2.90000   0.00000   2.47500
            191   2.90000  -0.15000   2.47500
            192   3.45000  -0.15000   2.51250
            193   3.45000   0.00000   2.51250
            194   2.80000   0.00000   2.40000
            195   2.80000  -0.15000   2.40000
            196   3.20000  -0.15000   2.40000
            197   3.20000   0.00000   2.40000
            198   3.52500   0.25000   2.49375
            199   2.80000   0.25000   2.47500
            200   3.45000   0.15000   2.51250
            201   2.90000   0.15000   2.47500
            202   3.20000   0.15000   2.40000
            203   2.80000   0.15000   2.40000
            204   0.00000   0.00000   3.15000
            205   0.00000  -0.00200   3.15000
            206   0.00200   0.00000   3.15000
            207   0.80000   0.00000   3.15000
            208   0.80000  -0.45000   3.15000
            209   0.45000  -0.80000   3.15000
            210   0.00000  -0.80000   3.15000
            211   0.00000   0.00000   2.85000
            212   0.20000   0.00000   2.70000
            213   0.20000  -0.11200   2.70000
            214   0.11200  -0.20000   2.70000
            215   0.00000  -0.20000   2.70000
            216  -0.00200   0.00000   3.15000
            217  -0.45000  -0.80000   3.15000
            218  -0.80000  -0.45000   3.15000
            219  -0.80000   0.00000   3.15000
            220  -0.11200  -0.20000   2.70000
            221  -0.20000  -0.11200   2.70000
            222  -0.20000   0.00000   2.70000
            223   0.00000   0.00200   3.15000
            224  -0.80000   0.45000   3.15000
            225  -0.45000   0.80000   3.15000
            226   0.00000   0.80000   3.15000
            227  -0.20000   0.11200   2.70000
            228  -0.11200   0.20000   2.70000
            229   0.00000   0.20000   2.70000
            230   0.45000   0.80000   3.15000
            231   0.80000   0.45000   3.15000
            232   0.11200   0.20000   2.70000
            233   0.20000   0.11200   2.70000
            234   0.40000   0.00000   2.55000
            235   0.40000  -0.22400   2.55000
            236   0.22400  -0.40000   2.55000
            237   0.00000  -0.40000   2.55000
            238   1.30000   0.00000   2.55000
            239   1.30000  -0.72800   2.55000
            240   0.72800  -1.30000   2.55000
            241   0.00000  -1.30000   2.55000
            242   1.30000   0.00000   2.40000
            243   1.30000  -0.72800   2.40000
            244   0.72800  -1.30000   2.40000
            245   0.00000  -1.30000   2.40000
            246  -0.22400  -0.40000   2.55000
            247  -0.40000  -0.22400   2.55000
            248  -0.40000   0.00000   2.55000
            249  -0.72800  -1.30000   2.55000
            250  -1.30000  -0.72800   2.55000
            251  -1.30000   0.00000   2.55000
            252  -0.72800  -1.30000   2.40000
            253  -1.30000  -0.72800   2.40000
            254  -1.30000   0.00000   2.40000
            255  -0.40000   0.22400   2.55000
            256  -0.22400   0.40000   2.55000
            257   0.00000   0.40000   2.55000
            258  -1.30000   0.72800   2.55000
            259  -0.72800   1.30000   2.55000
            260   0.00000   1.30000   2.55000
            261  -1.30000   0.72800   2.40000
            262  -0.72800   1.30000   2.40000
            263   0.00000   1.30000   2.40000
            264   0.22400   0.40000   2.55000
            265   0.40000   0.22400   2.55000
            266   0.72800   1.30000   2.55000
            267   1.30000   0.72800   2.55000
            268   0.72800   1.30000   2.40000
            269   1.30000   0.72800   2.40000
            270   0.00000   0.00000   0.00000
            271   1.50000   0.00000   0.15000
            272   1.50000   0.84000   0.15000
            273   0.84000   1.50000   0.15000
            274   0.00000   1.50000   0.15000
            275   1.50000   0.00000   0.07500
            276   1.50000   0.84000   0.07500
            277   0.84000   1.50000   0.07500
            278   0.00000   1.50000   0.07500
            279   1.42500   0.00000   0.00000
            280   1.42500   0.79800   0.00000
            281   0.79800   1.42500   0.00000
            282   0.00000   1.42500   0.00000
            283  -0.84000   1.50000   0.15000
            284  -1.50000   0.84000   0.15000
            285  -1.50000   0.00000   0.15000
            286  -0.84000   1.50000   0.07500
            287  -1.50000   0.84000   0.07500
            288  -1.50000   0.00000   0.07500
            289  -0.79800   1.42500   0.00000
            290  -1.42500   0.79800   0.00000
            291  -1.42500   0.00000   0.00000
            292  -1.50000  -0.84000   0.15000
            293  -0.84000  -1.50000   0.15000
            294   0.00000  -1.50000   0.15000
            295  -1.50000  -0.84000   0.07500
            296  -0.84000  -1.50000   0.07500
            297   0.00000  -1.50000   0.07500
            298  -1.42500  -0.79800   0.00000
            299  -0.79800  -1.42500   0.00000
            300   0.00000  -1.42500   0.00000
            301   0.84000  -1.50000   0.15000
            302   1.50000  -0.84000   0.15000
            303   0.84000  -1.50000   0.07500
            304   1.50000  -0.84000   0.07500
            305   0.79800  -1.42500   0.00000
            306   1.42500  -0.79800   0.00000)";


            std::stringstream  stream(strVertex);           
            char strLine[1024];
            int index,res;
            double x, y, z;
            while (stream.getline(strLine, 1024))
            {
                res=sscanf(strLine, "%d  %lf %lf %lf", &index, &x, &y, &z);
                if (res > 0)
                {
                    Vertex[index-1] = Point3(x,y,z);
                }
            }
           

    }
    void ReadPath()
    {
        // 茶壶顶点索引
        std::string indices = R"(  1	  1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16
                                   2	  4  17  18  19   8  20  21  22  12  23  24  25  16  26  27  28
                                   3	 19  29  30  31  22  32  33  34  25  35  36  37  28  38  39  40
                                   4	 31  41  42   1  34  43  44   5  37  45  46   9  40  47  48  13
                                   5	 13  14  15  16  49  50  51  52  53  54  55  56  57  58  59  60
                                   6	 16  26  27  28  52  61  62  63  56  64  65  66  60  67  68  69
                                   7	 28  38  39  40  63  70  71  72  66  73  74  75  69  76  77  78
                                   8	 40  47  48  13  72  79  80  49  75  81  82  53  78  83  84  57
                                   9	 57  58  59  60  85  86  87  88  89  90  91  92  93  94  95  96
                                  10	 60  67  68  69  88  97  98  99  92 100 101 102  96 103 104 105
                                  11	 69  76  77  78  99 106 107 108 102 109 110 111 105 112 113 114
                                  12	 78  83  84  57 108 115 116  85 111 117 118  89 114 119 120  93
                                  13	121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
                                  14	124 137 138 121 128 139 140 125 132 141 142 129 136 143 144 133
                                  15	133 134 135 136 145 146 147 148 149 150 151 152  69 153 154 155
                                  16	136 143 144 133 148 156 157 145 152 158 159 149 155 160 161  69
                                  17	162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
                                  18	165 178 179 162 169 180 181 166 173 182 183 170 177 184 185 174
                                  19	174 175 176 177 186 187 188 189 190 191 192 193 194 195 196 197
                                  20	177 184 185 174 189 198 199 186 193 200 201 190 197 202 203 194
                                  21	204 204 204 204 207 208 209 210 211 211 211 211 212 213 214 215
                                  22	204 204 204 204 210 217 218 219 211 211 211 211 215 220 221 222
                                  23	204 204 204 204 219 224 225 226 211 211 211 211 222 227 228 229
                                  24	204 204 204 204 226 230 231 207 211 211 211 211 229 232 233 212
                                  25	212 213 214 215 234 235 236 237 238 239 240 241 242 243 244 245
                                  26	215 220 221 222 237 246 247 248 241 249 250 251 245 252 253 254
                                  27	222 227 228 229 248 255 256 257 251 258 259 260 254 261 262 263
                                  28	229 232 233 212 257 264 265 234 260 266 267 238 263 268 269 242
                                  29	270 270 270 270 279 280 281 282 275 276 277 278  93 120 119 114
                                  30	270 270 270 270 282 289 290 291 278 286 287 288 114 113 112 105
                                  31	270 270 270 270 291 298 299 300 288 295 296 297 105 104 103  96
                                  32	270 270 270 270 300 305 306 279 297 303 304 275  96  95  94  93)";


        std::stringstream  stream(indices);
        char strLine[1024];
        int index, res;
        int a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
        while (stream.getline(strLine, 1024))
        {
            res = sscanf(strLine, "%d	%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", &index, 
                     &a1, &a2, &a3, &a4, &b1, &b2, &b3, &b4, &c1, &c2, &c3, &c4,&d1, &d2, &d3, &d4);
            if (res > 0)
            {
                _patch[index - 1].ptIndex[0][0] = a1; _patch[index - 1].ptIndex[0][1] = a2; _patch[index - 1].ptIndex[0][2] = a3; _patch[index - 1].ptIndex[0][3] = a4;
                _patch[index - 1].ptIndex[1][0] = b1; _patch[index - 1].ptIndex[1][1] = b2; _patch[index - 1].ptIndex[1][2] = b3; _patch[index - 1].ptIndex[1][3] = b4;
                _patch[index - 1].ptIndex[2][0] = c1; _patch[index - 1].ptIndex[2][1] = c2; _patch[index - 1].ptIndex[2][2] = c3; _patch[index - 1].ptIndex[2][3] = c4;
                _patch[index - 1].ptIndex[3][0] = d1; _patch[index - 1].ptIndex[3][1] = d2; _patch[index - 1].ptIndex[3][2] = d3; _patch[index - 1].ptIndex[3][3] = d4;
            }
        }
    }

    
    void DrawParts(HDC hdc,int nPatchStart,int nPatchEnd) // 绘制茶壶
    {
        Point3 P3[4][4]; // 曲面控制点
        int n=3;//递归深度

        for (int nPatch = nPatchStart; nPatch < nPatchEnd; nPatch++)
        {
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    P3[i][j] = Vertex[_patch[nPatch].ptIndex[i][j] - 1]; // 数组从0开始 -1
                }
            }
            
            Patch.ReadControlPoint(P3);     // 读取控制点
            Patch.DrawCurvedPatch(hdc,n);   // 绘制曲面
            //Patch.DrawControlGrid(hdc);   // 绘制控制网格
        }
    }
    
};

static bool     m_Play = false;
static wchar_t* m_str = L"左键旋转";

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT rect;
    static double alpha;
    static double beta;

    switch (uMsg)
    {
    case WM_TIMER:
        alpha += 1;
        beta += 1;
        InvalidateRect(hwnd, NULL, FALSE);
        return 0;

    case WM_LBUTTONDOWN:
        m_Play = !m_Play;
        if (m_Play)
        {
            SetTimer(hwnd, 0, 0, NULL);
        }
        else
        {
            KillTimer(hwnd, 0);
        }
        return 0;

    case WM_PAINT:
    {
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);

        SetMapMode(hdc, MM_ANISOTROPIC);
        SetWindowExtEx(hdc, rect.right, rect.bottom, NULL);
        SetViewportExtEx(hdc, rect.right, -rect.bottom, NULL);
        SetViewportOrgEx(hdc, rect.right / 2, rect.bottom / 2, NULL);

        // 内存DC
        HDC     memDC = CreateCompatibleDC(hdc);                                   // 创建兼容DC 画板
        HBITMAP newBitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);  // 创建画布
        HGDIOBJ oldBitmap = SelectObject(memDC, newBitmap);                        // 将画布选入画板
        FillRect(memDC, &rect, (HBRUSH)(COLOR_WINDOW + 1));
        DrawText(memDC, m_str, wcslen(m_str), &rect, NULL);

        SetMapMode(memDC, MM_ANISOTROPIC);
        SetWindowExtEx(memDC, rect.right, rect.bottom, NULL);
        SetViewportExtEx(memDC, rect.right, -rect.bottom, NULL);
        SetViewportOrgEx(memDC, rect.right / 2, rect.bottom / 2, NULL);

        // 绘制图形
       
          Transform3 transform;          
          UTeapot uteapot;
          uteapot.ReadVertext();
          uteapot.ReadPath();


          // 放大茶壶
          transform.SetMatrix(uteapot.Vertex,306);
          int scale = 150;
          transform.Scale(scale, scale, scale); 
          
          if (m_Play)
          {
              transform.RotateX(alpha);
              transform.RotateY(beta);
          }

          // 绘制茶壶
           uteapot.DrawParts(memDC,0, 12); // 绘制 Body 
           uteapot.DrawParts(memDC,12,16); // 绘制 Handle 
           uteapot.DrawParts(memDC,16,20); // 绘制 Spout 
           uteapot.DrawParts(memDC,20,28); // 绘制 Lid  
           uteapot.DrawParts(memDC,28,32); // 绘制 Bottom  

       

        // 内存dc复制到设备
        BitBlt(hdc, ROUND(-rect.right / 2), ROUND(-rect.bottom / 2), rect.right, rect.bottom, memDC, ROUND(-rect.right / 2), ROUND(-rect.bottom / 2), SRCCOPY);

        SelectObject(memDC, oldBitmap);

        DeleteObject(newBitmap);
        DeleteDC(memDC);

        EndPaint(hwnd, &ps);
    }
    return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    // Register the window class.
    const wchar_t CLASS_NAME[] = L"CAG";
    WNDCLASS wc = { };

    wc.style = CS_HREDRAW | CS_VREDRAW; // 重新绘制整个工作区
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        WINDOW_TEXT,                    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
    );

    if (hwnd == NULL)
    {
        return 0;
    }
    ShowWindow(hwnd, nCmdShow);
    MSG msg = { };
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}


  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值