#include "CPPYIN.3DLib.h"
// 全局变量
IDirect3DDevice9* pDevice = 0;
IDirect3DSurface9* pSurface = 0;
D3DLOCKED_RECT lockedRect;
bool _CPPYIN_3DLib::Init3DLib(HINSTANCE hInstance, HWND hWnd, int width, int height)
{
IDirect3D9* d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
d3dpp.BackBufferWidth = width;
d3dpp.BackBufferHeight = height;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.Windowed = TRUE;
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice);
d3d9->Release();
pDevice->CreateOffscreenPlainSurface(width, height, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pSurface, 0);
return true;
}
int _CPPYIN_3DLib::LockSurface()
{
memset(&lockedRect, 0, sizeof(lockedRect));
pSurface->LockRect(&lockedRect,NULL,D3DLOCK_DISCARD);
return 1;
}
int _CPPYIN_3DLib::UnlockSurface()
{
pSurface->UnlockRect();
return 1;
}
int _CPPYIN_3DLib::DrawPixel(int x,int y, DWORD color)
{
DWORD* pBits = (DWORD*)lockedRect.pBits;
pBits[x + y * (lockedRect.Pitch >> 2)] = color;
return 1;
}
int _CPPYIN_3DLib::DrawLine(int x0, int y0, int x1, int y1, DWORD color)
{
int x, y, dx, dy, dx2, dy2, xstep, ystep, error, index;
x = x0;
y = y0;
dx = x1 - x0;
dy = y1 - y0;
if (dx >= 0) // 从左往右画
{
xstep = 1; // x步进正1
}
else // 从右往左画
{
xstep = -1; // x步进负1
dx = -dx; // 取绝对值
}
if (dy >= 0) // 从上往下画
{
ystep = 1; // y步进正1
}
else // 从下往上画
{
ystep = -1; // y步进负1
dy = -dy; // 取绝对值
}
dx2 = dx << 1; // 2 * dx
dy2 = dy << 1; // 2 * dy
if (dx > dy) // 近X轴直线
{
error = dy2 - dx;
for (index = 0; index <= dx; ++index)
{
DrawPixel(x, y, color);
if (error >= 0)
{
error -= dx2;
y += ystep;
}
error += dy2;
x += xstep;
}
}
else // 近Y轴直线
{
error = dx2 - dy;
for (index = 0; index <= dy; ++index)
{
DrawPixel(x, y, color);
if (error >= 0)
{
error -= dy2;
x += xstep;
}
error += dx2;
y += ystep;
}
}
return 1;
}
// 返回1则有交点,返回0则无交点,无需画了
int _CPPYIN_3DLib::ClipLineByRect(int x1, int y1, int x2, int y2, RECT rect, int &nx1, int &ny1, int &nx2, int &ny2)
{
// 创建并设置起点p1和终点p2的位置代码p1code和p2code
int p1code = 0;
int p2code = 0;
if (y1 < rect.top)
p1code |= 8;
else if (y1 > rect.bottom)
p1code |= 4;
if (x1 < rect.left)
p1code |= 1;
else if (x1 > rect.right)
p1code |= 2;
if (y2 < rect.top)
p2code |= 8;
else if (y2 > rect.bottom)
p2code |= 4;
if (x2 < rect.left)
p2code |= 1;
else if (x2 > rect.right)
p2code |= 2;
// 过滤同侧情况
if ((p1code & p2code))
return 0;
// 完全保留
if (p1code == 0 && p2code == 0)
{
nx1 = x1;
ny1 = y1;
nx2 = x2;
ny2 = y2;
return 1;
}
// 计算np1的坐标nx1, ny1
switch(p1code)
{
case 0: // C
{
nx1 = x1;
ny1 = y1;
} break;
case 8: // N
{
ny1 = rect.top;
nx1 = int(x1 + (rect.top - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
} break;
case 4: // S
{
ny1 = rect.bottom;
nx1 = int(x1 + (rect.bottom - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
} break;
case 1: // W
{
nx1 = rect.left;
ny1 = int(y1 + (rect.left - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
} break;
case 2: // E
{
nx1 = rect.right;
ny1 = int(y1 + (rect.right - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
} break;
case 9: // NW
{
// 先和求N的一样
ny1 = rect.top;
nx1 = int(x1 + (rect.top - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
// 然后判断结果
if (nx1 < rect.left || nx1 > rect.right) // 上面的假设错误,需要算与左边线的交点
{
nx1 = rect.left;
ny1 = int(y1 + (rect.left - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
case 10: // NE
{
ny1 = rect.top;
nx1 = int(x1 + (rect.top - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
if (nx1 < rect.left || nx1 > rect.right)
{
nx1 = rect.right;
ny1 = int(y1 + (rect.right - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
case 6: // SE
{
ny1 = rect.bottom;
nx1 = int(x1 + (rect.bottom - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
if (nx1 < rect.left || nx1 > rect.right)
{
nx1 = rect.right;
ny1 = int(y1 + (rect.right - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
case 5: // SW
{
ny1 = rect.bottom;
nx1 = int(x1 + (rect.bottom - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
if (nx1 < rect.left || nx1 > rect.right)
{
nx1 = rect.left;
ny1 = int(y1 + (rect.left - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
}
// 计算np2的坐标nx2, ny2
switch(p2code)
{
case 0: // C
{
nx2 = x2;
ny2 = y2;
} break;
case 8: // N
{
ny2 = rect.top;
nx2 = int(x1 + (rect.top - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
} break;
case 4: // S
{
ny2 = rect.bottom;
nx2 = int(x1 + (rect.bottom - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
} break;
case 1: // W
{
nx2 = rect.left;
ny2 = int(y1 + (rect.left - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
} break;
case 2: // E
{
nx2 = rect.right;
ny2 = int(y1 + (rect.right - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
} break;
case 9: // NW
{
// 先和求N的一样
ny2 = rect.top;
nx2 = int(x1 + (rect.top - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
// 然后判断结果
if (nx2 < rect.left || nx2 > rect.right) // 上面的假设错误,需要算与左边线的交点
{
nx2 = rect.left;
ny2 = int(y1 + (rect.left - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
case 10: // NE
{
ny2 = rect.top;
nx2 = int(x1 + (rect.top - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
if (nx2 < rect.left || nx2 > rect.right)
{
nx2 = rect.right;
ny2 = int(y1 + (rect.right - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
case 6: // SE
{
ny2 = rect.bottom;
nx2 = int(x1 + (rect.bottom - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
if (nx2 < rect.left || nx2 > rect.right)
{
nx2 = rect.right;
ny2 = int(y1 + (rect.right - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
case 5: // SW
{
ny2 = rect.bottom;
nx2 = int(x1 + (rect.bottom - y1) * (x2 - x1) / (double)(y2 - y1) + 0.5);
if (nx2 < rect.left || nx2 > rect.right)
{
nx2 = rect.left;
ny2 = int(y1 + (rect.left - x1) * (y2 - y1) / (double)(x2 - x1) + 0.5);
}
} break;
}
// 过滤一种直线与矩形不相交的特殊情况
if (nx1 < rect.left || nx1 > rect.right ||
ny1 < rect.top || ny1 > rect.bottom ||
nx2 < rect.left || nx2 > rect.right ||
ny2 < rect.top || ny2 > rect.bottom)
{
return 0;
}
return 1;
}
void _CPPYIN_3DLib::FlipSurface()
{
// 获取后台缓存
IDirect3DSurface9* backBuffer = 0;
pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
// 使用自定义表面填充后台缓存
pDevice->StretchRect(pSurface, 0, backBuffer, 0, D3DTEXF_NONE);
// GetBackBuffer所得的缓存需要被释放,否则会内存泄露
backBuffer->Release();
// 将交换链中的后台缓存显示
pDevice->Present(0, 0, 0, 0);
}
void _CPPYIN_3DLib::Release3DLib()
{
pSurface->Release();
pDevice->Release();
}
- 1
- 2
- 3
前往页