zoukankan      html  css  js  c++  java
  • 《计算机图形学》 第一章 基础知识--02向量(二维)

      前沿:在计算机图形学中,我们会用到大量的数学知识,所以今天我们来看看第一个数学知识点:二维向量

    一、二维向量知识点:

      

    二、代码实现

      1.Vector2

      

    #ifndef _VECTOR_2_H_
    #define _VECTOR_2_H_
    
    #include <cmath>
    #include <cassert>
    
    #define _IS_ZERO(num) ((num)>=-0.0001&&(num)<=0.0001)
    
    class CVector2
    {
    public:
        float x, y;
    
        //构造函数
        CVector2(float X = 0.0f, float Y = 0.0f)
            :
        x(X), y(Y)
        {}
    
        //设置x、y的值
        void Set(float X = 0.0f, float Y = 0.0f)
        {
            x = X;
            y = Y;
        }
    
        //得到向量的长度
        float Length() const
        {
            return sqrt(x * x + y * y);
        }
    
        //得到向量的单位向量
        CVector2 Normalize() const
        {
            //得到长度
            float len = Length();
    
            //断言,长度不能为0
            assert(!_IS_ZERO(len));
    
            //返回单位向量
            return CVector2(x / len, y / len);
        }
    
        //重载 + 运算
        CVector2 operator + (const CVector2& that) const
        {
            return CVector2(x + that.x, y + that.y);
        }
    
        //重载 += 运算
        CVector2& operator += (const CVector2& that)
        {
            x += that.x;
            y += that.y;
    
            return *this;
        }
    
        //重载 - 运算
        CVector2 operator - (const CVector2& that) const
        {
            return CVector2(x - that.x, y - that.y);
        }
    
        //重载 向量取符号
        CVector2 operator - () const
        {
            return CVector2(-x, -y);
        }
    
        //重载 -= 运算
        CVector2& operator -= (const CVector2& that)
        {
            x -= that.x;
            y -= that.y;
            return *this;
        }
    
        //重载 * 运算 --- 向量 * 标量 
        CVector2 operator * (float num) const
        {
            return CVector2(x * num, y * num);
        }
    
        //重载 *= 运算
        CVector2& operator *= (float num)
        {
            x *= num;
            y *= num;
            return *this;
        }
    };
    
    //如果需要让 标量 * 向量 也重载的话,那么不能写在向量类(CVector2)中
    //凡是向量类中的运算符重载,都是默认指定 this 在运算符的左侧,所以我们
    //只能去重载全局的乘法
    
    //在函数声明或定义中函数返回类型前加上关键字inline,即可以把函数指定为内联函数。
    //关键字inline必须与函数定义放在一起才能使函数成为内联,仅仅将inline放在函数声明前面不起任何作用。
    //inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。
    //一般的,用户可以阅读函数的声明,但是看不到函数的定义。
    inline CVector2 operator * (float num, const CVector2 v)
    {
        return CVector2(v.x * num, v.y * num);
    }
    
    #endif

      2.运行

    #include <windows.h>
    #include <time.h>
    #include "Vector2.h"
    #pragma comment(lib, "msimg32.lib")
    
    #define _CLIENT_W 640
    #define _CLIENT_H 480
    #define _SLEEP_TIME 33
    
    BOOL g_Act = TRUE;//窗口激活标志
    
    HDC g_MainDC;
    HDC g_BackDC;
    
    #define _R 32 //半径
    #define _SPEED 20.0f //速率
    #define _SPEED_SUB 0.1f //不断减小的速度
    CVector2 pos; //位置
    CVector2 speed; //加速度
    
    void GameInit(HWND hwnd)
    {
        g_MainDC = GetDC(hwnd);
        g_BackDC = CreateCompatibleDC(g_MainDC);
        HBITMAP hbmp = CreateCompatibleBitmap(g_MainDC, _CLIENT_W, _CLIENT_H);
        DeleteObject(SelectObject(g_BackDC, hbmp));
        DeleteObject(hbmp);
    }
    
    void GameRun(HWND hwnd)
    {
        BitBlt(g_BackDC, 0, 0, _CLIENT_W, _CLIENT_H, 0, 0, 0, WHITENESS);
    
        Ellipse(g_BackDC, pos.x - _R, pos.y - _R, pos.x + _R, pos.y + _R);
    
        BitBlt(g_MainDC, 0, 0, _CLIENT_W, _CLIENT_H, g_BackDC, 0, 0, SRCCOPY);
    
        //如果小球的速度不为0
        if (!_IS_ZERO(speed.Length()))
        {
            //小球位置移动
            pos += speed;
    
            //得到加速度大小
            float speed_len = speed.Length();
    
            //得到速度单位方向
            CVector2 speed_nor = speed.Normalize();
    
            //加速度不断减小
            speed_len -= _SPEED_SUB;
    
            //如果加速度 <= 0.0f
            if (speed_len <= 0.0f)
            {
                //重新设置加速度
                speed.Set();
            }
            //如果加速度 > 0.0f
            else
            {
                //加速度 = 加速度大小 * 加速度单位向量
                speed = speed_len * speed_nor; //标量*向量
            }
        }
    
        //如果按下鼠标左键
        if (GetAsyncKeyState(VK_LBUTTON) & 1)
        {
            //记录当前按下的点的位置
            POINT p;
            GetCursorPos(&p);
            ScreenToClient(hwnd, &p);
    
            //如果当前点x >= 0 并且 x < 窗口的左边 并且 当前点y >= 0 并且 y < 窗口呀的下方
            if (p.x >= 0 && p.x < _CLIENT_W && p.y >= 0 && p.y < _CLIENT_H)
            {
                //位移方向 = 当前点 - 圆圈的当前位置
                CVector2 dir = CVector2(p.x, p.y) - pos;
    
                //得到加速度
                speed = dir.Normalize();
                speed *= _SPEED;
            }
        }
    }
    
    void GameEnd(HWND hwnd)
    {
        DeleteDC(g_BackDC);
        ReleaseDC(hwnd, g_MainDC);
    }
    
    // 窗口消息函数,本函数将被操作系统调用
    __w64 long __stdcall WindowProc(HWND hwnd,//产生消息的窗口
        unsigned int uMsg,//消息类型
        __w64 unsigned int wParam,//消息附加参数1
        __w64 long lParam)//消息附加参数2
    {
        switch (uMsg)
        {
        case WM_DESTROY:
        {
            PostQuitMessage(0);
            return 0;
        }
        case WM_ACTIVATEAPP:
        {
            g_Act = (BOOL)wParam;
            return 0;
        }
        }
        //我们不关心的消息就调用DefWindowProc(windows对所有消息的默认处理函数)来帮助我们处理
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    
    
    int __stdcall WinMain(HINSTANCE hInstance,//应用程序实例句柄
        HINSTANCE hPrevInstance,
        LPSTR lpCmdLine,
        int nCmdShow)
    {
                    //01)填充一个窗口类别的结构体
        WNDCLASS wc;
        wc.style = CS_HREDRAW | CS_VREDRAW;
        wc.lpfnWndProc = WindowProc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hInstance = hInstance;
        wc.hIcon = LoadIcon(0, IDI_APPLICATION);
        wc.hCursor = LoadCursor(0, IDC_ARROW);
        wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
        wc.lpszMenuName = 0;
        wc.lpszClassName = "3Dtest";
        RegisterClass(&wc);
    
        int sw = GetSystemMetrics(SM_CXSCREEN);
        int sh = GetSystemMetrics(SM_CYSCREEN);
    
        RECT r =
        {
            (sw - _CLIENT_W) / 2,
            (sh - _CLIENT_H) / 2,
            (sw - _CLIENT_W) / 2 + _CLIENT_W,
            (sh - _CLIENT_H) / 2 + _CLIENT_H
        };
    
        //得到窗口风格
        //已知字节????????和风格00001000
        //那么(字节&~风格)就为
        //????????
        //11110111
        //--------
        //????0???
        int ws = (WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME) & ~WS_MAXIMIZEBOX;
    
        AdjustWindowRect(&r, ws, FALSE);
    
        HWND hWnd = CreateWindow(
            wc.lpszClassName,
            "向量测试1",//窗口标题栏文字
            ws,//窗口风格
            r.left,//窗口的左上角x坐标
            r.top,//窗口的左上角y坐标
            r.right - r.left,//窗口的宽(像素)
            r.bottom - r.top,//窗口的高(像素)
            HWND_DESKTOP,//父窗口窗口句柄,HWND_DESKTOP表示桌面
            0,//窗口菜单句柄,不使用菜单填0
            wc.hInstance,//应用程序实例句柄
            0);//任意地址,该地址可以通过WM_CREATE消息得到,不使用设置为0
    
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
    
        GameInit(hWnd);
    
        MSG msg = {};
        while (msg.message != WM_QUIT)
        {
            if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            else if (g_Act)
            {
                int bt = GetTickCount();
                GameRun(hWnd);
                int at = GetTickCount() - bt;
                Sleep(at < _SLEEP_TIME ? _SLEEP_TIME - at : 1);
            }
            else
                WaitMessage();
        }
    
        GameEnd(hWnd);
    
        return 1;
    }
  • 相关阅读:
    Jenkins持续集成邮件发送
    基于appium快速实现H5自动化测试
    Linux常用命令学习一
    BZOJ4372烁烁的游戏——动态点分治+线段树(点分树套线段树)
    BZOJ3730震波——动态点分治+线段树(点分树套线段树)
    BZOJ1014[JSOI2008]火星人——非旋转treap+二分答案+hash
    BZOJ1299[LLH邀请赛]巧克力棒——Nim游戏+搜索
    BZOJ1115[POI2009]石子游戏——阶梯Nim游戏
    BZOJ3110[Zjoi2013]K大数查询——权值线段树套线段树
    BZOJ5343[Ctsc2018]混合果汁——主席树+二分答案
  • 原文地址:https://www.cnblogs.com/Dean27/p/7783509.html
Copyright © 2011-2022 走看看