IGME_waypoint_t* ME_GetWaypointUnderCrosshair()
{
	vec3_t			mins, maxs, dir;
	float			dist, closestDist = MAX_SELECTION_DISTANCE;
	IGME_waypoint_t* selwpt = 0;
	IGME_waypoint_t* wpt = 0;
	box3_t			bbox;
	ray3_t			ray;
	int				i;
	IGME_vehicle_t* selveh = ME_GetSelectedVehicle();
	vec3_t			wmins = { -25, -25, -25 },
					wmaxs = { 25, 25, 25 };

	if( !selveh ) return 0;

	VectorCopy( cg.predictedPlayerState.origin, ray.start );
	AngleVectors( cg.predictedPlayerState.viewangles, ray.dir, 0, 0 );
	VectorScale( ray.dir, MAX_SELECTION_DISTANCE, ray.dir );

	for( i = 0; i < IGME_MAX_WAYPOINTS; ++i ) {
		wpt = &selveh->waypoints[i];
		// not active
		if( !wpt->active ) continue;
		VectorSubtract( wpt->origin, ray.start, dir );
		dist = VectorNormalize( dir );
		// too far away
		if( dist > closestDist ) continue;
		VectorAdd( wmins, wpt->origin, mins );
		VectorAdd( wmaxs, wpt->origin, maxs );
		MakeBoxFromExtents(&bbox, mins, maxs, vec3_origin);
		if( RayIntersectBox(&ray, &bbox) ) {
			closestDist = dist;
			selwpt = wpt;
		} 
	}
	return selwpt;
}
IGME_vehicle_t* ME_GetVehicleUnderCrosshair()
{
	vec3_t			mins, maxs, dir;
	float			dist, closestDist = MAX_SELECTION_DISTANCE;
	IGME_vehicle_t* selveh = 0;
	IGME_vehicle_t*	veh = 0;
	box3_t			bbox;
	ray3_t			ray;
	int				i;

	VectorCopy( cg.predictedPlayerState.origin, ray.start );
	AngleVectors( cg.predictedPlayerState.viewangles, ray.dir, 0, 0 );
	VectorScale( ray.dir, MAX_SELECTION_DISTANCE, ray.dir );

	for( i = 0; i < IGME_MAX_VEHICLES; ++i ) {
		veh = &cgs.IGME.vehicles[i];
		// not active
		if( !veh->active ) continue;
		VectorSubtract( veh->origin, ray.start, dir );
		dist = VectorNormalize( dir );
		// too far away
		if( dist > closestDist ) continue;
		if( veh->groundInstallation ) {
			VectorAdd( availableGroundInstallations[veh->vehidx].mins, veh->origin, mins );
			VectorAdd( availableGroundInstallations[veh->vehidx].maxs, veh->origin, maxs );
		} else {
			VectorAdd( availableVehicles[veh->vehidx].mins, veh->origin, mins );
			VectorAdd( availableVehicles[veh->vehidx].maxs, veh->origin, maxs );
		}
		MakeBoxFromExtents(&bbox, mins, maxs, veh->angles);
		if( RayIntersectBox(&ray, &bbox) ) {
			closestDist = dist;
			selveh = veh;
		} 
	}
	return selveh;
}
Ejemplo n.º 3
0
/*************** 进行光线跟踪 *******************/
void RayThread::traceRay(RayVector start, RayVector direction, int depth, RayColor &color, bool isInside)
{
	RayVector interPoint, refDirection, completeRefDirection, transDirection;
	RayColor localColor, refColor, completeRefColor, transColor;

	if (depth > maxDepth)				// 递归层数超过限制
	{
		color.setR(0.0);
		color.setG(0.0);
		color.setB(0.0);
	}
	else
	{
		int objIndex, faceIndex;
		int objIndex1, faceIndex1;
		double T, T1;
		bool result = false, result1 = false, isPoly = false;
		RayColor useless;
		if (!m_bUseBSP)				// 不使用BSP加速
		{
			result = findNearestPoly(start, direction, T, objIndex, faceIndex, true, isInside, useless);
			result1 = findNearestSphere(start, direction, T1, objIndex1, faceIndex1, true, isInside, useless);
			isPoly = true;
			if (result && result1)
			{
				if (T1 < T)
				{
					T = T1;
					isPoly = false;
					objIndex = objIndex1;
					faceIndex = faceIndex1;
				}
			}
			else if (!result && result1)
			{
				T = T1;
				isPoly = false;
				objIndex = objIndex1;
				faceIndex = faceIndex1;
			}
			result = result || result1;
		}
		else						// 使用BSP加速
		{
			double tMin = 0.0, tMax = 0.0;
			/* 与最大包围盒相交才需要计算其内部相交情况,否则直接断定无交点 */
			if (RayIntersectBox(start, direction, tMin, tMax))
			{
				result = findNearestPointBSP(start, direction, T, objIndex, faceIndex,
											 tMin, tMax, bspTree, isPoly, true, useless);
			}
			else
			{
				result = false;
			}
		}

		if (!result)					// 无交点
		{
			color.setR(0.0);
			color.setG(0.0);
			color.setB(0.0);
		}
		else
		{
			RayColor ks, kt, ksTrans(0.0, 0.0, 0.0),  transRefColor(0.0, 0.0, 0.0);
			RayVector N;
			bool isSpecular, isTransparent;
			interPoint = start + direction * T;
			shade(objIndex, faceIndex, interPoint, localColor, isPoly, N, ks, isSpecular, isTransparent);

			if (isSpecular)					// 交点所在的表面为镜面
			{
				direction.normalize();
				refDirection = direction - N * (direction * N) * 2.0;
				traceRay(interPoint, refDirection, depth + 1, refColor, false);
			}
			if (isTransparent)				// 交点所在表面为透明面
			{
				double eta;
				if (isPoly)
				{
					eta = objData->objectList[objIndex].faceList[faceIndex].eta();
					kt = objData->objectList[objIndex].faceList[faceIndex].kt();
				}
				else
				{
					eta = objData->objectList[objIndex].sphereList[faceIndex].eta();
					kt = objData->objectList[objIndex].sphereList[faceIndex].kt();
				}
				double cosTheta1, cosTheta2;
				RayVector L, T;
				L = -direction;
				L.normalize();
				cosTheta1 = N * L;
				if (cosTheta1 > 0.0)		// 光线从空气射向物体
				{
					cosTheta2 = sqrt(1 - (1 - cosTheta1 * cosTheta1) / (eta * eta));
					transDirection = -L / eta - N * (cosTheta2 - cosTheta1 / eta);
					traceRay(interPoint, transDirection, depth + 1, transColor, true);
				}
				else						// 光线从物体射向空气
				{
					cosTheta1 *= -1.0;
					double sinTheta1 = sqrt(1 - cosTheta1 * cosTheta1);
					double sinThetaMax = 1.0 / eta;				// 临界角,入射角大于这个角会发生全反射
					ksTrans.setR(sinTheta1 / sinThetaMax);
					ksTrans.setG(sinTheta1 / sinThetaMax);
					ksTrans.setB(sinTheta1 / sinThetaMax);
					//ksTrans = RayColor(0.5, 0.5, 0.5);
					RayVector transRefDirection = -N * (L * -N) * 2.0 - L;
					traceRay(interPoint, transRefDirection, depth + 1, transRefColor, true);
					if ((1.0 - cosTheta1 * cosTheta1) * eta * eta < 1.0)		// 不发生全反射,此时需要计算折射
					{
						cosTheta2 = sqrt(1.0 - (1.0 - cosTheta1 * cosTheta1) * eta * eta);
						transDirection = -L * eta - -N * (cosTheta2 - cosTheta1 * eta);
						traceRay(interPoint, transDirection, depth + 1, transColor, false);
					}
				}
			}
			color = localColor + ks * refColor + kt * transColor + ksTrans * transRefColor;
		}
	}
}