第九十九讲 使用MFrame3D(1)

在上一讲里面我们终于将拖了很久的MFrame3D框架结束,里面的内容相对于初学C++的同学来说可能有些过多,而且我也权当大家都能够理解,所以就只是在程序中作了一些简单的注释便没有多加细说,因为我相信大家能够看懂,当然如果真看不懂也不是大家的问题,那一定是我没有表达清楚,原谅我不是一个善于说教的人吧。

当然,于一个框架来说,我们或许不需要知道这个框架是怎么实现的,他的底部细节如何我们可以不用知道,因为作为他的使用者我们只需要知道该怎么用就好,所以,就算没有看懂Mrame3D框架也无所谓,我们一样可以直接使用他,在上一讲中我们简单的画了一个幅旋转的3维图形,当然那是我一开始就将他写进框架里面作为一个默认程序而已,所以谈不上使用,更谈不上演示的效果,那么,今天我们就来看看怎么使用这个框架。

在这一讲里面我们来研究一下数学问题?哦…………什么?我们没看错吧,这是在谈C++编程,怎么就研究起数学问题来了呢?可能有同学看到这里的时候会很惊讶的发出这声疑问,ok,那我来解释一下吧,3D图形不用我说大家可能都很快的想起了3D游戏或者一些科技仿真,好吧,既然大家能够想到这些那么就应该明白这一切都和数学脱不了关系,科技仿真更不用说了,那么很多同学学习C++大概会是向往游戏上发展,而游戏同样离不开数学知识,比如那些打斗场景的打击感,各种物体的碰撞这些都是通过数学来计算出来的。当然,我数学知识有限,这里似乎给不了大家什么深奥的东西,也就简单滴说一下吧,算是带大家入门,之后的深入了解还是得大家。

好吧,我们进入主题,我们今天研究空间曲线,一线空间螺旋的线,为了简单,我们权当这条线是螺旋成一个圆柱的形状,如果我们假设他是水平的,那么我们可以得到这条曲线的参数方程表达式:
//==================================
{

x = x(t);



y = y(t);



z = z(t);


}
//==================================

接触过高等数学的同学应该都明白,这里t为参数,如果这是动态的,那么我们可以认为t就是时间,我们可以再假设这条曲线的旋转速度角速度 为w,线速度为v,由于我们假设他是沿水平方向延伸,所以我们就可以将上面的的表达式演变成下面这样:
//==================================
{

x = v*t;



y = r*cos(w*t);



z = r*sin(w*t);


}
//=================================

这里的r是螺旋的出来的圆的半径,知道这些后,我们建模的时候就很轻松了,ok,下面我们用代码来模拟这条曲线在空间的移动旋转。

(1) 从MDataBase派生一个数据类出来,我们用来管理数据,这个类名暂且就叫dataLine吧:
//=================================
class DataLine :public MDataBase{
public:

DataLine(){

m_line_point.clear();


m_radio = 2.0;


m_w = 0.0;


m_line_point.push_back(MVector3F(0.0, 0.0, m_radio));


}

void update(){

InvalidateRect((HWND)GetModuleHandle(nullptr), nullptr, false);


}

std::vector<MVector3F>m_line_point;



float m_radio;



float m_tatol_w;


};


//=====================================

我简单的介绍一下这个数据类:

m_line_point,表示线上的点,因为不管是什么,当我们都可以用一系列的点去表示。

m_radio,是上面我们所说的螺旋出来的圆的半径,这里我们就将他设置为2.0吧。

m_totle_w,用来记录线所旋转过的角度

update()这个是MDataBase里面声明的一个纯虚函数,我们不管用与不用这个函数都必须得重写,这里我们就假设他的作用就只是为了让界面刷新吧。

(2)从MWindow3D类派生出我们自己的3D类,这里我就简单的将这个类的名字定位Line3D;


//=================================
class Line3D: public MWindow3D{
public:

Line3D(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR

szCmdLine,
int iCmdShow, const std::wstring&

title,

const std:: wstring&

wndname);


protected:

void DrawScreenGL();



float m_w;



float m_v;


};
//=================================


由于我们没有什么特别的东西需要初始化,所以我们这里只需要简单重写DrawScreenGL()函数即可,所以也相当的简单了,m_w表示螺旋线的角速度,m_v表示线速度,现在我们可以来看下实现,关于实现也是很简单的:
//=================================
Line3D::Line3D(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine,

int iCmdShow, const std::wstring&

title, const std::wstring&

wndname)

:Window3D(hInstance, hPreInstance, szCmdLine, iCmdShow, title, wndname)
{

m_w = 10.0;



m_v = 1.0;


}



void Line3D::DrawScreenGL(){

DataLine* _data = dynamic_cast<DataLine*>(getData());



glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);



glLoadIdentity();



glPushMatrix();



glTranslatef(-10.0f, 0.0f, -20.0f);


glLineWidth(1);



glBegin(GL_LINE_STRIP);



glColor3f(1.0, 0.0, _data->m_radio);



glVertex3f(0.0, 0.0, _data->m_radio);



auto it = _data->m_line_point.begin();



while (it != _data->m_line_point.end()){

glVertex3f(it->m_x, it->m_y,it->m_z);


++it;


}

glEnd();



glPopMatrix();



MVector3F point;



MVector3F lastpoint = _data->m_line_point.at(_data->m_line_point.size() – 1);



point.m_x = lastpoint.m_x + m_v*10.0 / 1000.0;



_data->m_tatol_w += m_w*10.0 / 1000.0;

//由于在底层实现了一个定时器,定时间隔为10ms,所以这里就得使用10/1000转换为s

point.m_y = _data->m_radio*std::cos(_data->m_tatol_w);



point.m_z = _data->m_radio*std::sin(_data->m_tatol_w);



_data->m_line_point.push_back(point);


}

//==========================

关于opengl的东西这里不作介绍,有兴趣的东西可以自己去研究,那么上面除了opengl的函数调用外,其他的没什么好稀奇的,唯有后面一段就是说当我们画完一次屏幕后我们马上更新线下一处的位置,然后保存数据,留待接下来使用。

接下来就是驱动程序,几乎都不用修改的。

//==========================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, char* cmdline,
int showcmd){


try{

MWindow* w = new Window;


Line3D w3d(hInstance, hPreInstance, cmdline, showcmd, L"

Test"

, L"

Test"

);


w3d.Attach(w);


DataLine data;


w3d.AddData(&

data);


w3d.CreateGLWindow(750, 450, 32, false);


w->run();


delete w;


return 0;


}

catch (const wchar_t* s){

MessageBox(nullptr, s, L"

Error"

, MB_OK);


}
}

//=================================

运行程序我们发现线和我们想象中的一样旋转着前进。

第九十九讲  使用MFrame3D(1)

总结一下,如果说我们在看实现框架的时候觉得很烦,那么我们现在使用的时候是不是觉得很方便简单呢?


==============================
回复D直接查看目录,回复相应的数字查看对应章节


原文始发于微信公众号(

C/C++的编程教室

):第九十九讲 使用MFrame3D(1)

|

发表评论