欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenGL

程序员文章站 2023-12-25 20:28:03
...

用JOGL做简单的3D场景

制作3D场景先确定xyz坐标系,本文用的是右手原则的坐标系,如图
OpenGL
然后确定好自己要画的物体在该坐标系中对应的坐标就可以开始了;本文画的是非常简单的房子。

实现

继承GLEventListener,实现它的4个接口
首先画一个地板,在display(GLAutoDrawable drawable)中用4个glVertex3f()来构建一个平面,参数分别对应x, y, z

		//drawfloor
		gl.glBegin(GL2.GL_QUADS);
		gl.glColor3f(0.35f, 0.16f, 0.14f);
		gl.glVertex3f(-100.0f, -1.0f, -100.0f);
		gl.glVertex3f(-100.0f, -1.0f, 100.0f);
		gl.glVertex3f(100.0f, -1.0f, 100.0f);
		gl.glVertex3f(100.0f, -1.0f, -100.0f);

注意:因为OpenGL是C++的库,所以用JAVA写的时候需要导入的是JOGL,而且需要加上GL2 gl = drawable.getGL().getGL2();才能使用OpenGL的各个方法
然后用相同的方法画房子主体和屋顶,因为需要改变的只有各个点的坐标,所以就只放实现房顶正面的代码(和画地板是一样的)
画图的方法有很多,网上都能找到,注意:在每次画完一个图形之后,如果需要用glTranslatef()移动或者glBegin()画一个新的图形,需要添加gl.glLoadIdentity();

		//roof front
		gl.glColor3f(1.0f, 0.0f, 0.0f); //
		gl.glVertex3f( 2.0f, 3.7f, 1.25f ); 
		gl.glVertex3f( -2.0f, 3.7f, 1.25f ); 
		gl.glVertex3f( -3.0f, 2.5f, 1.75f );  
		gl.glVertex3f( 3.0f, 2.5f, 1.75f );

init( GLAutoDrawable drawable )中开启深度测试,为的是让位于后面的像素不会阻挡前面的像素

		gl.glClearDepth( 1.0f );
		gl.glEnable( GL2.GL_DEPTH_TEST );	//用来调整物体遮挡关系,使后面的像素不会挡住前面的像素
		gl.glDepthFunc( GL2.GL_LEQUAL );
		gl.glHint( GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST );

reshape(GLAutoDrawable drawable, int x, int y, int w, int h)中设置投影方式,一种是perspective projection,一种是orthographic projection

		float f = (float)w/(float)h;
		glu.gluPerspective(45, f, 1, 1000); //prespective projection定义相机内在镜头状态(可视空间),视角,定义在画板上xy方向上的比例;
		//gl.glOrthof(-10.0f, 10.0f, -10.0f, 10.0f, 10.0f, -10.0f); //orthographic projection, x, y, z;

perspective中各参数分别代表:可视角度,视景体的宽高比,z轴上相机最近可看到的距离,z轴…最远;
Orthof中各参数:前两个代表x轴上可是范围[-10,10],中间两个是y轴的,最后两个是z轴的;
然后设置相机所在位置和朝向(在3维坐标系中,知道两点的坐标可以确定一个向量)

	static float x = 0.0f,y = 4.5f, z = 10.0f; //相机位置
	static float vx = 0.0f, vy = -0.3f, vz = -1.0f; //视线方向,初始设置为沿着z轴方向
	glu.gluLookAt(x, y, z, x+vx, y+vy, z+vz, 0.0f, 1.0f, 0.0f);	//定义摄像机位置,朝向,

本文设置了按键监听,按左右键调整相机角度,上下键实现相机画面的缩放(当然也可以设计成前进后退模拟行走)
注意:如果要设置成缩放,要在display()中加一段代码 gl.glScalef(scale, scale, scale);

int key = ke.getKeyCode();
		switch(key) {
			case KeyEvent.VK_UP:
				scale += 0.1;
				break;
			case KeyEvent.VK_DOWN:
				scale -= 0.1;
				break;
			case KeyEvent.VK_LEFT:
				vx -= 0.05f;
				break;
			case KeyEvent.VK_RIGHT:
				vx += 0.05f;
		}

最后就是把画面显示出来,本文设置了3个相机,一个固定,一个使用透视投影,一个使用正交投影,分成3个class,代码基本相同,main函数随便放期中一个就好了

		JFrame frame = new JFrame ( "Assignment2 - 3D scene" );
		
		GLCanvas glcanvas = new GLCanvas();
		GLCanvas glcanvas1 = new GLCanvas();
		GLCanvas glcanvas2 = new GLCanvas();
		
		Perspective persp = new Perspective();
		Orthographic ortho = new Orthographic();
		
		glcanvas1 = Perspective.glcanvas;
		glcanvas2 = Orthographic.glcanvas;
		glcanvas.addGLEventListener( this );
		glcanvas.addKeyListener( this );
		glcanvas.setPreferredSize( new Dimension(800, 500) );
		glcanvas1.addGLEventListener( persp );
		glcanvas1.addKeyListener( persp );
		glcanvas1.setPreferredSize( new Dimension(400, 400) );
		glcanvas2.addGLEventListener( ortho );
		glcanvas2.addKeyListener( ortho );
		glcanvas2.setPreferredSize( new Dimension(400, 400) );
		
		frame.add( glcanvas, BorderLayout.NORTH );
		frame.add( glcanvas1, BorderLayout.WEST );
		frame.add( glcanvas2, BorderLayout.EAST );
		frame.setSize( frame.getContentPane().getPreferredSize() );
		frame.setVisible( true );
		
		anim = new Animator(glcanvas);
		anim.start();
		anim1 = new Animator(glcanvas1);
		anim1.start();
		anim2 = new Animator(glcanvas2);
		anim2.start();

下面是实现的效果
OpenGL

上一篇:

下一篇: