VC中的OpenGL制作动画 我想用OpenGL做一个机器臂的运动仿真,想把它的运动记录下来,现在打算是运动过程生成AVI格式的文件,我再编一个播放器的对话框。 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 直接使用OpenGL做动画还是比较复杂的,建议使用针对OpenGL的封装库,比如Open Inventor. 这个还真没有了解过,我在看看Open Inventor是怎么回事,和OpenGL对比后我再看看用不用更改我的方案。谢谢你 请问,你要程序是写论文,还是工作需要?这种程序可以用OpenGL写.也可以用AVI保存。(用MFC 加OpenGL). 你是本科还是研究生?这个程序可以用MFC 做框架。再用OpenGL画出机械.有现成的类完成AVI的输出。 OpenGL方面是不太难,关键是看你用的是怎么样的机械。 你用inventor,ug ,soliworks做吧, 不要考虑自己做,太难了。运动仿真很难。哥是搞这方面开发的。 你老师说简单,你问他怎么做。 现在的导师都是sb 我是本科生,机械的,老师还准备让我一直做下去,要是好的话就可以当做毕业设计做的。我现在就是用的单文档的MFC框架,OpenGL绘制并且控制机械的运动。现在主要是把路走走,看能不能走通,目前的难点是怎么把运动的动作记录下来,也就是回放动作过程,以前想着是建立数据库,我还没接触过VC的数据库,因此就想把过程通过程序输出,再通过控件显示。现在还不知道那个类能实现AVI输出。 新运动时,把上次屏幕复制为bmp,加到AVI中。 要是做软件。 应该如此 比如你用鼠标拖动手,手左一些运动(因为关节等约束,手只能做半圆周转动)。这里面涉及到1 三维模型的表示 建立 选择,图形的约束求解等等。这种情况想都不要想,灰常的难。要是自己学,avi问题就当不存在(很简单),vc的数据库知识估计够你折腾的。但是相比上面根本就是小儿科,你学都不知道从哪来学。 这个就是机械的仿真运动,Bmp加入到AVI中是要用转换软件吗?我用的是约束方程的建立来实现机械的运动,现在我的机械零件能随着我的按键做一系列运动,现在就回放卡着了,有一个星期了,我在网上也没找到相关的资料,我有点怀疑自己的思路有问题了,看了上面liangjinjing的回答,我发现我的思路还是能实现的,不过还是没有代码可以参考,这样就有点难了,我前面的程序都是参考别人的代码来编程的,要是没有相似功能的代码我还真编不出来的,我也是过完年在课余时间学习VC的。因此说avi在会用的人眼中还是比较简单的,相对我而言就有点难度了,呵呵。 发一个例子做代码,希望对你有用。CPP 文件#include "stdafx.h"#include "3DEditor.h"#include "AVICapture.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE[]=__FILE__;#define new DEBUG_NEW#endif//////////////////////////////////////////////////////////////////////// Construction/Destruction//////////////////////////////////////////////////////////////////////AVICapture::AVICapture() : width(-1), height(-1), frameRate(30.0f), frameCounter(0), capturing(false), aviFile(NULL), aviStream(NULL), compAviStream(NULL), image(NULL){ AVIFileInit();}AVICapture::~AVICapture(){ cleanup(); AVIFileExit();}bool AVICapture::start(CString filename, int w, int h, float fps){ if (capturing) return false; width = w; height = h; frameRate = fps; if (HIWORD(VideoForWindowsVersion()) < 0x010a) { // We need to be running on version 1.1 or later return false; } // Compute the width of a row in bytes; pad so that rows are aligned on // 4 byte boundaries. int rowBytes = (width * 3 + 3) & ~0x3; image = new unsigned char[rowBytes * height]; HRESULT hr = AVIFileOpen(&aviFile, filename, OF_WRITE | OF_CREATE, NULL); if (hr != AVIERR_OK) { MessageBox(NULL,"Erroring creating avi file for capture.","ERROR",MB_OK); return false; } AVISTREAMINFO info; ZeroMemory(&info, sizeof info); info.fccType = streamtypeVIDEO; info.fccHandler = 0; info.dwScale = 1; info.dwRate = (DWORD) frameRate; info.dwSuggestedBufferSize = rowBytes * height; SetRect(&info.rcFrame, 0, 0, width, height); hr = AVIFileCreateStream(aviFile, &aviStream, &info); if (hr != AVIERR_OK) { MessageBox(NULL,"Error creating AVI stream.","ERROR",MB_OK); cleanup(); return false; } // Display a dialog to allow the user to select compression options AVICOMPRESSOPTIONS options; AVICOMPRESSOPTIONS* arrOptions[1] = { &options }; ZeroMemory(&options, sizeof options); if (!AVISaveOptions(NULL, 0, 1, &aviStream, (LPAVICOMPRESSOPTIONS*) &arrOptions)) { // The user either clicked on cancel or there was an error cleanup(); return false; } hr = AVIMakeCompressedStream(&compAviStream, aviStream, &options, NULL); if (hr != AVIERR_OK) { MessageBox(NULL,"Error creating compressed AVI stream.", "ERROR",MB_OK); cleanup(); return false; } BITMAPINFOHEADER bi; ZeroMemory(&bi, sizeof bi); bi.biSize = sizeof bi; bi.biWidth = width; bi.biHeight = height; bi.biPlanes = 1; bi.biBitCount = 24; bi.biCompression = BI_RGB; bi.biSizeImage = rowBytes * height; bi.biXPelsPerMeter = 0; bi.biYPelsPerMeter = 0; bi.biClrUsed = 0; bi.biClrImportant = 0; hr = AVIStreamSetFormat(compAviStream, 0, &bi, sizeof bi); if (hr != AVIERR_OK) { MessageBox(NULL,"AVIStreamSetFormat failed.","ERROR",MB_OK); cleanup(); return false; } capturing = true; frameCounter = 0; return true;}bool AVICapture::end(){ capturing = false; cleanup(); return true;}bool AVICapture::captureFrame(){ if (!capturing) return false; // Get the dimensions of the current viewport int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); int x = viewport[0] + (viewport[2] - width) / 2; int y = viewport[1] + (viewport[3] - height) / 2; glReadPixels(x, y, width, height, GL_BGR_EXT, GL_UNSIGNED_BYTE, image); int rowBytes = (width * 3 + 3) & ~0x3; LONG samplesWritten = 0; LONG bytesWritten = 0; HRESULT hr = AVIStreamWrite(compAviStream, frameCounter, 1, image, rowBytes * height, AVIIF_KEYFRAME, &samplesWritten, &bytesWritten); if (hr != AVIERR_OK) { MessageBox(NULL,"AVIStreamWrite failed on frame.", "ERROR",MB_OK); return false; } // printf("Writing frame: %d %d => %d bytes\n", // frameCounter, rowBytes * height, bytesWritten); frameCounter++; return true;}void AVICapture::cleanup(){ if (aviStream != NULL) { AVIStreamRelease(aviStream); aviStream = NULL; } if (compAviStream != NULL) { AVIStreamRelease(compAviStream); compAviStream = NULL; } if (aviFile != NULL) { AVIFileRelease(aviFile); aviFile = NULL; } if (image != NULL) { delete[] image; image = NULL; }}int AVICapture::getWidth() const{ return width;}int AVICapture::getHeight() const{ return height;}float AVICapture::getFrameRate() const{ return frameRate;}H 文件#if !defined(AFX_AVICAPTURE_H__703E89CE_2A4E_4DD7_8B80_8AF78597D8B8__INCLUDED_)#define AFX_AVICAPTURE_H__703E89CE_2A4E_4DD7_8B80_8AF78597D8B8__INCLUDED_#if _MSC_VER > 1000#pragma once#endif // _MSC_VER > 1000#include <vfw.h>class AVICapture {public: AVICapture(); virtual ~AVICapture(); bool start(CString filename, int w, int h, float fps); bool end(); bool captureFrame(); int getWidth() const; int getHeight() const; float getFrameRate() const; private: void cleanup(); private: int width; int height; float frameRate; int frameCounter; bool capturing; PAVIFILE aviFile; PAVISTREAM aviStream; PAVISTREAM compAviStream; unsigned char* image;};#endif // !defined(AFX_AVICAPTURE_H__703E89CE_2A4E_4DD7_8B80_8AF78597D8B8__INCLUDED_) 把上面的CPP,H。直接加入到你的程序中,加工一下,应该可以用。(平台为MFC SDI add OpenGL VC6.0)祝你成功。 数据库方面用MFC ODBC。比较方便。用SQL语言直接驱动数据库。(看看书,对你来说应该不太难) liangjinjing 你好,能不能把完整的例子发过来,我把你的代码加入我的程序中后,经过修改也能编译通过了,但是没有出现理想的效果,可能是我学艺不精吧,我还没看出来压缩的数据存放到那个位子,在我的程序目录下还没有发现。谢谢。 完整例子已发至你邮箱。耐心查看一下使用方法。我写的机械的例子你也可以看一下。Liang_Jin_Jing. 为什么说:"View正常的PostNcDestroy实现是使用delete this销毁View"? 关于文件读写的问题,在线等待!!!!!! 如果更改指定文件夹名 [网络服务器编程问题]怎么样读取数据采集卡数据的数据并允许客户端查看? 串口通讯问题!!!!! 各位大侠,怎样才能随心所欲地控制窗口的大小以及只要客户区? 图像噪音如何处理? 请教有关数据库的问题! 请问setAudio怎么用啊 在DCOM的使用过程中,能不能开发监控程序来监视哪个方法是由哪个用户来调用的? CSerialPort的应用问题! 关于VS2010与mscomm控件的怨念,紧急求助。。
运动仿真很难。
哥是搞这方面开发的。
你老师说简单,你问他怎么做。 现在的导师都是sb
我现在就是用的单文档的MFC框架,OpenGL绘制并且控制机械的运动。现在主要是把路走走,看能不能走通,目前的难点是怎么把运动的动作记录下来,也就是回放动作过程,以前想着是建立数据库,我还没接触过VC的数据库,因此就想把过程通过程序输出,再通过控件显示。现在还不知道那个类能实现AVI输出。
要是做软件。 应该如此 比如你用鼠标拖动手,手左一些运动(因为关节等约束,手只能做半圆周转动)。这里面涉及到1 三维模型的表示 建立 选择,图形的约束求解等等。这种情况想都不要想,灰常的难。
要是自己学,avi问题就当不存在(很简单),vc的数据库知识估计够你折腾的。但是相比上面根本就是小儿科,你学都不知道从哪来学。
我用的是约束方程的建立来实现机械的运动,现在我的机械零件能随着我的按键做一系列运动,现在就回放卡着了,有一个星期了,我在网上也没找到相关的资料,我有点怀疑自己的思路有问题了,看了上面liangjinjing的回答,我发现我的思路还是能实现的,不过还是没有代码可以参考,这样就有点难了,我前面的程序都是参考别人的代码来编程的,要是没有相似功能的代码我还真编不出来的,我也是过完年在课余时间学习VC的。
因此说avi在会用的人眼中还是比较简单的,相对我而言就有点难度了,呵呵。
CPP 文件
#include "stdafx.h"
#include "3DEditor.h"
#include "AVICapture.h"#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////AVICapture::AVICapture() :
width(-1),
height(-1),
frameRate(30.0f),
frameCounter(0),
capturing(false),
aviFile(NULL),
aviStream(NULL),
compAviStream(NULL),
image(NULL)
{
AVIFileInit();
}
AVICapture::~AVICapture()
{
cleanup();
AVIFileExit();
}
bool AVICapture::start(CString filename,
int w, int h,
float fps)
{
if (capturing)
return false; width = w;
height = h;
frameRate = fps; if (HIWORD(VideoForWindowsVersion()) < 0x010a)
{
// We need to be running on version 1.1 or later
return false;
} // Compute the width of a row in bytes; pad so that rows are aligned on
// 4 byte boundaries.
int rowBytes = (width * 3 + 3) & ~0x3;
image = new unsigned char[rowBytes * height]; HRESULT hr = AVIFileOpen(&aviFile,
filename,
OF_WRITE | OF_CREATE,
NULL);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"Erroring creating avi file for capture.","ERROR",MB_OK);
return false;
} AVISTREAMINFO info;
ZeroMemory(&info, sizeof info);
info.fccType = streamtypeVIDEO;
info.fccHandler = 0;
info.dwScale = 1;
info.dwRate = (DWORD) frameRate;
info.dwSuggestedBufferSize = rowBytes * height;
SetRect(&info.rcFrame, 0, 0, width, height);
hr = AVIFileCreateStream(aviFile, &aviStream, &info);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"Error creating AVI stream.","ERROR",MB_OK);
cleanup();
return false;
} // Display a dialog to allow the user to select compression options
AVICOMPRESSOPTIONS options;
AVICOMPRESSOPTIONS* arrOptions[1] = { &options };
ZeroMemory(&options, sizeof options); if (!AVISaveOptions(NULL, 0, 1, &aviStream,
(LPAVICOMPRESSOPTIONS*) &arrOptions))
{
// The user either clicked on cancel or there was an error
cleanup();
return false;
} hr = AVIMakeCompressedStream(&compAviStream, aviStream, &options, NULL);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"Error creating compressed AVI stream.", "ERROR",MB_OK);
cleanup();
return false;
} BITMAPINFOHEADER bi;
ZeroMemory(&bi, sizeof bi);
bi.biSize = sizeof bi;
bi.biWidth = width;
bi.biHeight = height;
bi.biPlanes = 1;
bi.biBitCount = 24;
bi.biCompression = BI_RGB;
bi.biSizeImage = rowBytes * height;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0; hr = AVIStreamSetFormat(compAviStream, 0, &bi, sizeof bi);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"AVIStreamSetFormat failed.","ERROR",MB_OK);
cleanup();
return false;
} capturing = true;
frameCounter = 0; return true;
}
bool AVICapture::end()
{
capturing = false;
cleanup(); return true;
}
bool AVICapture::captureFrame()
{
if (!capturing)
return false; // Get the dimensions of the current viewport
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport); int x = viewport[0] + (viewport[2] - width) / 2;
int y = viewport[1] + (viewport[3] - height) / 2;
glReadPixels(x, y, width, height,
GL_BGR_EXT, GL_UNSIGNED_BYTE,
image); int rowBytes = (width * 3 + 3) & ~0x3; LONG samplesWritten = 0;
LONG bytesWritten = 0;
HRESULT hr = AVIStreamWrite(compAviStream,
frameCounter,
1,
image,
rowBytes * height,
AVIIF_KEYFRAME,
&samplesWritten,
&bytesWritten);
if (hr != AVIERR_OK)
{
MessageBox(NULL,"AVIStreamWrite failed on frame.", "ERROR",MB_OK);
return false;
} // printf("Writing frame: %d %d => %d bytes\n",
// frameCounter, rowBytes * height, bytesWritten);
frameCounter++; return true;
}
void AVICapture::cleanup()
{
if (aviStream != NULL)
{
AVIStreamRelease(aviStream);
aviStream = NULL;
}
if (compAviStream != NULL)
{
AVIStreamRelease(compAviStream);
compAviStream = NULL;
}
if (aviFile != NULL)
{
AVIFileRelease(aviFile);
aviFile = NULL;
}
if (image != NULL)
{
delete[] image;
image = NULL;
}
}
int AVICapture::getWidth() const
{
return width;
}int AVICapture::getHeight() const
{
return height;
}float AVICapture::getFrameRate() const
{
return frameRate;
}
H 文件
#if !defined(AFX_AVICAPTURE_H__703E89CE_2A4E_4DD7_8B80_8AF78597D8B8__INCLUDED_)
#define AFX_AVICAPTURE_H__703E89CE_2A4E_4DD7_8B80_8AF78597D8B8__INCLUDED_#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <vfw.h>class AVICapture
{
public:
AVICapture();
virtual ~AVICapture(); bool start(CString filename, int w, int h, float fps);
bool end();
bool captureFrame(); int getWidth() const;
int getHeight() const;
float getFrameRate() const; private:
void cleanup(); private:
int width;
int height;
float frameRate;
int frameCounter;
bool capturing;
PAVIFILE aviFile;
PAVISTREAM aviStream;
PAVISTREAM compAviStream;
unsigned char* image;
};#endif // !defined(AFX_AVICAPTURE_H__703E89CE_2A4E_4DD7_8B80_8AF78597D8B8__INCLUDED_)
祝你成功。