2025年28-Utah茶壶算法

28-Utah茶壶算法参考 https www bilibili com video BV1v14y1W7sA 数据 https github com dasch graphics blob master data teapot data 茶壶类 class UTeapot 茶壶类 public Point3 Vertex 306

大家好,我是讯享网,很高兴认识大家。


讯享网

参考: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. 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; } 

小讯
上一篇 2025-01-17 13:28
下一篇 2025-02-05 17:48

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/24101.html