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

📄 graytrace.cpp

📁 一个非常有用的开源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
/*	Copyright (C) 2006, Mike Gashler	This library is free software; you can redistribute it and/or	modify it under the terms of the GNU Lesser General Public	License as published by the Free Software Foundation; either	version 2.1 of the License, or (at your option) any later version.	see http://www.gnu.org/copyleft/lesser.html*/#include "GRayTrace.h"#include "GMacros.h"#include "GPointerQueue.h"#include "GXML.h"#include "GBits.h"#include "GHashTable.h"void GRayTraceVector::ComputeReflectionVector(GRayTraceVector* pRay, GRayTraceVector* pNormal){	Copy(pNormal);	Multiply(pNormal->DotProduct(pRay) * -2);	Add(pRay);}// -----------------------------------------------------------------------------#define MIN_RAY_DISTANCE ((GRayTraceReal).001)GRayTraceRay::GRayTraceRay(){	m_indexOfRefraction = 1;}GRayTraceRay::GRayTraceRay(GRayTraceRay* pThat){	m_indexOfRefraction = pThat->m_indexOfRefraction;}GRayTraceRay::~GRayTraceRay(){}bool GRayTraceRay::ComputeTransmissionVector(GRayTraceVector* pDirectionVector, GRayTraceVector* pTransmissionVector, GRayTraceReal oldIndexOfRefraction, GRayTraceReal newIndexOfRefraction){	double ratio = (double)oldIndexOfRefraction / newIndexOfRefraction;	double comp = (double)pDirectionVector->DotProduct(&m_normalVector);	double tmp = (double)1 - (ratio * ratio * ((double)1 - (comp * comp)));	if(tmp < 0)		return false;	pTransmissionVector->Copy(&m_normalVector);	pTransmissionVector->Multiply((GRayTraceReal)(-ratio * comp - sqrt(tmp)));	GRayTraceVector x(pDirectionVector);	x.Multiply((GRayTraceReal)ratio);	pTransmissionVector->Add(&x);	pTransmissionVector->Normalize();	return true;}void GRayTraceRay::ComputeRandomDiffuseVector(GRayTraceVector* pOutVector){	GRayTraceVector u;	GRayTraceVector v;	if(ABS(m_normalVector.m_vals[0]) < .5) // if N is not co-linear with (1, 0, 0)	{		v.m_vals[0] = 1;		u.CrossProduct(&m_normalVector, &v);	}	else	{		v.m_vals[1] = 1;		u.CrossProduct(&m_normalVector, &v);	}	u.Normalize();	v.CrossProduct(&u, &m_normalVector);	double a, b, c;	while(true)	{		a = GBits::GetRandomDouble() * 2 - 1;		b = GBits::GetRandomDouble() * 2 - 1;		if(a * a + b * b < 1)			break;	}	c = sqrt(1.0 - (a * a + b * b));	u.Multiply((GRayTraceReal)a);	v.Multiply((GRayTraceReal)b);	pOutVector->Copy(&m_normalVector);	pOutVector->Multiply((GRayTraceReal)c);	pOutVector->Add(&u);	pOutVector->Add(&v);}void GRayTraceRay::JitterRay(GRayTraceVector* pVector, GRayTraceReal jitter){	pVector->m_vals[0] += (jitter * (GRayTraceReal)(GBits::GetRandomDouble() * 2 - 1));	pVector->m_vals[1] += (jitter * (GRayTraceReal)(GBits::GetRandomDouble() * 2 - 1));	pVector->m_vals[2] += (jitter * (GRayTraceReal)(GBits::GetRandomDouble() * 2 - 1));	pVector->Normalize();}void GRayTraceRay::Cast(GRayTraceScene* pScene, GRayTraceVector* pRayOrigin, GRayTraceVector* pDirectionVector, int nMaxDepth){	// Find the object	GRayTraceReal distance;	GAssert(pScene->GetBoundingBoxTree(), "You must to call RenderBegin first?");	GRayTraceObject* pClosestObject = pScene->GetBoundingBoxTree()->FindClosestIntersection(pRayOrigin, pDirectionVector, &distance);	if(!pClosestObject)	{		m_color.Copy(pScene->GetBackgroundColor());		return;	}	// Compute the collision point	m_collisionPoint.Copy(pDirectionVector);	m_collisionPoint.Multiply(distance);	m_collisionPoint.Add(pRayOrigin);	// Compute the normal	m_bHitTexture = false;	pClosestObject->ComputeNormalVector(this);	if(!pClosestObject->IsCulled())	{		if(pDirectionVector->DotProduct(&m_normalVector) > 0)			m_normalVector.Multiply(-1);	}	// Compute the reflection vector	m_reflectionVector.ComputeReflectionVector(pDirectionVector, &m_normalVector);	// Compute the color	GRayTraceMaterial* pMaterial = pClosestObject->GetMaterial();	pMaterial->ComputeColor(pScene, this, true, true);	// Cast child rays	if(nMaxDepth > 0)	{		// Reflection		GRayTraceColor* pReflectedColor = pMaterial->GetColor(GRayTraceMaterial::Reflective, this);		if(!pReflectedColor->IsBlack())		{			GRayTraceReal jitter = pMaterial->GetGlossiness();			if(jitter > 0)				JitterRay(&m_reflectionVector, jitter);			GRayTraceRay reflectionRay(this);			reflectionRay.Cast(pScene, &m_collisionPoint, &m_reflectionVector, nMaxDepth - 1);			reflectionRay.m_color.Multiply(pReflectedColor);			m_color.Add(&reflectionRay.m_color);		}		// Transmission		GRayTraceColor* pTransmissionColor = pMaterial->GetColor(GRayTraceMaterial::Transmissive, this);		if(!pTransmissionColor->IsBlack())		{			// Compute transmission ray			GRayTraceReal newIndexOfRefraction;			if(m_indexOfRefraction > .9999 && m_indexOfRefraction < 1.0001)				newIndexOfRefraction = pMaterial->GetIndexOfRefraction();			else				newIndexOfRefraction = 1;			GRayTraceVector transmissionVector;			if(!ComputeTransmissionVector(pDirectionVector, &transmissionVector, m_indexOfRefraction, newIndexOfRefraction))			{				// total internal reflection occurs				transmissionVector.Copy(&m_reflectionVector);				newIndexOfRefraction = m_indexOfRefraction;			}			// Cast transmission ray			GRayTraceReal jitter = pMaterial->GetCloudiness();			if(jitter > 0)				JitterRay(&transmissionVector, jitter);			GRayTraceRay transmissionRay(this);			transmissionRay.m_indexOfRefraction = newIndexOfRefraction;			transmissionRay.Cast(pScene, &m_collisionPoint, &transmissionVector, nMaxDepth - 1);			transmissionRay.m_color.Multiply(pTransmissionColor);			m_color.Add(&transmissionRay.m_color);		}	}}#define PATH_TRACER_PROB_REFLECTIVE 0.5#define PATH_TRACER_PROB_TRANSMISSIVE 0.3void GRayTraceRay::Trace(GRayTraceScene* pScene, GRayTraceVector* pRayOrigin, GRayTraceVector* pDirectionVector, int nMaxDepth, bool bEmissive){	// Find the object	GRayTraceReal distance;	GRayTraceObject* pClosestObject = pScene->GetBoundingBoxTree()->FindClosestIntersection(pRayOrigin, pDirectionVector, &distance);	if(!pClosestObject)	{		m_color.Copy(pScene->GetBackgroundColor());		return;	}	// Compute the collision point	m_collisionPoint.Copy(pDirectionVector);	m_collisionPoint.Multiply(distance);	m_collisionPoint.Add(pRayOrigin);	// Compute the normal	m_bHitTexture = false;	pClosestObject->ComputeNormalVector(this);	if(!pClosestObject->IsCulled())	{		if(pDirectionVector->DotProduct(&m_normalVector) > 0)			m_normalVector.Multiply(-1);	}	// Compute the reflection vector	m_reflectionVector.ComputeReflectionVector(pDirectionVector, &m_normalVector);	// Compute the color	GRayTraceMaterial* pMaterial = pClosestObject->GetMaterial();	pMaterial->ComputeColor(pScene, this, false, false);	if(bEmissive)		m_color.Add(pMaterial->GetColor(GRayTraceMaterial::Emissive, this));	// Cast child rays	if(nMaxDepth > 0)	{		GRayTraceColor* pReflectedColor = pMaterial->GetColor(GRayTraceMaterial::Reflective, this);		GRayTraceColor* pTransmissionColor = pMaterial->GetColor(GRayTraceMaterial::Transmissive, this);		GRayTraceColor* pDiffuseColor = pMaterial->GetColor(GRayTraceMaterial::Diffuse, this);		GRayTraceReal lumReflective = pReflectedColor->r * (GRayTraceReal)0.299 + pReflectedColor->g * (GRayTraceReal)0.587 + pReflectedColor->b * (GRayTraceReal)0.114;		GRayTraceReal lumTransmissive = pTransmissionColor->r * (GRayTraceReal)0.299 + pTransmissionColor->g * (GRayTraceReal)0.587 + pTransmissionColor->b * (GRayTraceReal)0.114;		GRayTraceReal lumDiffuse = pDiffuseColor->r * (GRayTraceReal)0.299 + pDiffuseColor->g * (GRayTraceReal)0.587 + pDiffuseColor->b * (GRayTraceReal)0.114;		GRayTraceReal lumSum = lumReflective + lumTransmissive + lumDiffuse;		if(lumSum > .0001)		{			lumReflective /= lumSum;			lumTransmissive /= lumSum;			lumDiffuse /= lumSum;			double d = GBits::GetRandomDouble();			if(d < lumReflective)			{				// Reflective path				GRayTraceReal jitter = pMaterial->GetGlossiness();				if(jitter > 0)					JitterRay(&m_reflectionVector, jitter);				GRayTraceRay reflectionRay(this);				reflectionRay.Trace(pScene, &m_collisionPoint, &m_reflectionVector, nMaxDepth - 1, true);				reflectionRay.m_color.Multiply(pReflectedColor);				reflectionRay.m_color.Multiply((GRayTraceReal)1.0 / lumReflective); // Compensate for less than one probability of selecting this path				m_color.Add(&reflectionRay.m_color);			}			else if(d < lumReflective + lumTransmissive)			{				// Compute transmission ray				GRayTraceReal newIndexOfRefraction;				if(m_indexOfRefraction > .9999 && m_indexOfRefraction < 1.0001)					newIndexOfRefraction = pMaterial->GetIndexOfRefraction();				else					newIndexOfRefraction = 1;				GRayTraceVector transmissionVector;				if(!ComputeTransmissionVector(pDirectionVector, &transmissionVector, m_indexOfRefraction, newIndexOfRefraction))				{					// total internal reflection occurs					transmissionVector.Copy(&m_reflectionVector);					newIndexOfRefraction = m_indexOfRefraction;				}				// Cast transmission ray				GRayTraceReal jitter = pMaterial->GetCloudiness();				if(jitter > 0)					JitterRay(&transmissionVector, jitter);				GRayTraceRay transmissionRay(this);				transmissionRay.m_indexOfRefraction = newIndexOfRefraction;				transmissionRay.Trace(pScene, &m_collisionPoint, &transmissionVector, nMaxDepth - 1, true);				transmissionRay.m_color.Multiply(pTransmissionColor);				transmissionRay.m_color.Multiply((GRayTraceReal)1.0 / lumTransmissive); // Compensate for less than one probability of selecting this path				m_color.Add(&transmissionRay.m_color);			}			else			{				// Diffuse path				GRayTraceVector diffuseVector;				ComputeRandomDiffuseVector(&diffuseVector);				GRayTraceRay diffuseRay(this);				diffuseRay.Trace(pScene, &m_collisionPoint, &diffuseVector, nMaxDepth - 1, false);				diffuseRay.m_color.Multiply(pDiffuseColor);				diffuseRay.m_color.Multiply((GRayTraceReal)1.0 / lumDiffuse); // Compensate for less than one probability of selecting this path				m_color.Add(&diffuseRay.m_color);			}		}	}}// I'm not sure it really makes sense to store the texture coordinates// in the ray, but somehow this data needs to be passed from the tri-mesh// to the material, and the ray is a convenient carriervoid GRayTraceRay::SetTextureCoords(GRayTraceReal x, GRayTraceReal y){	m_bHitTexture = true;	m_textureX = x;	m_textureY = y;}void GRayTraceRay::GetTextureCoords(GRayTraceReal* x, GRayTraceReal* y){	*x = m_textureX;	*y = m_textureY;}// -----------------------------------------------------------------------------void GRayTraceCamera::ComputeSideVector(){	GRayTraceVector n(&m_lookAtPoint);	n.Subtract(&m_lookFromPoint);	m_viewSideVector.CrossProduct(&m_viewUpVector, &n);	m_viewUpVector.Normalize();	m_viewSideVector.Normalize();}void GRayTraceCamera::SetRoll(GRayTraceReal angle){	GRayTraceVector z(&m_lookAtPoint);	z.Subtract(&m_lookFromPoint);	GRayTraceVector x;	GRayTraceReal cosAngle = (GRayTraceReal)cos(angle);	x.m_vals[0] = cosAngle * z.m_vals[2];	x.m_vals[1] = (GRayTraceReal)sin(angle);	x.m_vals[2] = cosAngle * (-z.m_vals[0]);	m_viewUpVector.CrossProduct(&z, &x);	if(m_viewUpVector.GetMagnitudeSquared() == 0)		m_viewUpVector.m_vals[0] = 1;	ComputeSideVector();}// -----------------------------------------------------------------------------GRayTraceScene::GRayTraceScene(): m_backgroundColor(1, (GRayTraceReal).6, (GRayTraceReal).7, (GRayTraceReal).5),  m_ambientLight(1, (GRayTraceReal).3, (GRayTraceReal).3, (GRayTraceReal).3){	m_pMaterials = new GPointerArray(256);	m_pMeshes = new GPointerArray(64);	m_pObjects = new GPointerArray(1024);	m_pLights = new GPointerArray(32);	m_pCamera = new GRayTraceCamera();	m_pBoundingBoxTree = NULL;	m_pImage = NULL;	m_pDistanceMap = NULL;	m_nY = -1;	m_toneMappingConstant = .5;	m_eMode = FAST_RAY_TRACE;}GRayTraceScene::~GRayTraceScene(){	int n, nCount;	// Materials	nCount = m_pMaterials->GetSize();	for(n = 0; n < nCount; n++)		delete((GRayTraceMaterial*)m_pMaterials->GetPointer(n));	delete(m_pMaterials);	// Meshes	nCount = m_pMeshes->GetSize();	for(n = 0; n < nCount; n++)		delete((GRayTraceTriMesh*)m_pMeshes->GetPointer(n));	delete(m_pMeshes);	// Objects	nCount = m_pObjects->GetSize();	for(n = 0; n < nCount; n++)		delete((GRayTraceObject*)m_pObjects->GetPointer(n));	delete(m_pObjects);	// Lights	nCount = m_pLights->GetSize();	for(n = 0; n < nCount; n++)		delete((GRayTraceLight*)m_pLights->GetPointer(n));	delete(m_pBoundingBoxTree);	delete(m_pCamera);	delete(m_pImage);	delete(m_pDistanceMap);}int GRayTraceScene::GetObjectCount(){	return m_pObjects->GetSize();}GRayTraceObject* GRayTraceScene::GetObject(int n){	return (GRayTraceObject*)m_pObjects->GetPointer(n);}int GRayTraceScene::GetLightCount(){	return m_pLights->GetSize();}GRayTraceLight* GRayTraceScene::GetLight(int n){	return (GRayTraceLight*)m_pLights->GetPointer(n);}void GRayTraceScene::AddMaterial(GRayTraceMaterial* pMaterial){	m_pMaterials->AddPointer(pMaterial);}void GRayTraceScene::AddMesh(GRayTraceTriMesh* pMesh){	m_pMeshes->AddPointer(pMesh);	int nCount = pMesh->GetTriangleCount();	int i;	for(i = 0; i < nCount; i++)		AddObject(new GRayTraceTriangle(pMesh, i));}void GRayTraceScene::AddObject(GRayTraceObject* pObject){	m_pObjects->AddPointer(pObject);}void GRayTraceScene::AddLight(GRayTraceLight* pLight){	m_pLights->AddPointer(pLight);}void GRayTraceScene::ActivateDistanceMap(){	if(m_pDistanceMap)		delete[] m_pDistanceMap;	m_pDistanceMap = new GRayTraceReal[m_pCamera->GetImageWidth() * m_pCamera->GetImageHeight()];}void GRayTraceScene::RenderBegin(){	// Allocate an image	if(!m_pImage)		m_pImage = new GImage();	int nWidth = m_pCamera->GetImageWidth();	int nHeight = m_pCamera->GetImageHeight();	m_pImage->SetSize(nWidth, nHeight);	m_pImage->Clear(0xff808080);	// Rebuild the bounding box tree	delete(m_pBoundingBoxTree);	m_pBoundingBoxTree = GRayTraceBoundingBoxBase::MakeBoundingBoxTree(m_pObjects);	// Precompute vectors	m_pCamera->ComputeSideVector();	GRayTraceVector n(m_pCamera->GetLookAtPoint());	n.Subtract(m_pCamera->GetLookFromPoint());	GRayTraceVector v(m_pCamera->GetViewUpVector());	GRayTraceVector u(m_pCamera->GetViewSideVector());	GRayTraceReal halfViewHeight = (GRayTraceReal)(tan(m_pCamera->GetViewAngle() / 2) * sqrt(n.GetMagnitudeSquared()));	GRayTraceReal halfViewWidth = halfViewHeight * nWidth / nHeight;	u.Multiply(halfViewWidth);	v.Multiply(halfViewHeight);	m_pixSide.Copy(m_pCamera->GetLookAtPoint());	m_pixSide.Subtract(&u);	m_pixSide.Subtract(&v);	m_pixDX.Copy(&u);	m_pixDX.Multiply((GRayTraceReal)2 / nWidth);	m_pixDY.Copy(&v);	m_pixDY.Multiply((GRayTraceReal)2 / nHeight);	m_nY = nHeight - 1;}GColor GRayTraceScene::RenderPixel(GRayTraceRay* pRay, GRayTraceVector* pScreenPoint, GRayTraceReal* pDistance){	GRayTraceVector directionVector(pScreenPoint);	directionVector.Subtract(m_pCamera->GetLookFromPoint());	directionVector.Normalize();	pRay->Cast(this, m_pCamera->GetLookFromPoint(), &directionVector, m_pCamera->GetMaxDepth());

⌨️ 快捷键说明

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