匯東網


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;
}


[ 7] [ 7]


 評論區  0 條評論

+ 添加評論