计算机图形学opengl3D
vczhfans GEEK之路 6月5日
环境:VS2010
编程语言:C语言
调用API:glut库
原文地址:https://mp.weixin.qq.com/s/duQEXHu4v_z2xxP64BSUCw
作者:vczhfans
实现功能:
三维坐标建立;
opengl文本显示鼠标当前位置;
点画线,这个没有自己用算法实现,用的opengl中GL_LINES加两顶点画
线画面
面画体
键盘控制自己画的体,wasd前后左右 space上 c下
简单动画,画的魔方自己通过定时器旋转,angle增
效果: 3D .gif
1.点画线
2.线画面
3.面画体
4.坐标文本显示
调用的别人写好的opengl显示文本
然后我与要做的就是,鼠标事件,获取鼠标坐标,记录,移动操作点,送进字符串char*,显示就OK了
opengl3D用户交互
glutKeyboardFunc(keyboard); //响应键盘
glutMouseFunc(myMouse); //响应鼠标
glutTimerFunc(1000,timerFunc,1); //定时器
(sleep,*Func,ID)
主程序:
思路雷同2D吧,无非2D坐标变3D坐标
收获:int转char,char送进char*
对旋转平移有了更深的认识
opengl旋转右手坐标系:
glRotatef(angle,dx,dy,dz);
0.当前模型中心点为参考点
1.握住旋转向量
2.拇指指向向量正方向
3.其余手指指向即为旋转方向
4.angle必须为int
opengl平移:
glTranslatef(dx,dy,dz);
当前模型中心点为参考点
表示xyz分量各移动多少
//需要引入glut库
#include "stdafx.h" // 最前面
#include "stdlib.h"
#include "conio.h"
#include "math.h"
#include "glut.h" // C函数原型, 其中包括 gl.h 和 glu.h, 200多个函数, 状态变量
#include <windows.h>
// ASCII字符总共只有0到127,一共128种字符
#define MAX_CHAR 128
//
// 3D图形变换基本柜架演示
//
// 全局变量
GLsizei ww = 500, hh = 500; // 放当前窗口宽和高(像素数), 有size表示是只取正值
int button_x = 0;
int button_y = 0;
int angle = 0;
float key_dx = 0.0f;
float key_dy = 0.0f;
float key_dz = 0.0f;
/
显示字用来调用
void drawString(const char* str) {
static int isFirstCall = 1;
static GLuint lists;
if( isFirstCall ) { // 如果是第一次调用,执行初始化
// 为每一个ASCII字符产生一个显示列表
isFirstCall = 0;
// 申请MAX_CHAR个连续的显示列表编号
lists = glGenLists(MAX_CHAR);
// 把每个字符的绘制命令都装到对应的显示列表中
wglUseFontBitmaps(wglGetCurrentDC(), 0, MAX_CHAR, lists);
}
// 调用每个字符对应的显示列表,绘制每个字符
for(; *str!='\0'; ++str)
glCallList(lists + *str);
}
//所有文本内容显示
void body_DrawString()
{
glPushMatrix();
glRasterPos3f(0.0f, 0.0f,0.0f);
drawString("(0,0,0)");
glRasterPos3f(2.14f, 0.0f, 0.0f);
drawString("X");
glRasterPos3f(0.0f, 2.14f,0.0f);
drawString("Y");
glRasterPos3f(0.0f, 0.0f,2.14f);
drawString("Z");
glPopMatrix();
}
void display_body_DrawString(float dx, float dy, float dz, char* d_body)
{
glPushMatrix();
glRasterPos3f(dx, dy, dz);
drawString(d_body);
glPopMatrix();
}
//
//用来画一个坐标轴的函数,z轴
void axis(float length)
{
glPushMatrix();
glBegin(GL_LINES);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, length);
glEnd();
//将当前操作点移到指定位置
glTranslated(0.0, 0.0, length - 0.2);
glColor3f(1.0, 0.0, 0.0);
glutWireCone(0.04, 0.3, 8, 8);
glPopMatrix();
}
void x_y_z_lines(float length)
{
//画Z轴
glPushMatrix();
glColor3f(1.0f, 0.0f, 0.0f);
axis(length);
glPopMatrix();
//画Y轴
glPushMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glRotated(-90.0, 1.0, 0.0, 0);//绕x轴正方向旋转-90度
axis(length);
glPopMatrix();
//画X轴
glPushMatrix();
glColor3f(0.0f, 0.0f, 1.0f);
glRotated(90.0, 0.0, 1.0, 0.0);//绕y轴方向旋转90
axis(length);
glPopMatrix();
}
//
//画单网格面,yoz
//后面需要旋转就行
void yoz_face_lines(float length)
{
glPushMatrix();
glBegin(GL_LINES);
for(int i = 0;length>0;++i)
{
glVertex3d(0.0, length, 0.0);
glVertex3d(0.0, length, 2.0);
glVertex3d(0.0, 0.0, length);
glVertex3d(0.0, 2.0, length);
length -= 0.2;
}
glEnd();
glPopMatrix();
}
///
//画所有网格面,yoz,xoz,xoy
//通过yoz单面旋转
/坐标轴网格//
/
void xoz_yoz_xoz_face_lines(void)
{
glPushMatrix();
glColor3f(1.0f, 1.0f, 0.0f);
yoz_face_lines(2);
glPopMatrix();
glPushMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glRotated(90.0, 0, 1.0, 0);//绕y轴正方向旋转90度
yoz_face_lines(2);
glPopMatrix();
glPushMatrix();
glColor3f(1.0f, 1.0f, 1.0f);
glRotated(-90.0, 0.0, 0.0, 1.0);
yoz_face_lines(2);
glPopMatrix();
}
//z轴画线
void Draw_a_line(float length)
{
glPushMatrix();
glBegin(GL_LINES);
glVertex3d(0.0f, 0.0f, 0.0f);
glVertex3d(0.0f, 0.0f, length);
glEnd();
glPopMatrix();
}
//xoz平面画面
void Draw_a_face(float length)
{
//oz下 1
glPushMatrix();
Draw_a_line(length);
glPopMatrix();
//oz下对面 2
glPushMatrix();
glTranslatef(length, 0.0f, 0.0f);
Draw_a_line(length);
glPopMatrix();
//ox下 3
glPushMatrix();
glRotated(90.0, 0, 1.0, 0);
Draw_a_line(length);
glPopMatrix();
//ox下对面 4
glPushMatrix();
glTranslatef(0.0f, 0.0f, length);
glRotated(90.0, 0, 1.0, 0);
Draw_a_line(length);
glPopMatrix();
}
//xyz正半轴体
void six_face_body(float length)
{
//xoz下 底部 1
glPushMatrix();
glColor3f(1.0f, 0.0f, 0.0f);
Draw_a_face(length);
glPopMatrix();
//xoz上 顶部 2
glPushMatrix();
glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef( 0.0f, length, 0.0f );
Draw_a_face(length);
glPopMatrix();
//yoz左 左侧 3
glPushMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glRotated(90.0, 0.0f, 0.0f, 1.0f);
Draw_a_face(length);
glPopMatrix();
//yoz右 右侧 4
glPushMatrix();
glColor3f(0.0f, 1.0f, 0.0f);
glTranslatef( length, 0.0f, 0.0f );
glRotated(90.0, 0.0f, 0.0f, 1.0f);
Draw_a_face(length);
glPopMatrix();
//xoy后 后面 5
glPushMatrix();
glColor3f(0.0f, 0.0f, 1.0f);
glRotated(-90.0, 1.0f, 0.0f, 0.0f);
Draw_a_face(length);
glPopMatrix();
//xoy前 前面 6
glPushMatrix();
glColor3f(0.0f, 0.0f, 1.0f);
glTranslatef( 0.0f, 0.0f, length );
glRotated(-90.0, 1.0f, 0.0f, 0.0f);
Draw_a_face(length);
glPopMatrix();
//正面
glPushMatrix();
glColor3f(1.0f, 0.3f, 1.0f);
glTranslatef(0.0f , 0.0f, length );//向z轴正方向平移length
glRotated(90.0, 0, 1.0, 0);//绕y轴正方向旋转90度
Draw_a_face(length);
glPopMatrix();
}
void move_six_face_body(float dx, float dy, float dz,float length)
{
glPushMatrix();
glTranslatef( dx, dy, dz );
six_face_body(length);
glPopMatrix();
}
void x_y_move_six_face_body_2X2(float dx, float dy, float dz, float length )
{
move_six_face_body( dx, dy, dz, length);
move_six_face_body( dx+length, dy, dz, length);
move_six_face_body( dx, dy+length, dz, length);
move_six_face_body( dx+length, dy+length, dz, length);
}
void x_y_z_move_six_face_body_2X2(float dx, float dy, float dz, float length)
{
x_y_move_six_face_body_2X2(dx, dy, dz, length);
glPushMatrix();
glTranslatef( 0.0f, 0.0f, length );
x_y_move_six_face_body_2X2(dx, dy, dz, length);
glPopMatrix();
}
void draw_button_site(int button_x, int button_y)
{
char *button_siteX= "(0";
char *button_siteY= ",0)";
char Cbutton_x[20];
char Cbutton_y[20];
itoa(button_x,Cbutton_x,10); // itoa(int,char,要转换的进制数)
itoa(button_y,Cbutton_y,10); // itoa(int,char,要转换的进制数)
button_siteX = Cbutton_x;
button_siteY = Cbutton_y;
display_body_DrawString(1.0f, 2.0f, 2.0f,"button site now: ");
display_body_DrawString(1.1f, 1.9f, 2.0f,button_siteX);
display_body_DrawString(1.3f, 1.9f, 2.0f,button_siteY);
glutPostRedisplay();
}
// 功能: 显示程序, 重画消息回调函数
void display()
{
glClearColor(0.0f,0.0,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glPushMatrix();
glTranslatef( -1.8, -1.8, -1.8 ); // T2, T = T X T2
glScalef( 1.5, 1.5, 1.5 ); // T3, T = T X T3
//glRotatef( -90, 0.0, 1.0,0.0 ); // T4, T = T X T4
glColor3f(1.0, 0.5, 0.5 );
glColor3f(1.0,1.0,1.0);
draw_button_site(button_x, button_y);
glPushMatrix();
glTranslatef( 2.0f, 0.0f, 2.0f );
glRotatef( angle+30, 0.0f, 0.0,0.0f );
six_face_body(0.2);
six_face_body(0.3);
glPopMatrix();
glPushMatrix();
glTranslatef( key_dx, key_dy, key_dz );
glTranslatef( 0.0f, 2.0f, 0.0f );
glTranslatef( 2.0, 0.0, 0.0 );
glRotatef( angle+30, 0.0f, 30.0f,0.0f );
six_face_body(0.5);
six_face_body(0.7);
glPopMatrix();
glPushMatrix();
glTranslatef( 2.0, 0.0, 0.0 );
glRotatef( angle+30, 1.0f, 30.0f,0.0f );
glTranslatef( -2.0, 0.0, 0.0 );
x_y_z_move_six_face_body_2X2(0.0f,0.0f,0.0f,0.3);
glPopMatrix();
//
///site场景坐标
x_y_z_lines(2.5); //xyz坐标轴
xoz_yoz_xoz_face_lines(); //坐标轴网格
body_DrawString(); //文字内容
glPopMatrix();
glFlush();;//glutSwapBuffers(); // 立即把上面生成的图形, 即图形缓冲区中图像, 显示在屏幕上
}
// 功能: 窗口消息回调函数, 投影变换: 投影、截剪、窗口与视口变换
void reshape( GLsizei w, GLsizei h )
{
glMatrixMode( GL_PROJECTION ); // 当前选投影变换矩阵, 分二种: 正交投影和透视投影
glLoadIdentity(); // T11 = I, 置为单位矩阵
glViewport( 0, 0, (GLsizei)ww, (GLsizei)hh ); // T12, 窗口->视口变换, glViewport(x, y, width, height),
glFrustum( -1.0, 1.0, -1.0, 1.0, 1.5, 20.0 ); // T11 设置透视投影变换矩阵值,
glMatrixMode( GL_MODELVIEW ); // 当前选模型视图变换矩阵, 内部矩阵T: 4X4矩阵
glLoadIdentity(); // T = I 设为单位矩阵
// 视图(View)变换矩阵, 世界坐标系上的点 变换到 观察坐标系的点
gluLookAt( 0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); // T1, T = T X T1
}
// 功能: 初始化
// 说明: 一般把与图形无关的投影变换放在这里
void init()
{
// 清窗口(颜色缓冲区中位清0)
glClear( GL_COLOR_BUFFER_BIT );
glClearColor( 0.0, 0.0, 0.0, 0.0 );
}
void myMouse(int button, int state, int x, int y){
button_x = x;
button_y = y;
if (state == GLUT_DOWN){
printf("坐标:%d,%d\n\n",button_x,button_y);
if (button == GLUT_LEFT_BUTTON){
}
else if (button == GLUT_RIGHT_BUTTON){
glFlush();
}
}
return;
}
void keyboard (unsigned char key, int x, int y)
{
switch (key){
case 'Q':
//glutPostRedisplay();
break;
case 'q':
//glutPostRedisplay();
break;
case 'r':
key_dx = 1.0f;
key_dy = 1.0f;
key_dz = 0.0f;
glutPostRedisplay();
break;
case 32:
key_dy +=0.1;
glutPostRedisplay();
break;
case 'c':
key_dy -=0.1;
glutPostRedisplay();
break;
case 'w':
key_dz -=0.1;
glutPostRedisplay();
break;
case 'a':
key_dx -=0.1;
glutPostRedisplay();
break;
case 's':
key_dz +=0.1;
glutPostRedisplay();
break;
case 'd':
key_dx +=0.1;
glutPostRedisplay();
break;
case 27:
exit(0);
break;
default:
break;
}
}
//定时器
void timerFunc(int nTimerID)
{
switch(nTimerID)
{
case 1:
angle=(angle+10)%360;
printf("角度:%d\n",angle);
glutPostRedisplay();
glutTimerFunc(1000,timerFunc,1);
break;
}
}
// 功能: 程序入口
int main( int argc, char** argv )
{
glutInit( &argc, argv ); // 初始化模式并在屏幕左上角打开一个窗口
glutInitDisplayMode( GLUT_SINGLE | GLUT_RGB );
glutInitWindowSize( ww, hh ); // 窗口大小和窗口左上角在屏幕上位置
glutInitWindowPosition( 0, 0 );
glutCreateWindow( "Add3D交互" ); // 置窗口标题
init(); // 初始化
///
glutDisplayFunc( display ); // 注册重画消息回调函数
glutReshapeFunc( reshape ); // 注册窗口消息回调函数
///
glutKeyboardFunc(keyboard);
glutMouseFunc(myMouse);
glutTimerFunc(1000,timerFunc,1);
glutMainLoop(); // 无限循环, 完成消息检测与调用
return 0;
}
wanle
下一个:
opengl3D灯光与材质设置与显示,纹理,等