www.pudn.com > opengl_pick_sample.rar > ogl3d.cpp


//	ogl3d.cpp 
// 
 
#include "stdafx.h" 
#include "ogl3d.h" 
#include "bmpreader.h" 
 
#include  
#include  
 
const int OGL3D_EARTH_LIST = 111; 
const int OGL3D_EARTH_LINES = 222; 
const int SOLAR_SYSTEM_LIST = 333; 
 
namespace GEO { 
	const double PI = 3.14159265359; 
	const double TWOPI = 6.28318530718; 
	const double DE2RA = 0.01745329252; 
	const double RA2DE = 57.2957795129; 
	const double FLATTENING = 1.0/298.26; 
	const double PIOVER2 = 1.570796326795; 
} 
 
OGL3D::OGL3D(void) 
{ 
	InitOGL3D(); 
} 
 
OGL3D::~OGL3D(void) 
{ 
} 
 
void OGL3D::SetTexture(DIBSection& dib) 
{ 
	if (dib.IsCreated()) 
	{ 
		GenTexture(dib); 
	} 
} 
 
void OGL3D::GenTexture(DIBSection& dib) 
{ 
	UINT32 width = dib.Width(); 
	UINT32 height = dib.Height(); 
 
	int w, h; 
 
	UINT32 max_dimension = width > height ? width : height; 
 
	if (width >= 512) w = 512; 
	else if (width >= 256) w = 256; 
	else if (width >= 128) w = 128; 
	else if (width >= 64) w = 64; 
	else if (width >= 32) w = 32; 
	else w = 16; 
 
	if (height >= 512) h = 512; 
	else if (height >= 256) h = 256; 
	else if (height >= 128) h = 128; 
	else if (height >= 64) h = 64; 
	else if (height >= 32) h = 32; 
	else h = 16; 
 
	dib.ResizeImage(m_texture_dib,w,h); 
 
	if (m_texture_dib.IsCreated()) 
	{ 
		m_have_texture = 1; 
	} 
} 
 
void OGL3D::RenderPrimaryImage(void) 
{ 
	const int NumLatitudes = 36; 
	const int NumLongitudes = 72; 
 
	double start_lat, start_lon; 
	double theta1, phi1, theta2, phi2, lat_incr, lon_incr; 
 
	GLdouble u[3], v[3], w[3], n[3]; 
	GLdouble R; 
 
	if (!m_model_built) 
	{ 
		glNewList( OGL3D_EARTH_LIST, GL_COMPILE); 
 
		glColor3ub(0,0,224); 
 
		if (m_have_texture) 
		{ 
			glTexImage2D(GL_TEXTURE_2D,0,3,m_texture_dib.Width(),m_texture_dib.Height(), 
						0,GL_BGR_EXT,GL_UNSIGNED_BYTE,(GLvoid *)m_texture_dib.GetBits()); 
 
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
 
			//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); 
			//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
 
			glEnable( GL_TEXTURE_2D ); 
		} 
		else 
		{ 
			glDisable( GL_TEXTURE_2D ); 
		} 
 
		m_model_built = 1; 
 
		if ( m_draw_mode == DrawLines ) 
		{ 
			glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
		} 
		else 
		{ 
			glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
		} 
 
		glBegin( GL_TRIANGLES ); 
 
		start_lat = -90; 
		start_lon = 0.0; 
		R = 1.0; 
 
		lat_incr = 180.0 / NumLatitudes; 
		lon_incr = 360.0 / NumLongitudes; 
 
		int row, col; 
 
		for (col = 0; col < NumLongitudes; col++){ 
			phi1 = (start_lon + col * lon_incr) * GEO::DE2RA; 
			phi2 = (start_lon + (col + 1) * lon_incr) * GEO::DE2RA; 
 
			for (row = 0; row < NumLatitudes; row++){ 
				theta1 = (start_lat + row * lat_incr) * GEO::DE2RA; 
				theta2 = (start_lat + (row + 1) * lat_incr) * GEO::DE2RA; 
 
				u[0] = R * cos(phi1) * cos(theta1);//x 
				u[1] = R * sin(theta1);//y 
				u[2] = R * sin(phi1) * cos(theta1);//z 
				 
				v[0] = R * cos(phi1) * cos(theta2);//x 
				v[1] = R * sin(theta2);//y 
				v[2] = R * sin(phi1) * cos(theta2);//z 
 
				w[0] = R * cos(phi2) * cos(theta2);//x 
				w[1] = R * sin(theta2);//y 
				w[2] = R * sin(phi2) * cos(theta2);//z 
 
				NormalVector(u,v,w,n); 
				glNormal3dv(n); 
				glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,(theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
				glVertex3dv(u); 
				glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,(theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
				glVertex3dv(v); 
				glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,(theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
				glVertex3dv(w); 
 
				v[0] = R * cos(phi2) * cos(theta1);//x 
				v[1] = R * sin(theta1);//y 
				v[2] = R * sin(phi2) * cos(theta1);//z 
 
				NormalVector(u,w,v,n); 
				glNormal3dv(n); 
				glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,(theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
				glVertex3dv(u); 
				glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,(theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
				glVertex3dv(w); 
				glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,(theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
				glVertex3dv(v); 
			} 
		} 
 
		glEnd(); 
 
		if (m_have_texture) 
		{ 
			glDisable( GL_TEXTURE_2D ); 
		} 
 
		GLView3D::RenderPrimaryImage(); 
 
		glEndList(); 
	} 
 
	glCallList( OGL3D_EARTH_LIST ); 
} 
 
void SolarSystem3D::RenderSun(void) 
{ 
} 
 
void SolarSystem3D::RenderMercury(void) 
{ 
} 
 
void SolarSystem3D::RenderVenus(void) 
{ 
} 
 
void SolarSystem3D::RenderEarth(void) 
{ 
} 
 
void SolarSystem3D::RenderMars(void) 
{ 
} 
 
void SolarSystem3D::RenderJupiter(void) 
{ 
} 
 
void SolarSystem3D::RenderSaturn(void) 
{ 
} 
 
void SolarSystem3D::RenderUranus(void) 
{ 
} 
 
void SolarSystem3D::RenderNeptune(void) 
{ 
} 
 
void SolarSystem3D::RenderPluto(void) 
{ 
} 
 
SolarSystem3D::SolarSystem3D(void) 
{ 
	m_model_built = 0; 
	m_draw_mode = OGL3D::DrawTriangles; 
 
	DIBSection dib; 
	ReadBMPFile("et.bmp",dib); 
	GenTexture(dib,m_earth_texture); 
	ReadBMPFile("mt.bmp",dib); 
	GenTexture(dib,m_mars_texture); 
	ReadBMPFile("jt.bmp",dib); 
	GenTexture(dib,m_jupiter_texture); 
	ReadBMPFile("st.bmp",dib); 
	GenTexture(dib,m_saturn_texture); 
} 
 
SolarSystem3D::~SolarSystem3D(void) 
{ 
} 
 
void SolarSystem3D::RenderTexturedSphere(DIBSection& dib, double radius) 
{ 
 
	glTexImage2D(GL_TEXTURE_2D,0,3,dib.Width(),dib.Height(), 
				0,GL_BGR_EXT,GL_UNSIGNED_BYTE,(GLvoid *)dib.GetBits()); 
 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); 
 
	glEnable( GL_TEXTURE_2D ); 
 
	glBegin( GL_TRIANGLES ); 
 
	double start_lat = -90; 
	double start_lon = 0.0; 
	double R = radius; 
 
	const int NumLatitudes = 36; 
	const int NumLongitudes = 72; 
 
	double lat_incr = 180.0 / NumLatitudes; 
	double lon_incr = 360.0 / NumLongitudes; 
 
	double phi1, phi2, theta1, theta2; 
	GLdouble u[3], v[3], w[3], n[3]; 
 
	int row, col; 
 
	for (col = 0; col < NumLongitudes; col++){ 
		phi1 = (start_lon + col * lon_incr) * GEO::DE2RA; 
		phi2 = (start_lon + (col + 1) * lon_incr) * GEO::DE2RA; 
 
		for (row = 0; row < NumLatitudes; row++){ 
			theta1 = (start_lat + row * lat_incr) * GEO::DE2RA; 
			theta2 = (start_lat + (row + 1) * lat_incr) * GEO::DE2RA; 
 
			u[0] = R * cos(phi1) * cos(theta1);//x 
			u[1] = R * sin(theta1);//y 
			u[2] = R * sin(phi1) * cos(theta1);//z 
			 
			v[0] = R * cos(phi1) * cos(theta2);//x 
			v[1] = R * sin(theta2);//y 
			v[2] = R * sin(phi1) * cos(theta2);//z 
 
			w[0] = R * cos(phi2) * cos(theta2);//x 
			w[1] = R * sin(theta2);//y 
			w[2] = R * sin(phi2) * cos(theta2);//z 
 
			NormalVector(u,v,w,n); 
			glNormal3dv(n); 
			glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,(theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
			glVertex3dv(u); 
			glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,(theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
			glVertex3dv(v); 
			glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,(theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
			glVertex3dv(w); 
 
			v[0] = R * cos(phi2) * cos(theta1);//x 
			v[1] = R * sin(theta1);//y 
			v[2] = R * sin(phi2) * cos(theta1);//z 
 
			NormalVector(u,w,v,n); 
			glNormal3dv(n); 
			glTexCoord2d((180.0 - phi1*GEO::RA2DE)/360.0,(theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
			glVertex3dv(u); 
			glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,(theta2 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
			glVertex3dv(w); 
			glTexCoord2d((180.0 - phi2*GEO::RA2DE)/360.0,(theta1 + GEO::PIOVER2)*GEO::RA2DE/180.0); 
			glVertex3dv(v); 
		} 
	} 
 
	glDisable( GL_TEXTURE_2D ); 
 
	glEnd(); 
} 
 
void SolarSystem3D::RenderColoredSphere(COLORREF cr, double radius) 
{ 
	glDisable( GL_TEXTURE_2D ); 
 
	glBegin( GL_TRIANGLES ); 
 
	glColor3ub(GetRValue(cr),GetGValue(cr),GetBValue(cr)); 
 
	double start_lat = -90; 
	double start_lon = 0.0; 
	double R = radius; 
 
	const int NumLatitudes = 18; 
	const int NumLongitudes = 36; 
 
	double lat_incr = 180.0 / NumLatitudes; 
	double lon_incr = 360.0 / NumLongitudes; 
 
	double phi1, phi2, theta1, theta2; 
	GLdouble u[3], v[3], w[3], n[3]; 
 
	int row, col; 
 
	for (col = 0; col < NumLongitudes; col++){ 
		phi1 = (start_lon + col * lon_incr) * GEO::DE2RA; 
		phi2 = (start_lon + (col + 1) * lon_incr) * GEO::DE2RA; 
 
		for (row = 0; row < NumLatitudes; row++){ 
			theta1 = (start_lat + row * lat_incr) * GEO::DE2RA; 
			theta2 = (start_lat + (row + 1) * lat_incr) * GEO::DE2RA; 
 
			u[0] = R * cos(phi1) * cos(theta1);//x 
			u[1] = R * sin(theta1);//y 
			u[2] = R * sin(phi1) * cos(theta1);//z 
			 
			v[0] = R * cos(phi1) * cos(theta2);//x 
			v[1] = R * sin(theta2);//y 
			v[2] = R * sin(phi1) * cos(theta2);//z 
 
			w[0] = R * cos(phi2) * cos(theta2);//x 
			w[1] = R * sin(theta2);//y 
			w[2] = R * sin(phi2) * cos(theta2);//z 
 
			NormalVector(u,v,w,n); 
			glNormal3dv(n); 
			glVertex3dv(u); 
			glVertex3dv(v); 
			glVertex3dv(w); 
 
			v[0] = R * cos(phi2) * cos(theta1);//x 
			v[1] = R * sin(theta1);//y 
			v[2] = R * sin(phi2) * cos(theta1);//z 
 
			NormalVector(u,w,v,n); 
			glNormal3dv(n); 
			glVertex3dv(u); 
			glVertex3dv(w); 
			glVertex3dv(v); 
		} 
	} 
 
	glEnd(); 
} 
 
void SolarSystem3D::GenTexture(DIBSection& dib, DIBSection& texture_dib) 
{ 
	UINT32 width = dib.Width(); 
	UINT32 height = dib.Height(); 
 
	int w, h; 
 
	UINT32 max_dimension = width > height ? width : height; 
 
	if (width >= 512) w = 512; 
	else if (width >= 256) w = 256; 
	else if (width >= 128) w = 128; 
	else if (width >= 64) w = 64; 
	else if (width >= 32) w = 32; 
	else w = 16; 
 
	if (height >= 512) h = 512; 
	else if (height >= 256) h = 256; 
	else if (height >= 128) h = 128; 
	else if (height >= 64) h = 64; 
	else if (height >= 32) h = 32; 
	else h = 16; 
 
	dib.ResizeImage(texture_dib,w,h); 
} 
 
int SolarSystem3D::PickPlanet(int x, int y, CString& msg) 
{ 
	int result = -1; 
 
	if ( m_draw_mode == OGL3D::DrawLines ) 
	{ 
		glPolygonMode(GL_FRONT_AND_BACK,GL_LINE); 
	} 
	else 
	{ 
		glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); 
	} 
 
	glShadeModel(GL_FLAT); 
	glDisable(GL_LIGHT0); 
	glDisable(GL_LIGHTING); 
 
	glClearColor((float)1.00,(float)1.00, 
		(float)1.00,1.0f); 
 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
 
	glPushMatrix(); 
	glTranslated(m_model_matrix.X(),m_model_matrix.Y(),m_model_matrix.Z()); 
	glRotated(m_model_matrix.XRot(), 1.0, 0.0, 0.0); 
	glRotated(m_model_matrix.YRot(), 0.0, 1.0, 0.0); 
	glRotated(m_model_matrix.ZRot(), 0.0, 0.0, 1.0); 
	glScaled(m_model_matrix.XScale(),m_model_matrix.YScale(),m_model_matrix.ZScale()); 
 
	glScaled(0.40,0.40,0.40); 
 
	COLORREF cr; 
	std::vector colorVector; 
 
	cr = 1; 
	RenderColoredSphere(cr,0.55); 
	colorVector.push_back(cr); 
 
	glPushMatrix(); 
	glRotated(90.0, 0.0, 1.0, 0.0); 
	glTranslated(1.0,0.0,0.0); 
	cr = 2; 
	RenderColoredSphere(cr,0.10); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(180.0, 0.0, 1.0, 0.0); 
	glTranslated(1.5,0.0,0.0); 
	cr = 3; 
	RenderColoredSphere(cr,0.15); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(270.0, 0.0, 1.0, 0.0); 
	glTranslated(2.0,0.0,0.0); 
	cr = 4; 
	RenderColoredSphere(cr,0.20); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(0.0, 0.0, 1.0, 0.0); 
	glTranslated(2.5,0.0,0.0); 
	cr = 5; 
	RenderColoredSphere(cr,0.15); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(45.0, 0.0, 1.0, 0.0); 
	glTranslated(3.5,0.0,0.0); 
	cr = 6; 
	RenderColoredSphere(cr,0.40); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(135.0, 0.0, 1.0, 0.0); 
	glTranslated(4.5,0.0,0.0); 
	cr = 7; 
	RenderColoredSphere(cr,0.25); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(225.0, 0.0, 1.0, 0.0); 
	glTranslated(5.0,0.0,0.0); 
	cr = 8; 
	RenderColoredSphere(cr,0.15); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(315.0, 0.0, 1.0, 0.0); 
	glTranslated(5.5,0.0,0.0); 
	cr = 9; 
	RenderColoredSphere(cr,0.15); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPushMatrix(); 
	glRotated(15.0, 0.0, 1.0, 0.0); 
	glTranslated(6.0,0.0,0.0); 
	cr = 10; 
	RenderColoredSphere(cr,0.15); 
	colorVector.push_back(cr); 
	glPopMatrix(); 
 
	glPopMatrix(); 
 
	cr = 0; 
	m_dib.GetPixel(x,y,cr); 
	 
	msg = "missed"; 
 
	char * planets[10] = {"Sun","Mercury","Venus","Earth","Mars", 
		"Jupiter","Saturn","Uranus","Neptune","Pluto"}; 
 
	int color_size = colorVector.size(); 
	for (int i=0;i