|


#pragma once
#include <Windows.h>
#include <tchar.h>
#include "CELLMath.hpp"
using namespace CELL;
float3 g_cubeVertices[] ={ //4个点组成一个面,一共6个面,
//前面
float3(-1.0f,-1.0f, 1.0f ),//前面 左下
float3( 1.0f,-1.0f, 1.0f ),//前面 右下
float3( 1.0f, 1.0f, 1.0f ),//前面 右上
float3(-1.0f, 1.0f, 1.0f ),//前面 左上
//后面
float3(-1.0f,-1.0f,-1.0f ),
float3(-1.0f, 1.0f,-1.0f ),
float3( 1.0f, 1.0f,-1.0f ),
float3( 1.0f,-1.0f,-1.0f ),
//上面
float3(-1.0f, 1.0f,-1.0f ),
float3(-1.0f, 1.0f, 1.0f ),
float3( 1.0f, 1.0f, 1.0f ),
float3( 1.0f, 1.0f,-1.0f ),
//下面
float3(-1.0f,-1.0f,-1.0f ),
float3( 1.0f,-1.0f,-1.0f ),
float3( 1.0f,-1.0f, 1.0f ),
float3(-1.0f,-1.0f, 1.0f ),
//右侧
float3( 1.0f,-1.0f,-1.0f ),
float3( 1.0f, 1.0f,-1.0f ),
float3( 1.0f, 1.0f, 1.0f ),
float3( 1.0f,-1.0f, 1.0f ),
//左侧
float3(-1.0f,-1.0f,-1.0f ),
float3(-1.0f,-1.0f, 1.0f ),
float3(-1.0f, 1.0f, 1.0f ),
float3(-1.0f, 1.0f,-1.0f )
};
class Soft3d{
float2 _viewPort;//视口坐标
matrix4 _model;//模型矩阵
matrix4 _proj;//投影矩阵
matrix4 _view;//视图矩阵(观察矩阵)
float3 _trans;
float3 _scale;
quatr _quat;
float _angel;
public:
Soft3d(){
_trans = float3(0,0,-5);
_scale = float3(1,1,1);
_quat = angleAxis(float(0),float3(0,0,1));
_model = makeTransform(float3(0,0,0),_scale,_quat);
_view = matrix4(1);
_angel = 0;
}
void setTranlate(float3 trans) {
_trans = trans;
}
void setScale(float3 scale){
_scale = scale;
}
void rotate(float angle,float3 axis) {
_quat = CELL::rotate(float(angle),axis);
}
void drawLine(HDC hDC,const float3* arData,int length){
for (int i = 0 ;i < length ; ++ i) {
float3 pos = arData[i];
float4 world(pos.x,pos.y,pos.z,1);
float4 screen;
worldToScreen(world,screen);
if (i %4 == 0) {//一共6个面,每个面4个顶点(4个画一组)
::MoveToEx(hDC,int(screen.x),int(screen.y),0);//把画笔移到什么位置
}else{
::LineTo(hDC,int(screen.x),int(screen.y));//画到什么地方
}
}
}
void setViewport(float w,float h) {
_viewPort = float2(w,h);
}
void perspect(){
_proj = perspective<float>(45.0f,_viewPort.x/_viewPort.y,0.1f,1000);
}
/**
* 世界坐标转化为窗口坐标
*/
bool worldToScreen( const float4& world, float4& screen ){
screen = (_proj * _view * _model) * world;
if (screen.w == 0.0f){
return false;
}
screen.x /= screen.w;
screen.y /= screen.w;
screen.z /= screen.w;
// map to range 0 - 1
screen.x = screen.x * 0.5f + 0.5f;
screen.y = screen.y * 0.5f + 0.5f;
screen.z = screen.z * 0.5f + 0.5f;
// map to viewport
screen.x = screen.x * _viewPort.x;
screen.y = _viewPort.y - (screen.y * _viewPort.y);
return true;
}
/**
* 绘制函数
*/
void render(HDC hDC,float elapsed){
_angel += elapsed;
rotate(_angel,float3(1,1,1));
_model = CELL::makeTransform(_trans,_scale,_quat);
drawLine(hDC,g_cubeVertices,sizeof(g_cubeVertices)/sizeof(g_cubeVertices[0]));
}
};
class CELLWinApp{
public:
//! 实例句柄
HINSTANCE _hInstance;
//! 窗口句柄
HWND _hWnd;
//! 窗口的高度
int _width;
//! 窗口的宽度
int _height;
HDC _hMemDC; //内存DC(可以理解成 画板或设备)
HBITMAP _hBmp; //内存位图(可以理解成 一张纸)
Soft3d _device;
public:
CELLWinApp(HINSTANCE hInstance) :_hInstance(hInstance){
WNDCLASSEX winClass;
winClass.lpszClassName = _T("CELLWinApp");
winClass.cbSize = sizeof(winClass);
winClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
winClass.lpfnWndProc = wndProc;
winClass.hInstance = hInstance;
winClass.hIcon = 0;
winClass.hIconSm = 0;
winClass.hCursor = LoadCursor(hInstance, IDC_ARROW);
winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winClass.lpszMenuName = NULL;
winClass.cbClsExtra = 0;
winClass.cbWndExtra = 0;
RegisterClassEx(&winClass);
_hBmp = 0;
_hMemDC = 0;
}
virtual ~CELLWinApp() {
UnregisterClass(_T("CELLWinApp"),_hInstance);
}
protected:
static LRESULT CALLBACK wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
CELLWinApp* pThis = (CELLWinApp*)GetWindowLong(hWnd,GWL_USERDATA);
if (pThis)
{
return pThis->onEvent(hWnd,msg,wParam,lParam);
}
if (WM_CREATE == msg)
{
CREATESTRUCT* pCreate = (CREATESTRUCT*)lParam;
SetWindowLong(hWnd,GWL_USERDATA,(DWORD_PTR)pCreate->lpCreateParams);
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
public:
virtual LRESULT onEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
case WM_DESTROY:
{
::PostQuitMessage(0);
}
break;
case WM_MOUSEMOVE:
break;
case WM_SIZE:{//当窗口大小发生改变时
if (::IsWindow(_hWnd)){//如果窗口存在
if (_hBmp){
DeleteObject(_hBmp);
}
RECT rect;
GetClientRect(_hWnd,&rect);
HDC hDC = GetDC(_hWnd);
int w = rect.right - rect.left;
int h = rect.bottom - rect.top;
_hBmp = CreateCompatibleBitmap(hDC,w,h);
SelectObject(_hMemDC,_hBmp);//画板和纸关联在一起
ReleaseDC(_hWnd,hDC);
}
}
break;
default:
return DefWindowProc( hWnd, msg, wParam, lParam );
}
return S_OK;
}
/**
* 主函数
*/
int main(int width,int height){
_hWnd = CreateWindowEx( NULL,_T("CELLWinApp"),_T("CELLWinApp"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, NULL, NULL, _hInstance, this );
if (_hWnd == 0) {
return -1;
}
ShowWindow(_hWnd,SW_SHOW);
RECT rect;
GetClientRect(_hWnd,&rect);
int w = rect.right - rect.left;
int h = rect.bottom - rect.top;
HDC hDC = GetDC(_hWnd);//获取系统的画板或设备
//创建双缓冲区
_hMemDC = CreateCompatibleDC(hDC);//创建与当前DC兼容的内存DC
_hBmp = CreateCompatibleBitmap(hDC,w,h);// 创建一块指定大小的位图
SelectObject(_hMemDC,_hBmp);//画板和纸关联在一起
HPEN pen = ::CreatePen(PS_SOLID,1,RGB(255,255,255));//创建画笔,画笔颜色是白颜色
SelectObject(_hMemDC,pen);///画板和画笔关联在一起
MSG msg = {0};
while(msg.message != WM_QUIT) {
if (msg.message == WM_DESTROY || msg.message == WM_CLOSE) {
break;
}
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) { // 有消息,处理消息,无消息,则进行渲染绘制
TranslateMessage( &msg );
DispatchMessage( &msg );
}
HDC hDC = GetDC(_hWnd);
RECT rect;
GetClientRect(_hWnd,&rect);
int w = rect.right - rect.left;
int h = rect.bottom - rect.top;
bool isSHC=true;
if(isSHC){
FillRect(_hMemDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));
{
_device.setViewport(rect.right - rect.left,rect.bottom - rect.top);
_device.perspect();
_device.render(_hMemDC,.1f);
}
//将双缓冲区图像复制到显示缓冲区
BitBlt(hDC,0,0,w,h,_hMemDC,0,0,SRCCOPY);//把当前画板上的内容画到当前窗口上
}else{
SelectObject(hDC,pen);///画板和画笔关联在一起
FillRect(hDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));
{
_device.setViewport(rect.right - rect.left,rect.bottom - rect.top);
_device.perspect();
_device.render(hDC,.1f);
}
}
ReleaseDC(_hWnd,hDC);//释放引用计数
}
if (_hMemDC){
DeleteDC(_hMemDC);
}
if (_hBmp) {
DeleteObject(_hBmp);
}
return 0;
}
};
源码地址http://pan.baidu.com/s/1geVargZ
---------
{双缓冲步骤
1:创建一个画板(内存位图和画笔)
2:把要显示的东西画的内存位图上
3:把内存位图上的内容贴到显示器上
BitBlt(hDC,0,0,w,h,_hMemDC,0,0,SRCCOPY);
}
{具体实现步骤
1:创建一个画板(内存位图和画笔)
画板必须关联纸和画笔
HDC _hMemDC = CreateCompatibleDC(hDC); //创建与当前DC兼容的内存DC
HBITMAP _hBmp = CreateCompatibleBitmap(hDC,w,h); //创建一块指定大小的位图
SelectObject(_hMemDC,_hBmp);//画板和纸关联在一起
HPEN pen = ::CreatePen(PS_SOLID,1,RGB(255,255,255));//创建画笔,画笔颜色是白颜色
SelectObject(_hMemDC,pen);//画板和画笔关联在一起
2:把要显示的东西画的内存位图上
1:指定画面大小和颜色
FillRect(_hMemDC,&rect,(HBRUSH)GetStockObject(BLACK_BRUSH));
2:要画的东西画到画板上
_device.setViewport(rect.right - rect.left,rect.bottom - rect.top);
_device.perspect();
_device.render(_hMemDC,.1f);
3:把内存位图上的内容贴到显示器上
BitBlt(hDC,0,0,w,h,_hMemDC,0,0,SRCCOPY);
}
|