如何实现3D效果(绘制长方体/立方体)

原文地址::http://www.devdiv.net/viewthread-8326

原帖地址::http://www.devdiv.net/bbs/viewthread.php?tid=8326&extra=&page=1

 

 

 

 

 

 

 

 

 

现在有三张图片,希望可以将其做为一个长方体的可见的三个面。
我的思路是,将这三张图片分别打印到三个DC上,然后对这三块DC进行操作,但是对Windows编程了解太少,不知如何下手。
向诸位请教了。
2009-4-24 10:10:29

CODE:

/// <summary>
        /// 画矩形体
        /// </summary>
        /// <param name="x">矩形体最外面的矩形的左上角x坐标</param>
        /// <param name="y">矩形体最外面的矩形左上角y坐标</param>
        /// <param name="width">矩形最外面的矩形宽</param>
        /// <param name="length">矩形顶部面的矩形长</param>
        /// <param name="height">矩形最外面的矩形高</param>
        /// <param name="UpColor">正对面的颜色</param>
        /// <param name="Graphics">Graphics对象</param>
        public void DrawRectangle3D(int x, int y, int width, int length, int height, Color UpColor, Graphics Graphics)
      
{
            int _x1 = 0;
            int _y1 = 0;
            SolidBrush Brush;
            ChangeXY(out _x1, out  _y1, x, y, length);
            Pen blackPen = new Pen(Color.Black, 2);
            Point point1 = new Point();
            Point point2 = new Point();
            Point point3 = new Point();
            Point point4 = new Point();
            Point point5 = new Point();
            Point point6 = new Point();
            Point point7 = new Point();
            Point point8 = new Point();
            Brush = new SolidBrush(UpColor);
            int[] rgb = new int[3];
            rgb[0] = Convert.ToInt32(UpColor.R);
            rgb[1] = Convert.ToInt32(UpColor.G);
            rgb[2] = Convert.ToInt32(UpColor.B);
            float[] hls = new float[3];
            Color RightColor;
            RgbToHsl(rgb[0], rgb[1], rgb[2], ref hls[0], ref hls[1], ref hls[2]);
            hls[1] -= 20f;
            HslToRgb(ref rgb[0], ref rgb[1], ref rgb[2], hls[0], hls[1], hls[2]);
            RightColor = Color.FromArgb(rgb[0], rgb[1], rgb[2]);
            Color TopColor;
            RgbToHsl(rgb[0], rgb[1], rgb[2], ref hls[0], ref hls[1], ref hls[2]);
            hls[1] -= 20f;
            HslToRgb(ref rgb[0], ref rgb[1], ref rgb[2], hls[0], hls[1], hls[2]);
            TopColor = Color.FromArgb(rgb[0], rgb[1], rgb[2]);
            rgb[0] = Convert.ToInt32(UpColor.R);
            rgb[1] = Convert.ToInt32(UpColor.G);
            rgb[2] = Convert.ToInt32(UpColor.B);
            hls = new float[3];
            Brush = new SolidBrush(UpColor);
            if (DrawGraphics == null)
                AddNumber = 1;
            if (AddNumber <= 0) AddNumber = 1;
            for (int i = y + height, j = _y1 + height; j >= _y1 && i >= y; i -= AddNumber, j -= AddNumber) //实现着色渐变
            {
                if (i != y + height)
                {
                    HslToRgb(ref rgb[0], ref rgb[1], ref rgb[2], hls[0], hls[1], hls[2]);
                    UpColor = Color.FromArgb(rgb[0], rgb[1], rgb[2]);
                }
                point1 = new Point(x, i);
                point2 = new Point(x + width, i);
                point5 = new Point(_x1, j);
                point6 = new Point(_x1 + width, j);
                if (j - AddNumber < _y1)
                {
                    point3 = new Point(_x1, _y1);
                    point4 = new Point(_x1 + width, _y1);
                }
                else
                {
                    point3 = new Point(_x1, j - AddNumber);
                    point4 = new Point(_x1 + width, j - AddNumber);
                }
                if (i - AddNumber < y)
                {
                    point7 = new Point(x, y);
                    point8 = new Point(x + width, y);
                }
                else
                {
                    point7 = new Point(x, i - AddNumber);
                    point8 = new Point(x + width, i - AddNumber);
                }
                Point[] curvePointsUp = { point1, point2, point8, point7, };//正对面的点集
                Point[] curvePointsRight = { point2, point8, point4, point6, };//右部面的点集
                Point[] curvePointsTop = { point7, point8, point4, point3, };//顶部面的点集
                Brush = new SolidBrush(UpColor);
                if(this.dynamicDraw)
                    DrawGraphics.FillPolygon(Brush, curvePointsUp);
                Graphics.FillPolygon(Brush, curvePointsUp);
                Brush = new SolidBrush(RightColor);
                if(this.dynamicDraw)
                    DrawGraphics.FillPolygon(Brush, curvePointsRight);
                Graphics.FillPolygon(Brush, curvePointsRight);
                Brush = new SolidBrush(TopColor);
                if(this.dynamicDraw)
                    DrawGraphics.FillPolygon(Brush, curvePointsTop);
                Graphics.FillPolygon(Brush, curvePointsTop);
                RgbToHsl(rgb[0], rgb[1], rgb[2], ref hls[0], ref hls[1], ref hls[2]);
                hls[1] -= 100.0f * 1 / (height * 1.0f) * AddNumber;
            }
            if(this.dynamicDraw)
                DrawGraphics.Dispose();
            blackPen.Dispose();
            Graphics.Dispose();
            Brush.Dispose();
        }
目前我是这么实现的,画矩形


饼图3d.gif

2009-4-24 13:22:30
顶楼上,呵呵,很强大啊
2009-4-24 13:53:35
先试下看
2009-4-24 13:56:35
只贴了关键代码?编译不过。。
dynamicDraw,DrawGraphics等一堆变量和函数找不到定义。。
而且,现在实现的是矩形的每个面是用一个颜色填充的吧?
用3张图片代替单纯的颜色应该怎么实现呢?
请教~~
2009-4-24 14:40:47
恩,有了这些关键代码,相信你的实力应该可以搞定的。
还有你说的图片,我很想知道为什么要用图片,本来画3D就已经够慢了,要是再用上图片就更慢了。
这只是我的理解,再沟通。      
      
protected bool dynamicDraw = true;  //是否需要动态画图效果,你可以把它注释掉,这个是用来控制生成图的效果
2009-4-24 14:54:59
2#wt0731
强!看来要向你好好学习下。。。以后多多关照。。。
2009-4-24 14:58:58
好东西学习一下
2009-4-24 15:09:37
学习一下
2009-4-27 14:10:36

QUOTE:

恩,有了这些关键代码,相信你的实力应该可以搞定的。
还有你说的图片,我很想知道为什么要用图片,本来画3D就已经够慢了,要是再用上图片就更慢了。
这只是我的理解,再沟通。      
      
protected bool d ...
wt0731 发表于 2009-4-24 14:40
首先,十分感谢您的回答
我是想做一个3D效果的菜单,类似于多普达S1的Touch Flow,3D菜单的效果:


05.gif


我现在只是猜测,这个是用Direct 3D实现的,并不知道应该怎么做
如果您有其他的实现方法,请指教,我现在是一头雾水。。
谢谢~~
2009-4-27 14:31:28
你说的效果,暂时没有思路,我想简单了
希望高手出来给你解决下。


旋转.gif

2009-4-27 15:18:44
LS的那个“旋转.gif"中显示的那个插件我也下载安装了,是您做的吗?
那个插件做的真好,很想知道是怎么实现的。。

要是有源码的话,能有偿给我一份吗?代价好商量。。
2009-4-27 15:22:52
见笑了,我,还需要很长一段路要走!
是国外一个公司做的。
2009-4-27 16:00:20
唉,现在公司赶鸭子上架,要我基于一个已经成熟Windows Mobile的整机方案,搞一个产品出来。
我以前做过单片机和MTK,对Windows Mobile是一无所知啊,公司里又没有做过Windows Mobile的人,从应用开发到系统定制,全是现学现卖,一个多月了,进展不大,搞得七荤八素,郁闷的不行。。
2009-4-27 17:53:30
呵呵,加油!
如果暂时缺乏思路的话,可以找些相关的资料看看,推荐看看webcast,项目的话可以看下Mobile LOB-加速器(Mobile Line of Business )。
我们也可以交流下,如果你愿意的话。
2009-4-28 16:21:16
[i=s] 本帖最后由 Special_Lin 于 2009-4-28 16:33 编辑

呵呵,类似11楼“旋转.gif”那个应用的效果可以初步实现了,以StretchBlt为核心函数,实现一个梯形打印函数:

CODE:

//梯形方向
typedef enum
{
        TRIP_DIRECT_H = 0,
        TRIP_DIRECT_H_CONVERSE,
        TRIP_DIRECT_V,
        TRIP_DIRECT_V_CONVERSE,
}ENUM_TRIP_DIRECT;
/************************************************************
* FUNCTION
*   StretchRectToTrip
* DESCRIPTION
*   将矩形拉伸为梯形
* PARAMETERS
*       hdc:                        目标DC(梯形所在DC)
*        x1, y1-x4, y4:        矩形的四个顶点(顺序为左上,右上,左下,右下)
*        hdcMem:                        源DC(矩形所在DC)
*        iStartX, iStartY, nWidth, nHeight:        矩形起始位置和宽高
* RETURNS
*   void
* AUTHOR:
*        Lynn
*************************************************************/
void StretchRectToTrip(HDC hdc, int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4,
                                        HDC hdcMem, int iStartX, int iStartY, int nWidth, int nHeight)
{
        ENUM_TRIP_DIRECT eDirect;
        int x, y, w, h, dx, dy;                //目标DC
        int sx, sy;                                        //源DC

        //获取梯形方向
        if(y1 == y2 && y3 == y4 && x1 == x3 && x2 == x4)
        {
                //矩形,直接打印
                StretchBlt(hdc, x1, y1, x4 - x1 + 1, y4 - y1 + 1,
                        hdcMem, iStartX, iStartY, nWidth, nHeight, SRCCOPY);
                return;
        }
        if(y1 == y2 && y3 == y4)
        {
                if(x1 >= x3 && x2 <= x4)
                        eDirect = TRIP_DIRECT_H;
                else
                        eDirect = TRIP_DIRECT_H_CONVERSE;
        }
        else if(x1 == x3 && x2 == x4)
        {
                if(y1 >= y2 && y3<= y4)
                        eDirect = TRIP_DIRECT_V;
                else
                        eDirect = TRIP_DIRECT_V_CONVERSE;
        }
        else
        {
                //目标图形不是梯形,不能处理
                return;
        }

        //根据不同的方向做图像处理
        if(eDirect == TRIP_DIRECT_H || eDirect == TRIP_DIRECT_H_CONVERSE)
        {
                //梯形高度
                h = y3 - y1;

                //逐行处理
                for(y = 0; y < h; y++)
                {
                        //计算该行的起始X坐标
                        if(eDirect == TRIP_DIRECT_H)
                        {
                                x = x1 - (y * (x1 - x3) / h);
                                dx = x2 + (y * (x4 - x2) / h);
                        }
                        else
                        {
                                x = x1 + (y * (x1 - x3) / h);
                                dx = x3 - (y * (x2 - x4) / h);
                        }
                        //计算矩形要Strecth过来的y坐标
                        sy = y * nHeight / h ;
                        //处理一行
                        StretchBlt(hdc, x, y + y1, dx - x + 1, 1, hdcMem, iStartX, sy, nWidth, 1, SRCCOPY);
                }
        }
        else
        {
                //梯形高度
                w = x2 - x1;

                //逐行处理
                for(x = 0; x < w; x++)
                {
                        //计算列的起始Y坐标
                        if(eDirect == TRIP_DIRECT_V)
                        {
                                y = y1 -  (x * (y1 - y2) / w);
                                dy = y3 + (x * (y4 - y3) / w);
                        }
                        else
                        {
                                y = y1 + (x * (y2 - y1) / w);
                                dy = y3 - (x * (y3 - y4) / w);
                        }
                        //计算矩形要Strecth过来的X坐标
                        sx = x * nWidth / w;
                        //处理一列
                        StretchBlt(hdc, x + x1, y, 1, dy - y + 1, hdcMem, sx, iStartY, 1, nHeight, SRCCOPY);
                }

        }
}
这样使用:

CODE:

void DrawScreen(int x1, int y1, int x2, int y2, int x3, int y3, int x4, int y4, HBITMAP hImage)
{
        HDC hdc, hdcMem, hdcDoubleBuffer;
        HBITMAP bmpDoubleBuffer;
       
        //获取当前屏幕DC并创建设备相关的临时DC
        hdc = GetDC(hWnd);
        hdcMem = CreateCompatibleDC(hdc);
        hdcDoubleBuffer = CreateCompatibleDC(hdc);
        bmpDoubleBuffer = CreateCompatibleBitmap(hdc,240,320);
       
        //清空内存缓冲DC
        SelectObject(hdcDoubleBuffer, bmpDoubleBuffer);
        SelectObject(hdcDoubleBuffer, GetStockObject(BLACK_BRUSH));
        Rectangle(hdcDoubleBuffer, 0, 0, 240, 320);
       
        //打印左侧窗体到内存缓冲DC
        SelectObject(hdcMem, hImage);
        StretchRectToTrip(hdcDoubleBuffer,x1, y1, x2, y2, x3, y3, x4, y4,hdcMem, 0, 0, 240, 320);
       
        //复制到屏幕DC
        BitBlt(hdc, 0, 0, 240, 320, hdcDoubleBuffer, 0, 0, SRCCOPY);
       
        DeleteDC(hdc);
        DeleteDC(hdcMem);
        DeleteDC(hdcDoubleBuffer);
        DeleteObject(bmpDoubleBuffer);
}
将屏幕位图传进来,计算好中央矩形/两侧梯形的坐标位置就可以了。测试过了,速度还可以,没有那个软件流畅,但是也不算慢。
大概就是这样,应该还有很多优化的余地。比如,备份DC等。也有美化、去掉边缘锯齿的方法,就是在StretchRectToTrip中加入边缘像素点向底背景的RBG色过度的处理,不知道对效率影响大不大,还没试过。
2009-4-28 17:01:01
好强大,学习
2009-4-29 11:22:14
很好很强大,学习学习
2009-4-29 13:15:25
想做3D效果还用GDI画太慢了吧
2009-4-29 17:33:09
大家是否考虑用OPENGL ES呢
2009-4-30 11:00:02
LS的两位,能给出具体的例子吗
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++语言画矩形 "_AFXDLL" "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\Test.rc"" Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8A.tmp" with contents [ /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"Debug/Test.pch" /Yu"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\MainFrm.cpp" "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\Picdlg.cpp" "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\Test.cpp" "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\TestDoc.cpp" "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\TestView.cpp" ] Creating command line "cl.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8A.tmp" Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8B.tmp" with contents [ /nologo /MDd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_AFXDLL" /D "_MBCS" /Fp"Debug/Test.pch" /Yc"stdafx.h" /Fo"Debug/" /Fd"Debug/" /FD /GZ /c "E:\E03教学\2011下半年\图形学\计算机图形学基础教程(Visual C++版)\第五章\案例9-二维基本几何变换算法\StdAfx.cpp" ] Creating command line "cl.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8B.tmp" Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8C.tmp" with contents [ /nologo /subsystem:windows /incremental:yes /pdb:"Debug/Test.pdb" /debug /machine:I386 /out:"Debug/Test.exe" /pdbtype:sept ".\Debug\MainFrm.obj" ".\Debug\Picdlg.obj" ".\Debug\StdAfx.obj" ".\Debug\Test.obj" ".\Debug\TestDoc.obj" ".\Debug\TestView.obj" ".\Debug\Test.res" ] Creating command line "link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP8C.tmp" <h3>Output Window</h3> Compiling resources... Compiling... StdAfx.cpp Compiling... MainFrm.cpp Picdlg.cpp Test.cpp TestDoc.cpp TestView.cpp Generating Code... Linking...

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值