bool IntersectRayToBox( const LVector3& P, const LVector3& A, const LVector3& Pos, LVector3* V, const LVector3& Size, LVector3& isect )
{
	float Sign[] = { -1, -1, -1, +1, +1, +1 };

	// distance to source point;
	float _dist = -1.0f;

	bool Intersection = false;

	// check six faces
	for ( int i = 0 ; i < 6 ; i++ )
	{
		LVector3 Pt = Sign[i] * V[i % 3] * Size[i % 3] * 0.5f;
		LVector3 N = Pt.GetNormalized();

		Pt = P + Pt;

		float D = N.Dot( Pt );

		LVector3 LocalISect;

		if ( IntersectRayToPlane( P, A, N, D, LocalISect ) )
		{
			// plane vectors
			LVector3 V1 = V[( i+1 )%3];
			LVector3 V2 = V[( i+2 )%3];

			float szX = Size[( i+1 )%3];
			float szY = Size[( i+2 )%3];

			// project to plane
			float x = ( LocalISect - Pt ).Dot( V1 );
			float y = ( LocalISect - Pt ).Dot( V2 );

			// check if the point is inside the rectangle
			if ( x > -szX / 2 && x < szX / 2 && y > -szY / 2 && y < szY / 2 )
			{
				Intersection = true;
				// it is, compare its distance to P - to select the closest one
				float _newDist = ( isect - P ).Length();

				if ( _dist < 0.0f || _newDist < _dist )
				{
					isect = LocalISect;
					_dist = _newDist;
				}
			}
		}
	}

	return Intersection;
}
Beispiel #2
0
// (Re)generate representing geometry (beads and sticks) for the graph/curve
clGeom* clGraph::CreateGraphGeometry( float BeadRadius, float TubeRadius, float EdgeArrowSize, bool UseCubes, clMaterial* BeadMaterial, clMaterial* StickMaterial, clMaterial* EdgeArrowMaterial )
{
	clMesh* Mesh = Env->Resources->CreateMesh();

	int VtxMaterialID = Mesh->AddMaterial( BeadMaterial->GetMaterialDesc() );

	// 1. points(vertices) are spheres
	for ( size_t i = 0 ; i < FVertices.size() ; i++ )
	{
//    int VtxGeomID = static_cast<int>(i);

		clVertexAttribs* VtxVA;

		LVector3 BoxMin( -BeadRadius, -BeadRadius, -BeadRadius );
		LVector3 BoxMax( +BeadRadius, +BeadRadius, +BeadRadius );

		// name it for picking
		LString VtxName = LString( "Vertex " ) + LStr::ToStr( i );

		if ( UseCubes )
		{

			FIXME( "hack, resources should also create a VA ? Or it is a geomserv ?" )
			// clGeomServ::CreateAxisAlignedBox(BoxMin, BoxMax, false);
			VtxVA = Env->Resources->CreateBox( BoxMin, BoxMax )->GetCurrentMesh()->GetRigid( 0 );
		}
		else
		{
			// it does not work...
//       VtxVA = Env->Resources->CreateSphere();
			VtxVA = Env->Resources->CreateBox( BoxMin, BoxMax )->GetCurrentMesh()->GetRigid( 0 );
		}

		LVector3 VtxPos = FVertices[i];

		LMatrix4 VtxTransform = LMatrix4::GetTranslateMatrix( VtxPos );

		if ( UseCubes )
		{
			LQuaternion VtxOrientation = FLocalOrientations[i];

			// orient the cube at point, if needed
			VtxTransform = ComposeTransformation( VtxPos, LMatrix4( VtxOrientation.ToMatrix3() ) ); // add rotation from LocalOrientation
		}

		Mesh->AddVertexAttribs( VtxName, VtxVA, VtxTransform, -1, VtxMaterialID );
	}

	// 2. render arrows for oriented edges
	int ArrowMaterialID = -1;

	if ( FOriented && EdgeArrowMaterial )
	{
		ArrowMaterialID = Mesh->AddMaterial( EdgeArrowMaterial->GetMaterialDesc() );
	}

// map< pair<int,int> > ProcessedEdges;

	int EdgeMaterialID = Mesh->AddMaterial( StickMaterial->GetMaterialDesc() );

	// 3. render lines from point to point ("tubes"), avoiding duplicate generation for non-oriented edges
	for ( size_t i = 0; i < FEdge0.size() ; i++ )
	{
		int v1 = FEdge0[i];
		int v2 = FEdge1[i];

		LVector3 v1pos = FVertices[v1];
		LVector3 v2pos = FVertices[v2];

		LVector3 Dir = ( v2pos - v1pos );
		LVector3 DirN = Dir.GetNormalized();
		LVector3 EndPointDir = -Dir.Length() * DirN * ( EdgeArrowSize );

		LVector3 Offset = DirN * EdgeArrowSize;

		clVertexAttribs* EdgeVA = clGeomServ::CreateTube( 10, v1pos + Offset, Dir - Offset, TubeRadius, false );

		// name the edge for picking
		LString EdgeName = LString( "Edge " ) + LStr::ToStr( v1 ) + LString( " " ) + LStr::ToStr( v2 );

		LMatrix4 EdgeTransform = LMatrix4::Identity();

		Mesh->AddVertexAttribs( EdgeName, EdgeVA, EdgeTransform, -1, EdgeMaterialID );

		FIXME( "avoid duplicates, use processed edges list" )

		// add arrow, if required
		if ( FOriented )
		{
			clVertexAttribs* ArrowVA = clGeomServ::CreateTube( 10, v2pos - Offset, -EndPointDir, TubeRadius * 2.0f , true );

			LString ArrowName = LString( "Arrow_" ) + EdgeName;

			LMatrix4 ArrowTransform = LMatrix4::Identity();

			Mesh->AddVertexAttribs( ArrowName, ArrowVA, ArrowTransform, -1, ArrowMaterialID );
		}
	}

	clGeom* Geom = Env->Resources->CreateGeom();
	Geom->SetMesh( Mesh );

	return Geom;
}