2d图形旋转

news/2025/3/5 6:22:08/

2d图形旋转

1.这里旋转使用数学公式:
xr = x * cos(theta) - y * sin(theta);
yr = x * sin(theta) + y * cos(theta);
2.如果以左上角为原点(0,0),x方向向右增加,y方向向下增加的话,对于原图形旋转的100度并不等于连续20次的旋转5度的结果,可以举例对比一下。
3.memcpy对于复制对象真的很好用。
4.在这里我重画背景使用的是gdi的FillRect:
HDC hdc;
lpddsprimary->GetDC(&hdc);
FillRect(hdc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH));
lpddsprimary->ReleaseDC(hdc);
该程序以左上角(0,0)为原点,支持移动、改变窗口大小重画360°图形。

#include <Windows.h>
#include <ddraw.h>
#include <math.h>#pragma comment(lib, "ddraw.lib")
#pragma comment(lib, "dxguid.lib")#define WINDOW_WIDTH		640
#define WINDOW_HEIGHT		480
#define SCREEN_BPP			32
#define SCREEN_WIDTH		1920
#define SCREEN_HEIGHT		1080
#define KEY_DOWN(vk_code)	(GetAsyncKeyState(vk_code) & 0x8000 ? 1 : 0)
#define KEY_UP(vk_code)		(GetAsyncKeyState(vk_code) & 0x8000 ? 0 : 1)#define CLIP_CODE_C		0x0000
#define CLIP_CODE_N		0x0008
#define CLIP_CODE_S		0x0004
#define CLIP_CODE_E		0x0002
#define CLIP_CODE_W		0x0001#define CLIP_CODE_NE	0x000a
#define CLIP_CODE_SE	0x0006
#define CLIP_CODE_NW	0x0009
#define CLIP_CODE_SW	0x0005typedef struct VERTEX2DI_TYP
{int x, y;
}VERTEX2DI, * VERTEX2DI_PTR;typedef struct POLYGON2D_TYP
{int state;int num_verts;int x0, y0;int xv, yv;LONG color;VERTEX2DI* vlist;
} POLYGON2D, * POLYGON2D_PTR;HWND main_hwnd = nullptr;
RECT client;
LPDIRECTDRAW7 lpdd7 = nullptr;
LPDIRECTDRAWSURFACE7 lpddsprimary = nullptr;
LPDIRECTDRAWCLIPPER lpddclipper = nullptr;
DDSURFACEDESC2 ddsd;
int pixel;
int window_close = 0;
POLYGON2D triangles[4];
float cos_look[360];
float sin_look[360];
int theta = -5;	//旋转度数int Game_Init(void* params = nullptr, int num_params = 0);
int Game_Main(void* params = nullptr, int num_params = 0);
int Game_Shutdown(void* params = nullptr, int num_params = 0);
int Draw_Line(int x1, int y1, int x2, int y2, LONG color, LONG* vb_start, int iPitch);
int Clip_Line(int& x1, int& y1, int& x2, int& y2);
int GetInterSectionPoint(int p_code, int& xc, int& yc, int x1, int y1, int x2, int y2, int min_clip_x, int min_clip_y, int max_clip_x, int max_clip_y);
int Draw_Clip_Line(int x1, int y1, int x2, int y2, LONG color, LONG* vb_start, int iPitch);
int Draw_Polygon2D(POLYGON2D_PTR poly, LONG* vb_strat, int iPitch);
int Rotate_Polygon2D(POLYGON2D_PTR poly, int theta);LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{TCHAR szAppName[] = TEXT("normal window");MSG msg;WNDCLASS wndclass;wndclass.style = CS_VREDRAW | CS_HREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(nullptr, IDI_APPLICATION);wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW);wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndclass.lpszMenuName = nullptr;wndclass.lpszClassName = szAppName;if (!RegisterClass(&wndclass)){MessageBox(nullptr, TEXT("Register Class Failed"), szAppName, MB_ICONERROR);return 0;}client = {0, 0, WINDOW_WIDTH-1, WINDOW_HEIGHT-1};AdjustWindowRect(&client, WS_OVERLAPPEDWINDOW, false);main_hwnd = CreateWindow(szAppName, TEXT("normal_window"), WS_OVERLAPPEDWINDOW | WS_VISIBLE,CW_USEDEFAULT, CW_USEDEFAULT, client.right - client.left, client.bottom - client.top,nullptr, nullptr, hInstance, nullptr);Game_Init();while (true){if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)){if (msg.message == WM_QUIT)break;TranslateMessage(&msg);DispatchMessage(&msg);}Game_Main();}Game_Shutdown();return msg.wParam;
}LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{HDC hdc;PAINTSTRUCT ps;int xPos;int yPos;switch (message){case WM_CREATE://createreturn 0;case WM_SIZE://change sizetheta = -5;return 0;case WM_MOVE://movetheta = -5;return 0;case WM_LBUTTONDOWN:xPos = LOWORD(lParam);yPos = HIWORD(lParam);return 0;case WM_PAINT:hdc = BeginPaint(hwnd, &ps);//drawEndPaint(hwnd, &ps);return 0;case WM_DESTROY:window_close = 1;PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, message, wParam, lParam);
}int Game_Init(void* params, int num_params)
{if (FAILED(DirectDrawCreateEx(nullptr, (LPVOID*)&lpdd7, IID_IDirectDraw7, nullptr)))return 0;lpdd7->SetCooperativeLevel(main_hwnd, DDSCL_NORMAL);memset(&ddsd, 0, sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);ddsd.dwFlags = DDSD_CAPS;ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;if (FAILED(lpdd7->CreateSurface(&ddsd, &lpddsprimary, nullptr)))return 0;//获取像素格式DDPIXELFORMAT ddpixelformat;memset(&ddpixelformat, 0, sizeof(ddpixelformat));ddpixelformat.dwSize = sizeof(ddpixelformat);lpddsprimary->GetPixelFormat(&ddpixelformat);pixel = ddpixelformat.dwRGBBitCount;if (FAILED(lpdd7->CreateClipper(0, &lpddclipper, nullptr)))return 0;if (FAILED(lpddclipper->SetHWnd(0, main_hwnd)))return 0;if (FAILED(lpddsprimary->SetClipper(lpddclipper)))return 0;//init trianglesfor (int i = 0; i < 4; i++){triangles[i].state = 1;triangles[i].num_verts = 4;RECT rect = { 300 + i * 50, 300 + i * 50, 300 + i * 50 + 50, 300 + i * 50 + 50 };triangles[i].x0 = (rect.left + rect.right) / 2;triangles[i].y0 = (rect.top + rect.bottom) / 2;triangles[i].xv = triangles[i].yv = 10;triangles[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);triangles[i].vlist = new VERTEX2DI[triangles[i].num_verts];triangles[i].vlist[0] = { rect.left, rect.top };triangles[i].vlist[1] = { rect.right, rect.top };triangles[i].vlist[2] = { rect.right, rect.bottom };triangles[i].vlist[3] = { rect.left, rect.bottom };}//generate the tablesfor (int ang = 0; ang < 360; ang++){float theta = (float)ang * 3.14159 / 180;sin_look[ang] = sin(theta);cos_look[ang] = cos(theta);}return 1;
}int Game_Main(void* params, int num_params)
{DDBLTFX ddbltfx;if (KEY_DOWN(VK_ESCAPE)){window_close = 1;SendMessage(main_hwnd, WM_CLOSE, 0, 0);return 0;}if (window_close)return 0;//GetClientRect(main_hwnd, &client);GetWindowRect(main_hwnd, &client);if (theta == -5)	//界面初始化为白色{HDC hdc;lpddsprimary->GetDC(&hdc);FillRect(hdc, &client, (HBRUSH)GetStockObject(WHITE_BRUSH));lpddsprimary->ReleaseDC(hdc);}memset(&ddsd, 0, sizeof(ddsd));ddsd.dwSize = sizeof(ddsd);if (FAILED(lpddsprimary->Lock(nullptr, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, nullptr)))return 0;LONG* video_buffer = (LONG*)ddsd.lpSurface;int ipitch = ddsd.lPitch;if (pixel == 32){if (theta < 355){theta += 5;if (theta == 360){int x = 0;}//init temp_trianglesPOLYGON2D temp_triangles[4];memcpy(temp_triangles, triangles, sizeof(triangles));for (int i = 0; i < 4; i++){temp_triangles[i].vlist = new VERTEX2DI[temp_triangles[i].num_verts];memcpy(temp_triangles[i].vlist, triangles[i].vlist, temp_triangles[i].num_verts * sizeof(VERTEX2DI));}for (int i = 0; i < 4; i++){Rotate_Polygon2D(temp_triangles + i, theta);Draw_Polygon2D(temp_triangles + i, video_buffer, ipitch >> 2);}//destroy temp_triangles.vlistfor (int i = 0; i < 4; i++)delete[] temp_triangles[i].vlist;}}if (FAILED(lpddsprimary->Unlock(nullptr)))return 0;//Sleep(10000);return 1;
}int Game_Shutdown(void* params, int num_params)
{if (lpddsprimary){lpddsprimary->Release();lpddsprimary = nullptr;}if (lpddclipper){lpddclipper->Release();lpddclipper = nullptr;}if (lpdd7){lpdd7->Release();lpdd7 = nullptr;}//destroy trianglesfor (int i = 0; i < 4; i++)delete[] triangles[i].vlist;return 1;
}int Draw_Line(int x1, int y1, int x2, int y2, LONG color, LONG* vb_start, int iPitch)
{int dx = x2 - x1;int dy = y2 - y1;int inx, iny, dx2, dy2, error;if (dx >= 0)inx = 1;else{inx = -1;dx = -dx;}if (dy >= 0)iny = iPitch;else{iny = -iPitch;dy = -dy;}dx2 = dx << 1;dy2 = dy << 1;vb_start += x1 + y1 * iPitch;if (dx > dy){error = dy2 - dx;for (int i = 0; i <= dx; i++){*vb_start = color;if (error >= 0){error -= dx2;vb_start += iny;}error += dy2;vb_start += inx;}}else{error = dx2 - dy;for (int i = 0; i <= dy; i++){*vb_start = color;if (error >= 0){error -= dy2;vb_start += inx;}error += dx2;vb_start += iny;}}return 1;
}int Clip_Line(int& x1, int& y1, int& x2, int& y2)
{int min_clip_x = client.left;int min_clip_y = client.top;int max_clip_x = client.right;int max_clip_y = client.bottom;int xc1 = x1, yc1 = y1, xc2 = x2, yc2 = y2;int p1_code = 0, p2_code = 0;if (y1 < min_clip_y)p1_code |= CLIP_CODE_N;else if (y1 > max_clip_y)p1_code |= CLIP_CODE_S;if (x1 < min_clip_x)p1_code |= CLIP_CODE_W;else if (x1 > max_clip_x)p1_code |= CLIP_CODE_E;if (y2 < min_clip_y)p2_code |= CLIP_CODE_N;else if (y2 > max_clip_y)p2_code |= CLIP_CODE_S;if (x2 < min_clip_x)p2_code |= CLIP_CODE_W;else if (x2 > max_clip_x)p2_code |= CLIP_CODE_E;if (p1_code & p2_code)return 0;if (p1_code == 0 && p2_code == 0)return 1;int iSpStatus1 = GetInterSectionPoint(p1_code, xc1, yc1, x1, y1, x2, y2, min_clip_x, min_clip_y, max_clip_x, max_clip_y);int iSpStatus2 = GetInterSectionPoint(p2_code, xc2, yc2, x1, y1, x2, y2, min_clip_x, min_clip_y, max_clip_x, max_clip_y);if (!(iSpStatus1 | iSpStatus2))return  0;x1 = xc1;y1 = yc1;x2 = xc2;y2 = yc2;return 1;
}int GetInterSectionPoint(int p_code, int& xc, int& yc, int x1, int y1, int x2, int y2, int min_clip_x, int min_clip_y, int max_clip_x, int max_clip_y)
{switch (p_code){case CLIP_CODE_N:yc = min_clip_y;xc = x1 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1);break;case CLIP_CODE_S:yc = max_clip_y;xc = x1 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1);break;case CLIP_CODE_W:xc = min_clip_x;yc = y1 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1);break;case CLIP_CODE_E:xc = max_clip_x;yc = y1 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1);break;case CLIP_CODE_NW:yc = min_clip_y;xc = x1 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1);if (xc < min_clip_x){xc = min_clip_x;yc = y1 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1);}break;case CLIP_CODE_SW:yc = max_clip_y;xc = x1 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1);if (xc < min_clip_x){xc = min_clip_x;yc = y1 + (min_clip_x - x1) * (y2 - y1) / (x2 - x1);}break;case CLIP_CODE_NE:yc = min_clip_y;xc = x1 + (min_clip_y - y1) * (x2 - x1) / (y2 - y1);if (xc > max_clip_x){xc = max_clip_x;yc = y1 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1);}break;case CLIP_CODE_SE:yc = max_clip_y;xc = x1 + (max_clip_y - y1) * (x2 - x1) / (y2 - y1);if (xc > max_clip_x){xc = max_clip_x;yc = y1 + (max_clip_x - x1) * (y2 - y1) / (x2 - x1);}break;}if (xc < min_clip_x || xc > max_clip_x || yc < min_clip_y || yc > max_clip_y)return 0;return 1;
}int Draw_Clip_Line(int x1, int y1, int x2, int y2, LONG color, LONG* vb_start, int iPitch)
{int iDcStatus = Clip_Line(x1, y1, x2, y2);if (!iDcStatus)return 0;Draw_Line(x1, y1, x2, y2, color, vb_start, iPitch);return 1;
}int Draw_Polygon2D(POLYGON2D_PTR poly, LONG* vb_strat, int iPitch)
{if (poly->state){for (int i = 0; i < poly->num_verts - 1; i++){Draw_Clip_Line(poly->vlist[i].x, poly->vlist[i].y, poly->vlist[i + 1].x, poly->vlist[i + 1].y, poly->color, vb_strat, iPitch);}Draw_Clip_Line(poly->vlist[poly->num_verts - 1].x, poly->vlist[poly->num_verts - 1].y, poly->vlist[0].x, poly->vlist[0].y, poly->color, vb_strat, iPitch);return 1;}return 0;
}int Rotate_Polygon2D(POLYGON2D_PTR poly, int theta)
{if (!poly)return 0;for (int curr_vert = 0; curr_vert < poly->num_verts; curr_vert++){float xr = poly->vlist[curr_vert].x * cos_look[theta] - poly->vlist[curr_vert].y * sin_look[theta];float yr = poly->vlist[curr_vert].x * sin_look[theta] + poly->vlist[curr_vert].y * cos_look[theta];poly->vlist[curr_vert].x = xr;poly->vlist[curr_vert].y = yr;}return 1;
}

下面是效果图:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/news/505811.html

相关文章

2D-2D:对极几何与三角测量

文章目录 尺度不确定性对极几何尺度不确定性初始化的纯旋转问题 三角测量最小二乘法 单应性矩阵由像素系到相机系由像素系a到像素系b求解单应性矩阵 尺度不确定性 如果把相机的运动和场景同时放大两倍&#xff0c;单目相机所看到的像是一样的。同样的&#xff0c;把这个大小乘…

3D空间中的点坐标转化为屏幕二维点坐标(二)

&#x1f449;原文地址&#xff1a;3D空间中的点坐标转化为屏幕二维点坐标&#xff08;二&#xff09;&#x1f448; 上一节&#xff0c;简单的介绍了计算机时如何将三维世界中的点转化成屏幕上的二维点坐标的&#xff0c;知道了透视矩阵的作用。这一节内容&#xff0c;就是介…

3D点云综述

转载请注明作者和出处&#xff1a; http://blog.csdn.net/john_bh/ 论文链接&#xff1a;Deep Learning for 3D Point Clouds: A Survey 作者及团队&#xff1a;国防科大 & 中山大学 & 牛津大学 会议及时间&#xff1a; Arxiv 2019 code&#xff1a;https://github.co…

3D空间中的点坐标转化为屏幕二维点坐标(一)

每个人在进入计算机图形学的世界中&#xff0c;都有一个同样的困惑&#xff0c;三维世界中的三维坐标是如何被转换成屏幕上的二维坐标的&#xff0c;我如何在屏幕上找到一个点&#xff08;二维点&#xff09;对应三维世界中的点&#xff08;三维点&#xff09;呢&#xff1f; …

相机标定2d坐标转3d坐标

相机标定原理&#xff1a; 可以看看这两篇&#xff1a; https://blog.csdn.net/baidu_38172402/article/details/81949447 https://blog.csdn.net/weixin_43206570/article/details/84797361 在图像测量过程以及机器视觉应用中&#xff0c;为确定空间物体表面某点的三维几何位…

将3D坐标转成2D坐标的方法

将3D坐标转成2D坐标的方法。3D坐标在Unity中称作World Space,2D坐标称作Screen Space, 是以pixel为基准&#xff0c;以iPad 1024 x 768&#xff08;4:3&#xff09;的解析度为例子&#xff1a; 左上角是 &#xff08;0,0&#xff09; 右下角是&#xff08;1024,768&#xff0…

卫星建模、自动单体、实时三维重建...瞰景Smart3D 2023系列新产品新技术发布!

3月17日&#xff0c;由重庆市测绘地理信息学会、武汉大学遥感信息工程学院、重庆荣昌高新技术产业开发区管理委员会联合主办&#xff0c;瞰景科技发展&#xff08;上海&#xff09;有限公司承办的“智绘时空瞰见未来 2023实景三维中国新技术研讨会”于在重庆成功召开。本次大会…

nginx配置详细说明

server {listen 80;listen 443 ssl http2;server_name his6.dieya.net;index index.php index.html index.htm default.php default.htm default.html;root /www/wwwroot/his6.dieya.net/;#SSL-START SSL相关配置&#xff0c;请勿删除或修改下一行带注释的404规则#error_page 4…