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

📄 vector3.cpp

📁 蒙特卡罗方法可以有效地解决复杂的工程问题
💻 CPP
字号:
// Vector3.cpp : implementation file
//

#include "stdafx.h"
#include "noname.h"
#include "Vector3.h"
#include "AddSphere.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "Vector3.h"
void CPrimitive::SetName(char *a_Name)
{
	delete m_Name; 
	m_Name = new char[strlen( a_Name ) + 1]; 
	strcpy( m_Name, a_Name ); 
}
int CSphere::Intersect(CRay &a_Ray,float &a_Dist)
{
	CVector3 v = a_Ray.GetOrigin() - m_Centre;
	float b = -DOT( v, a_Ray.GetDirection() );
	float det = (b * b) - DOT( v, v ) + m_SqRadius;
	int retval = MISS;
	if (det > 0)
	{
		det = sqrtf( det );
		float i1 = b - det;
		float i2 = b + det;
		if (i2 > 0)
		{
			if (i1 < 0) 
			{
				if (i2 < a_Dist) 
				{
					a_Dist = i2;
					retval = INPRIM;
				}
			}
			else
			{
				if (i1 < a_Dist)
				{
					a_Dist = i1;
					retval = HIT;
				}
			}
		}
	}
	return retval;

}
CVector3 CPlanePrim::GetNormal( CVector3& a_Pos )
{
	return m_Plane.N;
}
int CPlanePrim::Intersect(CRay &a_Ray,float &a_Dist)
{
	float d = DOT( m_Plane.N, a_Ray.GetDirection() );
	if (d != 0)
	{
		float dist = -(DOT( m_Plane.N, a_Ray.GetOrigin() ) + m_Plane.D) / d;
		if (dist > 0)
		{
			if (dist < a_Dist) 
			{
				a_Dist = dist;
				return HIT;
			}
		}
	}
	return MISS;
}

void CScene::InitScene()
{
	m_Primitive = new CPrimitive*[500];
	// ground plane
	m_Primitive[0] = new CPlanePrim( CVector3( 0, 1, 0 ), 4.4f );
	m_Primitive[0]->SetName( "plane" );
	m_Primitive[0]->GetMaterial()->SetReflection( 0.0f );
	m_Primitive[0]->GetMaterial()->SetRefraction( 0.0f );
	m_Primitive[0]->GetMaterial()->SetDiffuse( 1.0f );
	m_Primitive[0]->GetMaterial()->SetColor( Color( 0.4f, 0.3f, 0.3f ) );
	// big sphere
	m_Primitive[1] = new CSphere( CVector3( 2, 0.8f, 3 ), 2.5f );
	m_Primitive[1]->SetName( "big sphere" );
	m_Primitive[1]->GetMaterial()->SetReflection( 0.2f );
	m_Primitive[1]->GetMaterial()->SetRefraction( 0.8f );
	m_Primitive[1]->GetMaterial()->SetRefrIndex( 1.3f );
	m_Primitive[1]->GetMaterial()->SetColor( Color( 0.7f, 0.7f, 1.0f ) );
	// small sphere
	m_Primitive[2] = new CSphere( CVector3( -5.5f, -0.5, 7 ), 2 );
	m_Primitive[2]->SetName( "small sphere" );
	m_Primitive[2]->GetMaterial()->SetReflection( 0.5f );
	m_Primitive[2]->GetMaterial()->SetRefraction( 0.0f );
	m_Primitive[2]->GetMaterial()->SetRefrIndex( 1.3f );
	m_Primitive[2]->GetMaterial()->SetDiffuse( 0.1f );
	m_Primitive[2]->GetMaterial()->SetColor( Color( 0.7f, 0.7f, 1.0f ) );
	// light source 1
	m_Primitive[3] = new CSphere( CVector3( 0, 5, 5 ), 0.1f );
	m_Primitive[3]->Light( true );
	m_Primitive[3]->GetMaterial()->SetColor( Color( 0.4f, 0.4f, 0.4f ) );
	// light source 2
	m_Primitive[4] = new CSphere( CVector3( -3, 5, 1 ), 0.1f );
	m_Primitive[4]->Light( true );
	m_Primitive[4]->GetMaterial()->SetColor( Color( 0.6f, 0.6f, 0.8f ) );
	// extra sphere
	m_Primitive[5] = new CSphere( CVector3( -1.5f, -3.8f, 1 ), 1.5f );
	m_Primitive[5]->SetName( "extra sphere" );
	m_Primitive[5]->GetMaterial()->SetReflection( 0.0f );
	m_Primitive[5]->GetMaterial()->SetRefraction( 0.8f );
	m_Primitive[5]->GetMaterial()->SetColor( Color( 1.0f, 0.4f, 0.4f ) );
	// back plane
	m_Primitive[6] = new CPlanePrim( CVector3( 0.0f, 0, -1 ), 12 );
	m_Primitive[6]->SetName( "back plane" );
	m_Primitive[6]->GetMaterial()->SetReflection( 0.0f );
	m_Primitive[6]->GetMaterial()->SetRefraction( 0.0f );
	m_Primitive[6]->GetMaterial()->SetSpecular( 0 );
	m_Primitive[6]->GetMaterial()->SetDiffuse( 0.6f );
	m_Primitive[6]->GetMaterial()->SetColor( Color( 0.5f, 0.3f, 0.5f ) );
	// ceiling plane
	m_Primitive[7] = new CPlanePrim( CVector3( 0, -1, 0 ), 7.4f );
	m_Primitive[7]->SetName( "back plane" );
	m_Primitive[7]->GetMaterial()->SetReflection( 0.0f );
	m_Primitive[7]->GetMaterial()->SetRefraction( 0.0f );
	m_Primitive[7]->GetMaterial()->SetSpecular( 0 );
	m_Primitive[7]->GetMaterial()->SetDiffuse( 0.5f );
	m_Primitive[7]->GetMaterial()->SetColor( Color( 0.4f, 0.7f, 0.7f ) );
	// grid
	int prim = 8;

	for ( int x = 0; x < 8; x++ ) 
	for ( int y = 0; y < 7; y++ )
	{
		m_Primitive[prim] = new CSphere( CVector3( -4.5f + x * 1.5f, -4.3f + y * 1.5f, 10 ), 0.3f );
		m_Primitive[prim]->SetName( "grid sphere" );
		m_Primitive[prim]->GetMaterial()->SetReflection( 0 );
		m_Primitive[prim]->GetMaterial()->SetRefraction( 0 );
		m_Primitive[prim]->GetMaterial()->SetSpecular( 0.6f );
		m_Primitive[prim]->GetMaterial()->SetDiffuse( 0.6f );
		m_Primitive[prim]->GetMaterial()->SetColor( Color( 0.3f, 1.0f, 0.4f ) );
		prim++;
	}

	// set number of primitives
	m_Primitives = prim;
}
CScene::~CScene()
{
	delete m_Primitive;	
}
CSurface::CSurface( int a_Width, int a_Height ) :
	m_Width( a_Width ),
	m_Height( a_Height )
{
	m_Buffer  = new RGBQUAD*[a_Height];
	for(int l=0 ; l<a_Height; l++)
	{
		m_Buffer[l] = new RGBQUAD[a_Width];
	}
}
void CSurface::Clear()
{
	int s = m_Width * m_Height;
	for(int i=m_Height-1; i>=0; i--)
	{
		for(int j=0; j<m_Width; j++)
		{
			m_Buffer[i][j].rgbBlue =0;
			m_Buffer[i][j].rgbGreen=0;
			m_Buffer[i][j].rgbRed  =0;
			m_Buffer[i][j].rgbReserved = 0;
		
		}
	}
}



CSurface::~CSurface()
{
	delete [] m_Buffer;
}
CRayTraceEngine::CRayTraceEngine()
{
	m_Scene = new CScene();
}
CRayTraceEngine::~CRayTraceEngine()
{
	delete m_Scene;
}
void CRayTraceEngine::SetTarget(RGBQUAD** a_Dest,int a_Width,int a_Height)
{
	m_Dest = a_Dest;
	m_Width = a_Width;
	m_Height = a_Height;
}
void CRayTraceEngine::InitRender()
{
	// set firts line to draw to
	m_CurrLine = 20;
	// set pixel buffer address of first pixel
	m_PPos = m_CurrLine * m_Width;
	// screen plane in world space coordinates
	m_WX1 = -4, m_WX2 = 4, m_WY1 = m_SY = 3, m_WY2 = -3;
	// calculate deltas for interpolation
	m_DX = (m_WX2 - m_WX1) / m_Width;
	m_DY = (m_WY2 - m_WY1) / m_Height;
	m_SY += m_CurrLine * m_DY;
	// allocate space to store pointers to primitives for previous line
	m_LastRow = new CPrimitive*[m_Width];
	memset( m_LastRow, 0, m_Width * 4 );
}
CPrimitive* CRayTraceEngine::Raytrace( CRay& a_Ray, Color& a_Acc, int a_Depth, float a_RIndex, float& a_Dist )
{
	if (a_Depth > TRACEDEPTH) return 0;
	// trace primary ray
	a_Dist = 1000000.0f;
	CVector3 pi;
	CPrimitive* prim = 0;
	int result;
	// find the nearest intersection
	for ( int s = 0; s < m_Scene->GetNrPrimitives(); s++ )
	{
		CPrimitive* pr = m_Scene->GetPrimitive( s );
		int res;
		if (res = pr->Intersect( a_Ray, a_Dist )) 
		{
			prim = pr;
			result = res; // 0 = miss, 1 = hit, -1 = hit from inside primitive
		}
	}
	// no hit, terminate ray
	if (!prim) return 0;
	// handle intersection
	if (prim->IsLight())
	{
		// we hit a light, stop tracing
		a_Acc = Color( 1, 1, 1 );
	}
	else
	{
		// determine color at point of intersection
		pi = a_Ray.GetOrigin() + a_Ray.GetDirection() * a_Dist;
		// trace lights
		for ( int l = 0; l < m_Scene->GetNrPrimitives(); l++ )
		{
			CPrimitive* p = m_Scene->GetPrimitive( l );
			if (p->IsLight()) 
			{
				CPrimitive* light = p;
				// handle point light source
				float shade = 1.0f;
				if (light->GetType() == CPrimitive::SPHERE)
				{
					CVector3 L = ((CSphere*)light)->GetCentre() - pi;
					float tdist = LENGTH( L );
					L *= (1.0f / tdist);
					CRay r = CRay( pi + L * EPSILON, L );
					for ( int s = 0; s < m_Scene->GetNrPrimitives(); s++ )
					{
						CPrimitive* pr = m_Scene->GetPrimitive( s );
						if ((pr != light) && (pr->Intersect( r, tdist )))
						{
							shade = 0;
							break;
						}
					}
				}
				if (shade > 0)
				{
					// calculate diffuse shading
					CVector3 L = ((CSphere*)light)->GetCentre() - pi;
					NORMALIZE( L );
					CVector3 N = prim->GetNormal( pi );
					if (prim->GetMaterial()->GetDiffuse() > 0)
					{
						float dot = DOT( L, N );
						if (dot > 0)
						{
							float diff = dot * prim->GetMaterial()->GetDiffuse() * shade;
							// add diffuse component to ray color
							a_Acc += diff * prim->GetMaterial()->GetColor() * light->GetMaterial()->GetColor();
						}
					}
					// determine specular component
					if (prim->GetMaterial()->GetSpecular() > 0)
					{
						// point light source: sample once for specular highlight
						CVector3 V = a_Ray.GetDirection();
						CVector3 R = L - 2.0f * DOT( L, N ) * N;
						float dot = DOT( V, R );
						if (dot > 0)
						{
							float spec = powf( dot, 20 ) * prim->GetMaterial()->GetSpecular() * shade;
							// add specular component to ray color
							a_Acc += spec * light->GetMaterial()->GetColor();
						}
					}
				}
			}
		}
		// calculate reflection
		float refl = prim->GetMaterial()->GetReflection();
		if ((refl > 0.0f) && (a_Depth < TRACEDEPTH))
		{
			CVector3 N = prim->GetNormal( pi );
			CVector3 R = a_Ray.GetDirection() - 2.0f * DOT( a_Ray.GetDirection(), N ) * N;
			Color rcol( 0, 0, 0 );
			float dist;
			Raytrace( CRay( pi + R * EPSILON, R ), rcol, a_Depth + 1, a_RIndex, dist );
			a_Acc += refl * rcol * prim->GetMaterial()->GetColor();
		}
		// calculate refraction
		float refr = prim->GetMaterial()->GetRefraction();
		if ((refr > 0) && (a_Depth < TRACEDEPTH))
		{
			float rindex = prim->GetMaterial()->GetRefrIndex();
			float n = a_RIndex / rindex;
			CVector3 N = prim->GetNormal( pi ) * (float)result;
			float cosI = -DOT( N, a_Ray.GetDirection() );
			float cosT2 = 1.0f - n * n * (1.0f - cosI * cosI);
			if (cosT2 > 0.0f)
			{
				CVector3 T = (n * a_Ray.GetDirection()) + (n * cosI - sqrtf( cosT2 )) * N;
				Color rcol( 0, 0, 0 );
				float dist;
				Raytrace( CRay( pi + T * EPSILON, T ), rcol, a_Depth + 1, rindex, dist );
				// apply Beer's law
				Color absorbance = prim->GetMaterial()->GetColor() * 0.15f * -dist;
				Color transparency = Color( expf( absorbance.r ), expf( absorbance.g ), expf( absorbance.b ) );
				a_Acc += rcol * transparency;
			}
		}
	}
	// return pointer to primitive hit by primary ray
	return prim;
}
bool CRayTraceEngine::Render()
{
	
	// initialize timer
	int msecs = GetTickCount();
	// reset last found primitive pointer
	CPrimitive* lastprim = 0;
	//m_Width=40;//试一下的
	// render remaining lines
	for ( int y = m_CurrLine; y < (m_Height - 20); y++ )
	{
		m_SX = m_WX1;
		// render pixels for current line
		for ( int x = 0; x < m_Width; x++ )
		{
			// fire primary rays
			Color acc( 0, 0, 0 );
			CVector3 dir = CVector3( m_SX, m_SY, 0 ) - o;
			NORMALIZE( dir );
			CRay r( o, dir );
			float dist;
			CPrimitive* prim = Raytrace( r, acc, 1, 1.0f, dist );
			int red, green, blue;
			if (prim != lastprim)
			{
				lastprim = prim;
				Color acc( 0, 0, 0 );
				for ( int tx = -1; tx < 2; tx++ ) 
				for ( int ty = -1; ty < 2; ty++ )
				{
					CVector3 dir = CVector3( m_SX + m_DX * tx / 2.0f, m_SY + m_DY * ty / 2.0f, 0 ) - o;
					NORMALIZE( dir );
					CRay r( o, dir );
					float dist;
					CPrimitive* prim = Raytrace( r, acc, 1, 1.0f, dist );
				}
				red = (int)(acc.r * (256 / 9));
				green = (int)(acc.g * (256 / 9));
				blue = (int)(acc.b * (256 / 9));
			}
			else
			{
				red = (int)(acc.r * 256);
				green = (int)(acc.g * 256);
				blue = (int)(acc.b * 256);
			}
			if (red > 255) red = 255;
			if (green > 255) green = 255;
			if (blue > 255) blue = 255;
			m_Dest[y][x].rgbRed=red;
			m_Dest[y][x].rgbGreen=green;
			m_Dest[y][x].rgbBlue=blue;
			
			m_SX += m_DX;
		}
		m_SY += m_DY;
		// see if we've been working to long already
		/*
		if ((GetTickCount() - msecs) > 100) 
		{
			// return control to windows so the screen gets updated
			m_CurrLine = y + 1;
			return false;
		}
		*/
	}
	// all done
	return true;
}


void CScene::AddScene(int type)
{
	float r,colorr,colorg,colorb,centerx,centery,centerz;
	float reflect,refract,refrindex,dif;
	CAddSphere newsphere;
	switch(type)
	{
		case 1:
			
			if(IDOK==newsphere.DoModal())
			{
				r=newsphere.m_R;
				colorr=newsphere.m_ColorRed;
				colorg=newsphere.m_ColorGreen;
				colorb=newsphere.m_ColorBlue;
				centerx=newsphere.m_Centerx;
				centery=newsphere.m_Centery;
				centerz=newsphere.m_Centerz;
				reflect=newsphere.m_Refre;
				refract=newsphere.m_Refra;

				m_Primitive[m_Primitives] = new CSphere( CVector3( centerx,centery,centerz ),r );
				m_Primitive[m_Primitives]->SetName( "sphere" );
				m_Primitive[m_Primitives]->GetMaterial()->SetReflection( reflect );//0.5f
				m_Primitive[m_Primitives]->GetMaterial()->SetRefraction( refract );//0.0f
				m_Primitive[m_Primitives]->GetMaterial()->SetRefrIndex( 1.3f );
				m_Primitive[m_Primitives]->GetMaterial()->SetDiffuse( 0.1f );
				m_Primitive[m_Primitives]->GetMaterial()->SetColor( Color(colorr, colorg, colorb ) );
				m_Primitives++;


			}

			break;
		case 2:
			break;
	}
}

void CScene::DeleteLastObject()
{
	m_Primitives--;
}

void CRayTraceEngine::GetViewPoint(CVector3 ViewPoint)
{
	o=ViewPoint;
}

⌨️ 快捷键说明

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