3D 圆柱
[編輯] [转简体] (简体译文)
|
作者:huidong
| 分類:【編程】EasyX
[
25 瀏覽
0 評論
7 贊
7 踩
]
概要
正文
#include <easyx.h> #include <math.h> #include <conio.h> #include <stdio.h> #include <algorithm> // π #define PI 3.1415926535 // 点信息结构体 struct dPOINT { double x; double y; }; // 3D 点和颜色信息 struct dCPOINT3D { double x, y, z; COLORREF c; bool operator< (dCPOINT3D p) { return z < p.z; } bool operator<= (dCPOINT3D p) { return z <= p.z; } bool operator> (dCPOINT3D p) { return z > p.z; } bool operator>= (dCPOINT3D p) { return z >= p.z; } }; // 3D 点信息结构体 struct dPOINT3D { dPOINT3D() { } dPOINT3D(dCPOINT3D p) : x(p.x), y(p.y), z(p.z) { } double x; double y; double z; }; void Equal(dCPOINT3D& pc, const dPOINT3D& p) { pc = { p.x, p.y, p.z, pc.c }; } // 物体 class Object { public: Object() { } Object(int num) { New(num); } void New(int num) { p = new dCPOINT3D[num]; capacity = num; } void Free() { delete[] p; p = NULL; capacity = 0; n = 0; } void Copy(Object obj) { New(obj.n); memcpy(p, obj.p, obj.n * sizeof(dCPOINT3D)); n = obj.n; } dCPOINT3D* p = NULL; int capacity = 0; int n = 0; }; dCPOINT3D rotate3D(dCPOINT3D p, double Z, double Y, double X) { return { p.x * (cos(Y) * cos(Z)) + p.y * (-(cos(X) * sin(Z)) + (sin(X) * sin(Y) * cos(Z))) + p.z * ((sin(X) * sin(Z)) + (cos(X) * sin(Y) * cos(Z))), p.x * (cos(Y) * sin(Z)) + p.y * ((cos(X) * cos(Z)) + (sin(X) * sin(Y) * sin(Z))) + p.z * ((-sin(X) * cos(Z)) + (cos(X) * sin(Y) * sin(Z))), p.x * (-sin(Y)) + p.y * (sin(X) * cos(Y)) + p.z * (cos(X) * cos(Y)), p.c }; } void AddPointFromImage(Object& obj, COLORREF c) { for (int i = 0; i < getwidth(); i++) { for (int j = 0; j < getheight(); j++) { if (getpixel(i, j) != BLACK) { obj.p[obj.n++] = { (double)i, (double)j, 0, c }; } } } } void RotateObj(Object obj, double x, double y, double z) { for (int i = 0; i < obj.n; i++) { obj.p[i] = rotate3D(obj.p[i], z, y, x); } } void Render(Object obj) { Object obj_sort; obj_sort.Copy(obj); std::sort(obj_sort.p, obj_sort.p + obj_sort.n); for (int i = obj_sort.n - 1; i >= 0; i--) { putpixel((int)obj_sort.p[i].x + 320, (int)obj_sort.p[i].y + 240, obj_sort.p[i].c); } obj_sort.Free(); } Object GetObj() { int w = 50, h = 50, depth = 70; IMAGE img(w, h); Object obj(w * h * depth); SetWorkingImage(&img); solidcircle(25, 25, 24); AddPointFromImage(obj, GREEN); int len = obj.n; Object obj2(w * h); cleardevice(); circle(25, 25, 24); AddPointFromImage(obj2, GREEN); int len2 = obj2.n; for (int k = 0; k < depth - 1; k++) { for (int m = 0; m < len2; m++) { obj.p[obj.n] = obj2.p[m]; obj.p[obj.n].c = RGB(123, 223, 213); obj.p[obj.n].z = k; obj.n++; } } for (int m = 0; m < len; m++) { obj.p[obj.n] = obj.p[m]; obj.p[obj.n].c = RED; obj.p[obj.n].z = depth - 1; obj.n++; } SetWorkingImage(); return obj; } class Drag { private: ExMessage old, msg; int dx, dy; bool lbtn = false, mbtn = false, rbtn = false; bool newmsg = false; bool UpdateDragInfo(bool& btn, int msgid_down, int msgid_up) { if (newmsg) { if (btn) { if (msg.message == msgid_up) { btn = false; } dx = msg.x - old.x; dy = msg.y - old.y; old = msg; return true; } else { if (msg.message == msgid_down) { btn = true; old = msg; } return false; } newmsg = false; } else { return false; } } public: void UpdateMessage(ExMessage m) { msg = m; newmsg = true; } bool isLeftDrag() { return UpdateDragInfo(lbtn, WM_LBUTTONDOWN, WM_LBUTTONUP); } bool isMiddleDrag() { return UpdateDragInfo(mbtn, WM_MBUTTONDOWN, WM_MBUTTONUP); } bool isRightDrag() { return UpdateDragInfo(rbtn, WM_RBUTTONDOWN, WM_RBUTTONUP); } int GetDragX() { return dx; }; int GetDragY() { return dy; }; }; int main() { // 图形界面初始化 initgraph(640, 480, EX_SHOWCONSOLE); BeginBatchDraw(); setbkcolor(BLUE); cleardevice(); Object obj = GetObj(); RotateObj(obj, 0, 0, 0); double x = 0, y = 0; Drag drag; for (double i = 0;; i += 0.05) { cleardevice(); Object obj2; obj2.Copy(obj); RotateObj(obj2, x, y, 0); Render(obj2); obj2.Free(); FlushBatchDraw(); if (i >= 2 * PI) { i = 0; } ExMessage msg; while (peekmessage(&msg, EX_MOUSE)) { drag.UpdateMessage(msg); if (drag.isLeftDrag()) { y += drag.GetDragX() / 10.0; x += drag.GetDragY() / 10.0; } } } // 关闭窗口 EndBatchDraw(); closegraph(); return 0; }