⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 camera.cpp

📁 file code.zip are used to implement ray tracing technology.
💻 CPP
字号:
#include "camera.h"

#define ROUND(X)	((int)floor((X) + 0.5))
#define COLOR(X)	((unsigned char)max(0, min(255, ROUND((X)*255.0))))

void Camera::status(ostream &myOut, long currentRay, int percent, Scene scn)
{
	myOut << percent << "% completed (" << currentRay << " rays cast from eye, "
			<< scn.shadowRays << " shadow rays cast, "
			<< scn.reflRays << " reflection rays cast, "
			<< scn.refrRays << " refraction rays cast)\r";
	myOut.flush();
}

void Camera :: setModelViewMatrix(void) 
{ // load modelview matrix with existing camera values 
	float m[16]; 
	Vector3 eVec(eye.x, eye.y, eye.z); // a vector version of eye  
	m[0] =  u.x; m[4] =  u.y; m[8]  =  u.z;  m[12] = -eVec.dot(u); 
	m[1] =  v.x; m[5] =  v.y; m[9]  =  v.z;  m[13] = -eVec.dot(v); 
	m[2] =  n.x; m[6] =  n.y; m[10] =  n.z;  m[14] = -eVec.dot(n); 
	m[3] =  0;   m[7] =  0;   m[11] =  0;    m[15] = 1.0; 
	glMatrixMode(GL_MODELVIEW); 
	glLoadMatrixf(m); // load OpenGL抯 modelview matrix 
} 

void Camera:: set(Point3 Eye, Point3 look, Vector3 up, bool tellOpenGL) 
{	// create a modelview matrix and optionally send it to OpenGL 
	eye.set(Eye); // store the given eye position 
	n.set(eye.x - look.x, eye.y - look.y, eye.z - look.z); // make n 
	Vector3 t1;
	t1 = up.cross(n);
	u.set(t1); // make u = up X n 
	n.normalize(); u.normalize(); // make them unit length 
	Vector3 t2;
	t2 = n.cross(u);
	v.set(t2);  // make v =  n X u 

	// Pass modelview to OpenGL only if you are drawing polygons (not raytracing)
	if(tellOpenGL)
		setModelViewMatrix(); // tell OpenGL  
} 

//<<<<<<<<<<<<<<<<<<<<<< slide >>>>>>>>>>>>>>>>>>>>>>..
void Camera :: slide(float du, float dv, float dn)
{ // slide both eye and lookAt by amount du * u + dv * v + dn * n;
	eye.x += du * u.x + dv * v.x + dn * n.x;
	eye.y += du * u.y + dv * v.y + dn * n.y;
	eye.z += du * u.z + dv * v.z + dn * n.z;
	setModelViewMatrix();
}
//<<<<<<<<<<<<<<<<<<<<<<<< rotAxes >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void Camera:: rotAxes(Vector3& a, Vector3& b, float angle)
{ // rotate orthogonal vectors a (like x axis) and b(like y axia) through angle degrees
	float ang = 3.14159265/180*angle;
	float C = cos(ang), S = sin(ang);
	Vector3 t(C * a.x + S * b.x, C * a.y + S * b.y, C * a.z + S * b.z); // tmp for a vector
	b.set(-S * a.x + C * b.x, -S * a.y + C * b.y,-S * a.z + C * b.z);
	a.set(t.x, t.y, t.z); // put tmp into a'
}
//<<<<<<<<<<<<<<<<<<<<<<<< roll >>>>>>>>>>>>>>>>>>>>>>>>>>>
void Camera :: roll(float angle)
{
	rotAxes(u, v, -angle); setModelViewMatrix();
}
//<<<<<<<<<<<<<<<<<<<<<<<< pitch >>>>>>>>>>>>>>>>>>>>>>>>>
void Camera :: pitch(float angle)
{
	rotAxes(n, v, -angle);setModelViewMatrix();
}
//<<<<<<<<<<<<<<<<<<<<<<<<< yaw >>>>>>>>>>>>>>>>>>>>>>>>
void Camera :: yaw(float angle)
{
	rotAxes(u, n, -angle);setModelViewMatrix();
}
void Camera:: setProjectionMatrix()
{
	glMatrixMode(GL_PROJECTION); glLoadIdentity();
	gluPerspective(viewAngle, aspect, nearDist, farDist);
	glMatrixMode(GL_MODELVIEW); // set its mode back again
}
void Camera :: setDisplay(int numRows, int numCols)
{ // tell camera screen size
	nRows = numRows; 	nCols = numCols;
}
void Camera:: drawOpenGL(Scene &scn)
	{
		//first set the lights for openGL
		float globalAmbient[4];
		scn.ambient.build4tuple(globalAmbient); //build 4tuple for global ambient
		glLightModelfv(GL_LIGHT_MODEL_AMBIENT,globalAmbient);
		int num, lightNum = GL_LIGHT0; //grab defined int for GL's light0
		float colr[4], posn[4]; // arrays to hold openGL lights: color and position
		setModelViewMatrix(); // for this camera set up
		setProjectionMatrix(); // for this camera
		Light *p;
		for(p = scn.light, num = 0; p && num < 8; p = p->next, lightNum++, num++)
		{ // set up to 8 OpenGL lights
			(p->color).build4tuple(colr);
			(p->pos).build4tuple(posn);
			float zero[] = {0.0,0.0,0.0,1.0}; // sources don't have ambient component
			glLightfv(lightNum,GL_AMBIENT,zero); //lights don't have their own ambient part
			glLightfv(lightNum,GL_DIFFUSE,colr); // tell openGL diffuse light color
			glLightfv(lightNum,GL_SPECULAR,colr); // tell openGl specualt light color
			glLightfv(lightNum,GL_POSITION,posn);
			glEnable(lightNum); // enable it after specifying its properties
		}
		glEnable(GL_DEPTH_TEST);
		glEnable(GL_LIGHTING);
		glClearColor(scn.background.red, scn.background.green, scn.background.blue,1.0f);
		for(GeomObj* q = scn.obj; q ; q = q->next)
			q->drawOpenGL(); // draw it
		glFlush();
}
//<<<<<<<<<<<<<<<<<<<<<<<<< set - takes 9 params >>>>>>>>>>>>>>>>>
void Camera :: set(float ex, float ey, float ez, float lx, float ly, float lz, float upx, float upy, float upz)
{
	Point3 e(ex, ey, ez);
	Point3 look(lx, ly, lz);
	Vector3 Up(upx, upy, upz);
	set(e,look, Up);
}
void Camera :: setShape(float vAng, float asp, float nearD, float farD, bool tellOpenGL)
{
	viewAngle = vAng;
	aspect = asp;
	nearDist = nearD;
	farDist = farD;
	H = nearD * tan(vAng * M_PI/360); // tan(theta/2) theta in radians
	W = H * asp;

	// Pass perspective to OpenGL only if you are drawing polygons (not raytracing)
	if(tellOpenGL)
	{
		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		gluPerspective(viewAngle, aspect, nearDist, farDist);
	}
}

unsigned char* Camera::raytrace(Scene& scn, int blockSize, bool useOpenGL)
{
	size_t rayCount = 0;
	float percentage = 10;
	Ray theRay;
	Color3 clr;

	// Initialize the image buffer
	unsigned char *buffer;
	buffer = new unsigned char[3*nRows*nCols];
	if(buffer==NULL)
	{
	  fprintf(stderr,"Error Allocating Memory\n");
	  return NULL;
	}

	// Move through image plane and shoot rays
	theRay.setStart(eye);
	for(int row=0; row < nRows; row+=blockSize)
	{
		for(int col=0; col < nCols; col+=blockSize)
		{
			// compute the ray's direction
			float x = -W + col * 2 * W / (float) nCols;
			float y = -H + row * 2 * H / (float) nRows;
			theRay.setDir( -nearDist * n.x + x * u.x + y * v.x,
						   -nearDist * n.y + x * u.y + y * v.y,
						   -nearDist * n.z + x * u.z + y * v.z);

			// Shoot the ray into the scene
			clr = scn.shade(theRay);

			// Write the resulting color to the image buffer
			for(int i=0; i<blockSize; i++)
			{
				for(int j=0; j<blockSize; j++)
				{		   
					buffer[3*(nRows-1-row-i)*nCols+3*(col+j)] = COLOR(clr.red);
					buffer[3*(nRows-1-row-i)*nCols+3*(col+j)+1] = COLOR(clr.green);
					buffer[3*(nRows-1-row-i)*nCols+3*(col+j)+2] = COLOR(clr.blue);
				}
			}

			// Increment the ray counter
			rayCount++;

			// Update the text progress message
			if(100*rayCount/(float)(nRows*nCols) > percentage)
			{
				status(cout, rayCount, (int)floor(100*rayCount/(float)(nRows*nCols)), scn);
				percentage += 10;
			}
		}

		// Draw to OpenGL
		if(useOpenGL)
		{
			glRasterPos2i(0, row);
			glDrawPixels(nCols, 1, GL_RGB, GL_UNSIGNED_BYTE, buffer + (3*(nRows-(row+1))*nCols));
			glFlush();
		}
	}
	
	// Output final status message
	status(cout, rayCount, 100, scn);
	cout << endl;
	// Return a pointer to the image buffer
	return buffer;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -