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

📄 cvhittst.cpp

📁 Windows上的MUD客户端程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				name.MakeLower();
				if(!boolFound && name == "xch_hint")
				{
					hint = pChild->string.value.getString();
					boolFound = true;
				}
				if(name == "xch_cmd")
				{
					cmd = pChild->string.value.getString();
				}
			}
		}

	}
	if(!boolFound)		// use the href as the hint
	{
		name = GetAnchorNode()->name.value.getString();
		if(!name.IsEmpty() && name != "<Undefined info>")
		{ 
			hint = name;
			boolFound = true;
		}
	}
	if(!cmd.IsEmpty())
	{
		string tmp = hint;
		hint = cmd;
		if(boolFound)
		{
			hint += " (" + tmp + ")";
		}
		boolFound = true;
	}

	return boolFound;
}

#if defined(CH_USE_3DR)
#endif	   // CH_USE_3DR


bool ChHittestIterator::DoNode(ChQvInstance& inst)
{
	bool boolKeepGoing = true;
	switch(GetVisitType())
	{
		case beforeChildren:
		{
			bool ImHit = false;
						   // GetBounds && check em
			ChQvBounds bounds;
			inst.GetBounds(bounds);

			//check instance's bounds
			GxVec3f hPt;
			ImHit = bounds.HitTest(GetRenderContext(), m_iX, m_iY, hPt); // hit me
			SetDoKids(ImHit); 

			break;
		}
		case afterChildren:
		{
			break;			 
		}
		case isLeaf:
		{
			boolKeepGoing = true; 	// need logic for first find, etc here
			inst.Hittest(GetRenderContext(), this);
			break;
		}
	}
	return boolKeepGoing;

};

void ChHittestIterator::Add(ChQvInstance *pInstance, const GxVec3f &pt)
{
	m_instances.AddTail(ChInstanceHit(pInstance, pt));
};

bool ChHittestIterator::GetHit( ChQvInstance *& closest, GxVec3f &pt)
{
	if(m_instances.IsEmpty()) return false;
	#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
	float distance = 1e17;		// way far away
	ChPosition pos = m_instances.GetHeadPosition();
    while (pos)
    {
        ChInstanceHit &bucket = m_instances.GetNext(pos);
		
		// Transform to screen space
		#if (defined(CH_USE_RLAB))
		RLIMViewVertex ptInScreen;
		
		RLIMTransformVertices
        (   GetRenderContext()->GetViewport(), 
        	bucket.m_pInstance->GetFrame(),
            (RLIMPositionVector*)&(bucket.m_pt),
            &ptInScreen,
            sizeof(RLIMPositionVector), 
            sizeof(RLIMViewVertex),
            1,
            1
        );
		bool boolUseIt = ptInScreen.sz >= 0 && ptInScreen.sz < distance; 

		if(boolUseIt)
		{
			distance = ptInScreen.sz;
			closest =  bucket.m_pInstance;
			pt = bucket.m_pt;
		}
		#elif (defined(CH_USE_D3D) && defined(CH_IMMED_MODE))

		#pragma message("D3D Immediate mode hittesting not done")
		bool boolUseIt = false; 

		#endif

			
    }

	#endif
	return true;
};

bool ChCollisionIterator::DoNode(ChQvInstance& inst)
{
	bool boolKeepGoing = true;
	switch(GetVisitType())
	{
		case beforeChildren:
		{
			bool ImHit = true;
						   // GetBounds && check em
			ChQvBounds bounds;
			inst.GetBounds(bounds);

			//check group instance's bounds
			GxVec3f hPt;
			//ImHit = bounds.Test(GetRenderContext(), m_iX, m_iY, hPt); // hit me  TODO ???????!!!!!!!!!!!!!!!
			SetDoKids(ImHit); 

			break;
		}
		case afterChildren:
		{
			break;			 
		}
		case isLeaf:
		{
			boolKeepGoing = true; 	// need logic for first find, etc here
			inst.CollisionTest(GetRenderContext(), this);
			break;
		}
	}
	return boolKeepGoing;

};

void ChCollisionIterator::Add(ChQvInstance *pInstance, float t)
{
	m_instances.AddTail(ChInstanceHit(pInstance, t));
};

bool ChCollisionIterator::GetHit( ChQvInstance *& closest,float &t)
{
	if(m_instances.IsEmpty()) return false;
	#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
	ChPosition pos = m_instances.GetHeadPosition();
	bool boolHit = false;
    while (pos)
    {
        ChInstanceHit &bucket = m_instances.GetNext(pos);
		
		if(!boolHit || (bucket.m_t < t && bucket.m_t >= 0))
		{
			boolHit = true;
			closest =  bucket.m_pInstance;
			t = bucket.m_t;
		}
    }

	return boolHit;
	#endif
};


/* derived from Graphics Gems II intsph.c
/* ----	intsph - Intersect a ray with a sphere. -----------------------	*/
/*									*/
/*									*/
/*	Description:							*/
/*	    Intsph determines the intersection of a ray with a sphere.	*/
/*									*/
/*	On entry:							*/
/*	    raybase = The coordinate defining the base of the		*/
/*		      intersecting ray.					*/
/*	    raycos  = The direction cosines of the above ray.		*/
/*	    center  = The center location of the sphere.		*/
/*	    radius  = The radius of the sphere.				*/
/*									*/
/*	On return:							*/
/*	    rin     = The entering distance of the intersection.	*/
/*	    rout    = The leaving  distance of the intersection.	*/
/*									*/
/*	Returns:  True if the ray intersects the sphere.		*/
/*									*/
/* --------------------------------------------------------------------	*/


int	intsph(const GxVec3f &raybase, const GxVec3f &raycos, const GxVec3f &center, float radius, float &rin, float &rout)
{
	int	hit;			/* True if ray intersects sphere*/
	double	dx, dy, dz;		/* Ray base to sphere center	*/
	double	bsq, u, disc;
	double	root;


	dx   = raybase.x() - center.x();
	dy   = raybase.y() - center.y();
	dz   = raybase.z() - center.z();
	bsq  = dx*raycos.x() + dy*raycos.y() + dz*raycos.z(); 
	u    = dx*dx + dy*dy + dz*dz - radius*radius;
	disc = bsq*bsq - u;
  
	hit  = (disc >= 0.0);

	if  (hit) { 				/* If ray hits sphere	*/
	    root  =  sqrt(disc);
	    rin  = -bsq - root;		/*    entering distance	*/
	    rout = -bsq + root;		/*    leaving distance	*/
	}
  
	return (hit);
}

bool ChQvSphereInstance::Hittest(ChRenderContext *pRC, ChHittestIterator *pIterator)
{
	GxVec3f p, vec;	// the line
	int iX, iY;
	pIterator->GetScreenPoint(iX, iY);
	m_pBounds->SetTransform(GetTransform());;	// refresh bounds
	m_pBounds->PointWindowToObject(pRC, iX, iY, p, vec);
	vec.normalize();
	GxVec3f center(0, 0, 0);	  // always centered at 0 in object space
	float rin, rout;
	int hit = intsph(p, vec, center, ((QvSphere*)GetNode())->radius.value, rin, rout);
	if(hit && (rin >= 0 || rout >= 0))
	{
		float t = (rin >= 0) ? rin : rout;
		vec *= t;
		vec += p;
		pIterator->Add(this, vec); 
	}
	return true;
}

bool ChQvSphereInstance::CollisionTest(ChRenderContext *pRC, ChCollisionIterator *pIterator)
{
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
	// using rlab transforms here - otherwise portable
	GxVec3f p0(pIterator->GetLoc()), vec(pIterator->GetDir());	// the line
	float radius = pIterator->GetRadius();
	
	GxVec3f center(0, 0, 0);	  // always centered at 0 in object space
	float r = ((QvSphere*)GetNode())->radius.value;
	// now transform camera loc and dir to object - they are in world now
	GxVec3f vecObj, p0Obj;
	vec += p0;
	vec.z() = -vec.z();
	p0.z() = -p0.z();
	ChNrFrameInverseTransform(m_frame, (ChNrVector*)&vecObj, (ChNrVector*)&vec);
	ChNrFrameInverseTransform(m_frame, (ChNrVector*)&p0Obj, (ChNrVector*)&p0);
	vecObj -= p0Obj;

	// R is a problem TODO	 !!!!!!!!!!!!

	float t;
	int hit = MovingSphereToSphere(p0Obj, vecObj, radius, center, r, t);

	if(hit && (t >= 0.0))
	{
		pIterator->Add(this, t); 
	}
#endif
	return true;
}

#if (defined(CH_USE_RLAB))
bool ChRenderContext::GetHitPoint(int iX, int iY, GxVec3f &pt)
{
	// ix and iY are in screen coords; pt is in -world- coords

	bool boolHit = false; 

	if(m_viewport)
	{
		ChNrFrame frame;

		// Lock the scene and don't be nice
		LockScene();
	
		RLVisual visual;
		const float aTinyBit = 1e-6;
		 
		if(ChNrViewportFindVisual( m_viewport, &visual, &frame, iX, iY) != RLNotFound)
		{
			// Hit -something-. How far away is it?
			GxVec3f clickPoint, framePoint;
			ChNrFaceInfo faceInfo;
			ChNrVector4d screenCoord, frameScreenCoord;

			ChNrFrameGetPosition(frame, m_sceneFrame, (ChNrVector*)&framePoint);
			ChNrViewportTransform(m_viewport, &frameScreenCoord, (ChNrVector*)&framePoint);
			float fVisualFrameZ = ((frameScreenCoord.w != 0.0) ? (frameScreenCoord.z / frameScreenCoord.w) : 0.0);
			RLError foundIt = ChNrViewportFindFace( m_viewport, &faceInfo, iX, iY);
			if( foundIt != RLNotFound )
			{
				ChNrFrameGetPosition(faceInfo.frame, m_sceneFrame, (ChNrVector*)&clickPoint);
				ChNrViewportTransform(m_viewport, &frameScreenCoord, (ChNrVector*)&clickPoint);
				float fFaceFrameZ = ((frameScreenCoord.w != 0.0) ? (frameScreenCoord.z / frameScreenCoord.w) : 0.0);
				if(faceInfo.frame == frame  || fFaceFrameZ <= fVisualFrameZ + aTinyBit )
				{
					clickPoint = *(GxVec3f*)&faceInfo.position;
					screenCoord.x = clickPoint.x();
					screenCoord.y = clickPoint.y();
					screenCoord.z = clickPoint.z();
					screenCoord.w = 1;
					ChNrViewportInverseTransform(m_viewport, (ChNrVector*)&clickPoint, &screenCoord);
				}
				else
				{
					// It's not a face visual, must be a decal
					clickPoint = framePoint;
				}
			}
			else
			{
				// It's not a face visual, must be a decal
				clickPoint = framePoint;
			}

			// Convert to world coords
			ChNrFrameInverseTransform(m_sceneFrame, (ChNrVector*)&pt, (ChNrVector*)&clickPoint);
			boolHit = true;
	

		}
		// Now see if it's in the immediate render world
		#if defined(CH_IMMED_MODE)
		{
			ChHittestIterator	iterator(this, iX, iY);
			iterator.Attach(GetRoot());
			iterator.Iterate();

			ChQvInstance *pInst;
			GxVec3f immpt;

			if(iterator.GetHit(pInst, immpt))
			{
				ChNrFrame	hitFrame = pInst->GetFrame();
				bool boolIsClosest = true;
				if(boolHit)
				{
					RLIMViewVertex ptInScreen;
		
					#if 1
					RLIMTransformVertices
				    (   GetViewport(), 
				    	m_sceneFrame,
				        (RLIMPositionVector*)&(pt),
				        &ptInScreen,
				        sizeof(RLIMPositionVector), 
				        sizeof(RLIMViewVertex),
				        1,
				        1
				    );
					#endif
					float retainedZ = ptInScreen.sz;

					RLIMTransformVertices
				    (   GetViewport(), 
				    	hitFrame,
				        (RLIMPositionVector*)&(immpt),
				        &ptInScreen,
				        sizeof(RLIMPositionVector), 
				        sizeof(RLIMViewVertex),
				        1,
				        1
				    );
					float immedZ = ptInScreen.sz;

					boolIsClosest = immedZ < retainedZ;
				}
				if(boolIsClosest)
				{
					GxVec3f tmp;
					ChNrFrameTransform(hitFrame, (ChNrVector*)&tmp, (ChNrVector*)&immpt);
					ChNrFrameInverseTransform(m_sceneFrame, (ChNrVector*)&pt, (ChNrVector*)&tmp);
					boolHit = true;
				}
			}
		}
		#endif

		UnlockScene();
	}
	
	return boolHit;

} 

//#if 0
#elif (defined(CH_USE_D3D))

bool ChRenderContext::GetHitPoint(int iX, int iY, GxVec3f &pt)
{
	// ix and iY are in screen coords; pt is in -world- coords


	bool boolHit = false; 

	if(m_viewport)
	{

		// Lock the scene and don't be nice
		LockScene();
	
		GxVec3f	retainedPoint;
	    LPDIRECT3DRMVISUAL visual;
	    LPDIRECT3DRMFRAME pickFrame;
	    LPDIRECT3DRMPICKEDARRAY picked = 0;
	    LPDIRECT3DRMFRAMEARRAY frames;
	    LPDIRECT3DRMMESHBUILDER mesh;
	    LPDIRECT3DRMTEXTURE decal;
		D3DRMPICKDESC 	pickInfo;

		HRESULT rval = m_viewport->Pick(iX, iY, &picked);
		int count = picked ? picked->GetSize() : 0;
		float z = 0;
		if(count > 0)
		{
            picked->GetPick(0, &visual, &frames, &pickInfo);
            frames->GetElement(frames->GetSize() - 1, &pickFrame);

            if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMMeshBuilder, (void **) &mesh)))
            {   
                mesh->Release();
				boolHit = true;
            }
            else if (SUCCEEDED(visual->QueryInterface(IID_IDirect3DRMTexture, (void **) &decal)))
            {   
                decal->Release();
 				boolHit = true;
           }

			pickFrame->Release();
			frames->Release();
			visual->Release();
			GxVec3f clickPoint;
			ChNrVector4d screenCoord;

			screenCoord.x = pickInfo.vPosition.x;
			screenCoord.y = pickInfo.vPosition.y;
			screenCoord.z = pickInfo.vPosition.z;
			screenCoord.w = 1;
			ChNrViewportInverseTransform(m_viewport, (ChNrVector*)&clickPoint, &screenCoord);

			ChNrFrameInverseTransform(m_sceneFrame, (ChNrVector*)&pt, (ChNrVector*)&clickPoint);

		}
		UnlockScene();
	
	}
	return boolHit;
};
#endif

//#endif
// end of file

⌨️ 快捷键说明

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