Exemplo n.º 1
0
// -----------------------------------------------------------
// Engine::FindNearest
// Finds the nearest intersection in a KdTree for a ray
// -----------------------------------------------------------
int KDTree::FindNearestToRay( Ray& vRay, Vec3 &tmin, Vec3 &tmax, RayIntersectCallback callback, Matrix4x4 * temp )
{
	static bool bOutput = false;
	float tnear = 0;
	float tfar = ( tmax - tmin ).Length();
	float t;
	int retval = 0;
	float D[3];
	float O[3];
	VecToFloatArray( vRay.m_Direction, D );
	VecToFloatArray( vRay.m_Origin, O );
	// We assume ray fits in extents
	// clip ray segment to box
	static AABB bbox;
	bbox.Set( tmin, tmax );
	if( !bbox.IntersectRay( vRay, tnear, tfar ) )
		return 0;
	if( tnear < 0 || 
		tfar < 0 || 
		tnear > tfar )
		return 0;
	// init stack
	int entrypoint = 0, exitpoint = 1;
	// init traversal
	KDTreeNode* farchild, *currnode;
	farchild = 0;
	currnode = m_Root;
	m_Stack[entrypoint].t = tnear;
	if (tnear > 0.0f) 
	{
		m_Stack[entrypoint].pb[0] = O[0] + D[0]*tnear;
		m_Stack[entrypoint].pb[1] = O[1] + D[1]*tnear;
		m_Stack[entrypoint].pb[2] = O[2] + D[2]*tnear;
	}
	else
	{
		m_Stack[entrypoint].pb[0] = O[0];
		m_Stack[entrypoint].pb[1] = O[1];
		m_Stack[entrypoint].pb[2] = O[2];
	}
	m_Stack[exitpoint].t = tfar;
	m_Stack[exitpoint].pb[0] = O[0] + D[0]*tfar;
	m_Stack[exitpoint].pb[1] = O[1] + D[1]*tfar;
	m_Stack[exitpoint].pb[2]= O[2] + D[2]*tfar;
	m_Stack[exitpoint].node = 0;
	int dim = -1;
	// traverse kd-tree
	char buf[1024];

	static int aa = 0;
	if( bOutput )
	{
		sprintf( buf, "tfar: %f, tnear: %f\n", tfar, tnear );
		OutputDebugString( buf );
		OutputVector( vRay.m_Origin, "Ray origin" );
		OutputVector( vRay.m_Direction, "Ray direction" );
		OutputVector( O, "Ray origin2" );
		OutputVector( D, "Ray direction2" );
		OutputVector( m_Stack[ entrypoint ].pb, "entry" );
		sprintf( buf, "exit far: %f\n", m_Stack[exitpoint].t );
		OutputDebugString( buf );
		OutputVector( m_Stack[ exitpoint ].pb, "exit" );
	}
	KDTreeNode * lastNode = 0;
	g_Boxes.clear();
	vector< KDTreeNode * > nodesToCheck;
	while(currnode)
	{
		if( aa < 1 )
			DrawBox( currnode->bounds.m_Bounds[0], currnode->bounds.m_Bounds[1], temp );
		//Is not a leaf?
		while( currnode->pntidx < 0 )
		{		
			lastNode = currnode;
			dim = (dim + 1) % ndim;
			if( m_Stack[entrypoint].pb[dim] <= currnode->key )
			{
				if( m_Stack[exitpoint].pb[dim] <= currnode->key )
				{
					currnode = m_Root + currnode->leftIdx;
					continue;
				}
				farchild = m_Root + currnode->rightIdx; // GetRight();
				currnode = m_Root + currnode->leftIdx;
			}
			else 
			{
				if (m_Stack[exitpoint].pb[dim] > currnode->key)
				{
					currnode = m_Root + currnode->rightIdx;
					continue;
				}
				farchild = m_Root + currnode->leftIdx;
				currnode = m_Root + currnode->rightIdx; // GetRight();
			}
			
			t = (currnode->key - O[dim]) / D[dim];
			int tmp = exitpoint++;
			if (exitpoint == entrypoint) 
				exitpoint++;
			m_Stack[exitpoint].prev = tmp;
			m_Stack[exitpoint].t = t;
			m_Stack[exitpoint].node = farchild;
			m_Stack[exitpoint].pb[dim] = currnode->key;
			int nextaxis = (dim + 1) % ndim;
			int prevaxis = (dim + 2) % ndim;
			m_Stack[exitpoint].pb[nextaxis] = O[nextaxis] + t * D[nextaxis];
			m_Stack[exitpoint].pb[prevaxis] = O[prevaxis] + t * D[prevaxis];
		}
		if( aa < 1 )
				DrawBox( currnode->bounds.m_Bounds[0], currnode->bounds.m_Bounds[1], temp );			
			
		float dist = m_Stack[exitpoint].t;
		nodesToCheck.push_back( currnode );
		entrypoint = exitpoint;
		currnode = m_Stack[exitpoint].node;
		exitpoint = m_Stack[entrypoint].prev;
	}
	bool bfound = (*callback)( nodesToCheck );
	if( bfound )
	{
		return 1;
	}
//	return 0;
	//check by comparing all nodes
	nodesToCheck.clear();
	nodesToCheck.push_back( m_Root );
	bool bresult = (*callback)( nodesToCheck );
	if( bresult )
	{
		if( g_Boxes.size() > 0 && aa < 1 )
		{
			for( int i = 0; i < (int)g_Boxes.size(); i++ )
			{
				static DWORD msgHash_AddAxisAlignedBox = CHashString(_T("AddAxisAlignedBox")).GetUniqueID();
				EngineGetToolBox()->SendMessage(msgHash_AddAxisAlignedBox,sizeof(g_Boxes[i]), &g_Boxes[i] );
				OutputDebugString("Box:\t");
				OutputVector(	g_Boxes[i].min, "Min" );
				OutputVector(	g_Boxes[i].max, "Max" );
			}
			g_Boxes.clear();
			aa++;
			static CHashString h(_T("none"));
			ADDLINEPARAMS LineParam;
			LineParam.name = &h;
			LineParam.start = (*temp)*vRay.m_Origin;
			LineParam.end =  vRay.m_Origin + vRay.m_Direction*10000;
			LineParam.end = (*temp)*LineParam.end;
			LineParam.red = 0;
			LineParam.blue = 0;
			LineParam.green = 255;
			static DWORD msgHash_AddLine = CHashString(_T("AddLine")).GetUniqueID();
			EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );

		}
        return 1;
	}
	return 0;
}
Exemplo n.º 2
0
// -----------------------------------------------------------
// Find nearest ray 2
// -----------------------------------------------------------
int KDTree::FindNearestToRay2( Ray& vRay, Vec3 &tmin, Vec3 &tmax, RayIntersectCallback callback, Matrix4x4 * temp )
{
	static bool bOutput = false;
	float tnear = 0;
	float tfar = ( tmax - tmin ).Length();
	int retval = 0;
	float D[3];
	float O[3];
	VecToFloatArray( vRay.m_Direction, D );
	VecToFloatArray( vRay.m_Origin, O );
	// We assume ray fits in extents
	// clip ray segment to box
	static AABB bbox;
	static int aa = 0;
	bbox.Set( tmin, tmax );
	if( !bbox.IntersectRay( vRay, tnear, tfar ) )
		return 0;
	if( tnear < 0 || 
		tfar < 0 || 
		tnear > tfar )
		return 0;
	stack< RayFindStruct > nodeStack;
	vector< KDTreeNode * > nodesToCheck;
	g_Boxes.clear();
	nodeStack.push( RayFindStruct( m_Root, tnear, tfar ) );
	while( nodeStack.size() > 0 )
	{
		RayFindStruct curSearch = nodeStack.top();
		nodeStack.pop();
		DrawBox( curSearch.node->bounds.m_Bounds[0], curSearch.node->bounds.m_Bounds[1], temp );
		
		while( curSearch.node->pntidx < 0 )//is not a leaf
		{
			int dim = curSearch.node->axis;
			float tSplit = (curSearch.node->key - O[dim]) / D[dim];
			KDTreeNode * first = m_Root + curSearch.node->leftIdx;
			KDTreeNode * second = m_Root + curSearch.node->rightIdx;
			//check dimension
			if( D[dim] < 0 )
			{
				//swap
				KDTreeNode * temp;
				temp = first;
				first = second;
				second = temp;
			}
			if( tSplit >= curSearch.tmax 
				//|| tSplit < 0 
				)
			{
				curSearch.node = first;
			}
			else 
				if( tSplit <= curSearch.tmin )
			{
				curSearch.node = second;
			}
			else
			{
				nodeStack.push( RayFindStruct( second, tSplit, curSearch.tmax ) );
				curSearch.node = first;
				curSearch.tmax = tSplit;
			}
			DrawBox( curSearch.node->bounds.m_Bounds[0], curSearch.node->bounds.m_Bounds[1], temp );
		}
		assert( curSearch.node != NULL );
		//check triangles
		nodesToCheck.push_back( curSearch.node );
		bool bresult = (*callback)( nodesToCheck );
		if( bresult )
		{
			return 1;
		}
		nodesToCheck.clear();
	}
	return 0;
	if( tnear == tfar )
	{
		return 0;
	}
	nodesToCheck.clear();
	nodesToCheck.push_back( m_Root );
	bool bresult = (*callback)( nodesToCheck );
	if( bresult )
	{
		if( g_Boxes.size() > 0 && aa < 5 
			&&
			vRay.m_Origin.z > 1000 )
		{
			OutputDebugString("RAYDEBUG START----------------------\n");
			for( int i = 0; i < (int)g_Boxes.size(); i++ )
			{
				static DWORD msgHash_AddAxisAlignedBox = CHashString(_T("AddAxisAlignedBox")).GetUniqueID();
				EngineGetToolBox()->SendMessage(msgHash_AddAxisAlignedBox,sizeof(g_Boxes[i]), &g_Boxes[i] );
				OutputDebugString("Box:\t");
				OutputVector(	g_Boxes[i].min, "Min" );
				OutputVector(	g_Boxes[i].max, "Max" );
			}
			g_Boxes.clear();
			aa++;
			static CHashString h(_T("none"));
			ADDLINEPARAMS LineParam;
			LineParam.name = &h;
			LineParam.start = (*temp)*vRay.m_Origin;
			LineParam.end =  vRay.m_Origin + vRay.m_Direction*10000;
			LineParam.end = (*temp)*LineParam.end;
			LineParam.red = 0;
			LineParam.blue = 0;
			LineParam.green = 255;
			static DWORD msgHash_AddLine = CHashString(_T("AddLine")).GetUniqueID();
			EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
		}
        return 1;
	}
	return 0;
}
void LightMapGenerator::IntersectWithWorld( Ray &vRay, POTENTIAL_INTERSECTION_SORT &sortedIntersections )
{
	float rayTmin, rayTMax;
	Vec3 LightOrigin;	
	double t, u, v;
	Ray rRay;
	static CHashString meshType(_T("MeshParameterization") );
	for( int j = 0; j < (int)m_MeshObjects.size(); j++ )
	{
		//now check each mesh's triangles
		CHashString &meshName= m_MeshObjects[ j ];
		Matrix4x4 meshTransform;
		Matrix4x4 meshInverseTransform;
		static DWORD msgHash_GetMeshTransform = CHashString(_T("GetMeshTransform")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_GetMeshTransform, sizeof( Matrix4x4 ), &meshTransform, &meshName, &meshType );
		static DWORD msgHash_GetMeshInverseTransform = CHashString(_T("GetMeshInverseTransform")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_GetMeshInverseTransform, sizeof( Matrix4x4 ), &meshInverseTransform, &meshName, &meshType );
		
		AABB meshBounds;
		static DWORD msgHash_GetAABB = CHashString(_T("GetAABB")).GetUniqueID();
		m_ToolBox->SendMessage(msgHash_GetAABB, sizeof( AABB ), &meshBounds, &meshName, &meshType );
		
		//transform this by inverse matrix
		LightOrigin = meshInverseTransform*vRay.m_Origin;
		Matrix3x3 matRotate;
		matRotate.SetFrom4x4( meshInverseTransform.GetMatrix() );
		Vec3 transformedDir = matRotate*vRay.m_Direction;
		transformedDir.Normalize();
		rRay = Ray( LightOrigin, transformedDir );
		
		if( meshBounds.IntersectRay( rRay, rayTmin, rayTMax ) )
		{
			//cull mesh away that need not be tested
			int face = 0;
			//test intersection
			MESHPARAMINTERSECTRAYTRIANGLEMSG intersectMsg;
			intersectMsg.inRay = &rRay;
			static DWORD msgHash_IntersectRayTriangle = CHashString(_T("IntersectRayTriangle")).GetUniqueID();
			m_ToolBox->SendMessage(msgHash_IntersectRayTriangle, sizeof( MESHPARAMINTERSECTRAYTRIANGLEMSG ), &intersectMsg, &meshName, &meshType );
		
			if( intersectMsg.outCollided == true)
			{
				face = intersectMsg.outFaceIndex;
				t = intersectMsg.outIntersectionDistance;
				u = intersectMsg.outULength;
				v = intersectMsg.outVLength;
				if( t < 0 )
				{
					continue;
				}
				PotentialIntersection pIntersection;
				pIntersection.faceIndex = face;
				pIntersection.t = t;
				pIntersection.u = u;
				pIntersection.v = v;
				pIntersection.mesh = meshName;
				pIntersection.transformedRay = rRay;
				sortedIntersections.insert( POTENTIAL_INTERSECTION_SORT_PAIR( (float)t, pIntersection ) );
			}
		}
		
	}
}