Esempio n. 1
0
Physics::CRay* CPhysicsServer::CreateRay(const vector3& Origin, const vector3& Dir) const
{
	CRay* R = CRay::Create();
	R->SetOrigin(Origin);
	R->SetDirection(Dir);
	return R;
}
Esempio n. 2
0
/*
	It all boils down to this.  Here is the portion of code that determines collision between
	a plane and a ray.  Lets rexamin the equations of plane and ray:
	
	Plane:
		
		p * n = -d		Where p == point on plane, n == unit normal to plane, 
						d == signed distance to plane
		
	Ray:
	
		O + tD			Where O == origin of ray, t == "time" traveled along ray, 
						D == Direction vector of the ray
						
	If we replace 'p' with the equation of ray we get:
	
		(O + tD) * n = -d
		
	And with a little algerbra for a final answer we get:
	
		t = -((n * O) + d) / (n * D)
		  
	If we treat our ray like a parametric line, we know that when 't' is between 0.0f and 1.0f, then
	there is a collision with the ray, otherwise, the ray does not collide
*/  		 
bool CPlane::intersect(const CRay &ray)
{
	// Calculate the denominator
	// **NOTE** Our ray's direction vector is always normalized, so we must
	//			multiply by the ray's length so we correctly check collision against
	//			the desired portion of the ray			
	float denominator = mNormal * ray.getDir() * ray.getLength();
	
	// If the denominator is greater than or equal to 0.0f, the ray intersects on the backside of 
	// the plane or is collinear to the plane
	// **NOTE** The "backside" of a plane is defined to be the side of the plane the 
	//			plane's normal points away from
	if(denominator >= 0.0f)
		return false; 
	
	// Calculate the numerator	
	float numerator = -((mNormal * ray.getOrigin()) + mDist);
	
	// Calculate 't'
	float t = numerator / denominator;
	
	// This return statement reads like:
	// 
	// if(t < 0.0f || t > 1.0f)
	//	return false;
	// else
	//	return true;
	//
	// We use this shorter notation because it gets rid of the if statement.  Branching
	// is usually a speed hit on x86 architecture which Windows 2000 and XP run on. 	
	return (t >= 0.0f && t <= 1.0f);
}
Esempio n. 3
0
 bool CDynamics3DEntity::CheckIntersectionWithRay(Real& f_t_on_ray,
                                                  const CRay& c_ray) const {
    /* Create an ODE ray from ARGoS ray */
    Real fRayLength = c_ray.GetLength();
    dGeomID tRay = dCreateRay(m_cEngine.GetSpaceID(), fRayLength);
    CVector3 cDirection;
    c_ray.GetDirection(cDirection);
    dGeomRaySet(tRay,
                c_ray.GetStart().GetX(),
                c_ray.GetStart().GetY(),
                c_ray.GetStart().GetZ(),
                cDirection.GetX(),
                cDirection.GetY(),
                cDirection.GetZ());
    /* Create the structure to contain info about the possible
       ray/geom intersection */
    dContactGeom tIntersection;
    /* Check for intersection between the ray and the object local space */
    if(dCollide(tRay, reinterpret_cast<dGeomID>(m_tEntitySpace), 1, &tIntersection, sizeof(dContactGeom)) > 0) {
       /* There is an intersecton */
       f_t_on_ray = tIntersection.depth / fRayLength;
       return true;
    }
    else {
       /* No intersection detected */
       return false;
    }
 }
Esempio n. 4
0
bool CheckRay(const CRay& ray, const CPlane& plane, Vector3* hitPoint)
{
    //This algorithm is based on the plane equation we saw in the CheckPlane methods
	float planeRayDirection = plane.GetNormal().Dot(ray.GetDirection());

	if (planeRayDirection == 0)
	{
		return false;
	}

    //The equation is between the plane normal and the ray origin. It is also divided by the dot product of the plane normal and ray direction
	float t = -(plane.GetNormal().Dot(ray.GetOrigin()) + plane.GetDistance()) / planeRayDirection;
	
    //If the result of the equation is negative then there is no hit
    if (t < 0)
	{
		return false;
	}
	if (hitPoint)
	{
        //Here we calculate the point where the ray hits the plane
		Vector3 pointOnPlane = (ray.GetDirection() * t) + ray.GetOrigin();
		hitPoint->x = pointOnPlane.x;
		hitPoint->y = pointOnPlane.y;
		hitPoint->z = pointOnPlane.z;
	}
	return true;
}
Esempio n. 5
0
  bool CKinematics2DCollisionCircle::CheckIntersectionWithRay(Real& f_distance, const CRay& c_ray) const {
    CSegment c_segment = c_ray.ProjectOntoXY();
    CVector2 c_closest_point, c_closest_segment_point;
    c_segment.GetMinimumDistancePoints( m_cPosition, c_closest_point, c_closest_segment_point );
    
    Real f_min_segment_distance = Distance(m_cPosition,c_closest_segment_point);
    if( f_min_segment_distance > m_fRadius ) {
      return false;
    }

    // see http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/
    CVector2 dp = c_segment.GetEnd() - c_segment.GetStart();
    Real     a  = dp.SquareLength();
    Real     b  = 2 * dp.DotProduct(c_segment.GetStart() - m_cPosition);
    Real     c  = (m_cPosition.SquareLength() +
		   c_segment.GetStart().SquareLength() -
		   2 * m_cPosition.DotProduct(c_segment.GetStart()) -
		   m_fRadius*m_fRadius);
    Real bb4ac  = b*b - 4*a*c;
    Real mu1    = (-b + sqrt(bb4ac)) / (2 * a);
    Real mu2    = (-b - sqrt(bb4ac)) / (2 * a);
    
    Real mu = Min(mu1,mu2);
    if( mu < 0 || mu > 1 ) mu = Max(mu1,mu2);

    f_distance = mu * c_ray.GetLength();    
    return true;
  }
Esempio n. 6
0
// Do a ray check starting from position `pos' along direction `dir'.
// Make resulting intersection points available in `GetIntersectionPoints()'.
bool CPhysicsServer::RayCheck(const vector3& Pos, const vector3& Dir, const CFilterSet* ExcludeSet)
{
	Contacts.Clear();
	CRay R;
	R.SetOrigin(Pos);
	R.SetDirection(Dir);
	if (ExcludeSet) R.SetExcludeFilterSet(*ExcludeSet);
	R.DoRayCheckAllContacts(matrix44::identity, Contacts);
	return Contacts.Size() > 0;
}
Esempio n. 7
0
axelynx::RaySystem::Ray* CRaySystem::AddInstance()
{
	CRay *piv = new CRay;
	piv->SetColor(1.0f,1.0f,1.0f,1.0f);
	piv->SetWidth(1.0f);
	piv->SetLenght(128.0f);

	instances_.push_back(piv);
	
	return piv;
}
Esempio n. 8
0
bool CPolygon::Intersect(CRay &ray, bool cull, float *dist)
{
   if(!ray.Intersect(m_vertexList[0], m_vertexList[1],
      m_vertexList[2], false, dist)) return false;
   
   if(!cull)
      {
         if(!ray.Intersect(m_vertexList[2], m_vertexList[1],
            m_vertexList[0], false, dist)) return false;
      }
   
   return true;
}
Esempio n. 9
0
bool
CSphere::Intersect(const CRay& clRay, RealType t0, RealType t1, TTracingContext& tContext ) const
{
	/*
		Implement ray-sphere intersection.
		You must set the following member of the TTracingContext struct:
		t          - ray parameter of intersection point
		v3Normal   - Normal of surface at intersection point
		v3HitPoint - Coordinate of intersection point
		v2TexCoord - 2D-Texture coordinate of intersection point (use polar coordinates (method Cartesian2Polar), not needed currently)
		pclShader  - Material of sphere
	*/

    VectorType3 vecDiff(m_v3Center - clRay.GetOrigin());


    RealType t_ca = vecDiff | clRay.GetDir();

    if (t_ca < 0)
        return false;

    RealType d2 = (vecDiff | vecDiff) - t_ca * t_ca;
    RealType r2 = m_rRadius * m_rRadius ;

    if (d2 > r2) {
        return false;
    }

    RealType desc = sqrt(r2 - d2);

    RealType t = (t_ca - desc) ;

    if (t < 0.0) {
        t = (t_ca + desc);
    }

    if (t > tContext.t) {
        return false;
    }
    tContext.t = t;

    tContext.v3HitPoint = clRay.Evaluate(tContext.t);
    tContext.v3Normal = (tContext.v3HitPoint - m_v3Center).normalize();

    tContext.pclShader = GetShader();

    return true;

}
Esempio n. 10
0
	bool intersect(CRay& _ray, float* _thit, CLocalGeo* _local, int& _id)  {
		if (_ray.m_id == m_id)
			return false; 
		V3f E1 = m_V0 - m_V1; 
		V3f E2 = m_V0 - m_V2; 
		V3f S = m_V0 - _ray.m_pos;
		float d = det(_ray.m_dir, E1, E2);
		if (d < EPS && d > -EPS)
		 	return false; 
		float d1 = det(S, E1, E2);
		float t = d1 / d; 
		if (t < _ray.m_t_min || t > _ray.m_t_max)
		 	return false; 
		float d2 = det(_ray.m_dir, S, E2);
		float beta = d2 / d; 
		if (beta < -EPS || beta  - 1 > EPS)
		 	return false; 
		float d3 = det(_ray.m_dir, E1, S);
		float gamma = d3 / d; 
		if (gamma < -EPS || gamma - 1 > EPS || beta + gamma - 1 > EPS)
		 	return false; 
		*_thit = t;
		_id = m_id; 
		_local->m_pos = _ray.Ray_t(t);
		_local->m_n = (m_V0-m_V1).cross(m_V0-m_V2);
		_local->m_n = _local->m_n / _local->m_n.norm();
		return true; 
	}
Esempio n. 11
0
// --[ Method ]---------------------------------------------------------------
//
//  - Class     : CVector3
//  - Prototype : float Angle(const CRay& ray)
//
//  - Purpose   : Returns the angle between the vector and a ray.
//
// ---------------------------------------------------------------------------
float CVector3::Angle(const CRay& ray) const
{
	float fAngle = Angle(ray.Direction());

	if(fAngle > 90.0f) fAngle = 180.0f - fAngle;

	return fAngle;
}
Esempio n. 12
0
// WinProc
LRESULT CALLBACK WinProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	// Constant amounts to move the origin of the ray by
	const CVector kXAxisMoveAmt(0.05f, 0.0f, 0.0f);
	const CVector kYAxisMoveAmt(0.0f, 0.05f, 0.0f);
	
	switch(message)
    {
		case WM_SYSKEYDOWN:

			// Toggle on ALT + ENTER				
			if(wparam == VK_RETURN && (lparam & (1 << 29)))
			{
				g3D->toggleFullScreen();
				g3D->setViewMatrix(CPos(0,1,-3.0f), CPos(0,0,0)); // Reset the view of our scene
					return 0;
			}

			break; // Allow other system keys to be handled by DefWindowProc()
			
		case WM_KEYDOWN: // If we get a key down message, do stuff

			switch(wparam)
			{
				case VK_ESCAPE: // If they push ESC, close the app
					SendMessage(hwnd, WM_CLOSE, 0, 0);
						break;
						
				case VK_LEFT: // Move the origin of the ray to the left (-X axis)
					gRay.setOrigin(gRay.getOrigin() - kXAxisMoveAmt);
						break;
						
				case VK_RIGHT: // Move the origin of the ray to the right (+X axis)
					gRay.setOrigin(gRay.getOrigin() + kXAxisMoveAmt);
						break;
						
				case VK_DOWN: // Move the origin of the ray down (-Y axis)
					gRay.setOrigin(gRay.getOrigin() - kYAxisMoveAmt);
					break;

				case VK_UP: // Move the origin of the ray up (+Y axis)
					gRay.setOrigin(gRay.getOrigin() + kYAxisMoveAmt);
					break;
			}
			
			return 0;
		
		case WM_DESTROY:
			PostQuitMessage(0);
				return 0;
    }

    return DefWindowProc(hwnd, message, wparam, lparam);
}
Esempio n. 13
0
bool CheckRay(const CRay& ray, const CBoundingSphere& sphere, Vector3* hitPoint)
{
    //This algorithm is adatped from: http://www.cosinekitty.com/raytrace/chapter06_sphere.html
    //It breaks the problem down into the plane equations needed to find the hit points between the ray and sphere
    //To solve this correctly it makes use of a quadratic equation.
	Vector3 displacement = ray.GetOrigin() - sphere.GetCenter();
	float a = ray.GetDirection().LengthSquared();
	float b = 2.0f * displacement.Dot(ray.GetDirection());
	float c = displacement.LengthSquared() - sphere.GetRadius() * sphere.GetRadius();

	float randicand = b*b - 4.0f * a * c;
	//If the quadratic equation comes back as a negitive then there is no hit.
    if (randicand < 0.0f)
	{
		return false;
	}
	

	float root = sqrt(randicand);
	float denom = 2.0 * a;

    //Here we calculate the distance between ray origin and the two hit points (where the ray enters the sphere and where it exits)
	float hit1 = (-b + root) / denom;
	float hit2 = (-b - root) / denom;

    //If both of the hits are negitive then it means that the sphere is behind the origin of the ray so there is no hit
	if (hit1 < 0 && hit2 < 0)
	{
		return false;
	}

	
	if (hitPoint)
	{
        //If we need to know the first hit point on the sphere then we should use hit1, unless it's negative then we use hit2.
        //This would come up in situations where the origin of the ray is within the sphere.
        float firstHitDistance = hit1 < 0 ? hit2 : hit1;
		Vector3 pointOnSphere = (ray.GetDirection() * firstHitDistance) + ray.GetOrigin();
		hitPoint->x = pointOnSphere.x;
		hitPoint->y = pointOnSphere.y;
		hitPoint->z = pointOnSphere.z;
	}
	return true;
}
Esempio n. 14
0
static void RepWireBondRender(RepWireBond * I, RenderInfo * info)
{
  PyMOLGlobals *G = I->R.G;
  CRay *ray = info->ray;
  auto pick = info->pick;
  int ok = true;

  if(ray) {
#ifndef _PYMOL_NO_RAY
    CGORenderRay(I->primitiveCGO, ray, info, NULL, NULL, I->R.cs->Setting, I->R.cs->Obj->Obj.Setting);
    ray->transparentf(0.0);
#endif
  } else if(G->HaveGUI && G->ValidContext) {
    bool use_shader = SettingGetGlobal_b(G, cSetting_line_use_shader) &&
                      SettingGetGlobal_b(G, cSetting_use_shaders);
    if(pick) {
      CGORenderGLPicking(use_shader ? I->shaderCGO : I->primitiveCGO, info, &I->R.context, NULL, NULL, &I->R);
    } else { /* else not pick i.e., when rendering */
      short line_as_cylinders ;
      line_as_cylinders = SettingGetGlobal_b(G, cSetting_render_as_cylinders) && SettingGetGlobal_b(G, cSetting_line_as_cylinders);
      if (I->shaderCGO && (!use_shader || (line_as_cylinders ^ I->shaderCGO_has_cylinders))){
      CGOFree(I->shaderCGO);
        I->shaderCGO_has_cylinders = 0;
	}
	if (ok){
        if (use_shader) {
          if (!I->shaderCGO)
            ok &= RepWireBondCGOGenerate(I, info);
          CGORenderGL(I->shaderCGO, NULL, NULL, NULL, info, &I->R);
	    } else {
          CGORenderGL(I->primitiveCGO, NULL, NULL, NULL, info, &I->R);
	}
      }
    }
  }
  if (!ok){
    CGOFree(I->shaderCGO);
    I->R.fInvalidate(&I->R, I->R.cs, cRepInvPurge);
    I->R.cs->Active[cRepLine] = false;
  }
}
Esempio n. 15
0
File: Ray.cpp Progetto: 7kia/CG
bool CPlane::Hit(const CRay &ray, SRayIntersection &intersection) const
{
    // Величина, меньше которой модуль скалярного произведения вектора направления луча и
    // нормали плоскости означает параллельность луча и плоскости
    const float EPSILON = std::numeric_limits<float>::epsilon();

    // Нормаль к плоскости в системе координат объекта
    const glm::vec3 normalInObjectSpace(m_planeEquation);

    // Скалярное произведение направления луча и нормали к плоскости
    const float normalDotDirection = glm::dot(ray.GetDirection(), normalInObjectSpace);

    // Если скалярное произведение близко к нулю, луч параллелен плоскости
    if (fabs(normalDotDirection) < EPSILON)
    {
        return false;
    }

    /*
    Находим время пересечения луча с плоскостью, подставляя в уравнение плоскости точку испускания луча
    и деление результата на ранее вычисленное сканярное произведение направления луча и нормали к плоскости
    */
    const float hitTime = -glm::dot(glm::vec4(ray.GetStart(), 1), m_planeEquation) / normalDotDirection;

    // Нас интересует только пересечение луча с плоскостью в положительный момент времени,
    // поэтому находящуюся "позади" точки испускания луча точку пересечения мы за точку пересечения не считаем
    // Сравнение с величиной EPSILON, а не с 0 нужно для того, чтобы позволить
    // лучам, испущенным с плоскости, оторваться от нее.
    // Это необходимо при обработке вторичных лучей для построения теней и отражений и преломлений
    if (hitTime <= EPSILON)
    {
        return false;
    }

    // Вычисляем точку столкновения с лучом в системе координат сцены в момент столкновения
    const glm::vec3 hitPoint = ray.GetPointAtTime(hitTime);
    intersection.m_time = hitTime;
    intersection.m_point = hitPoint;

    return true;
}
Esempio n. 16
0
bool CDynamics2DCylinderEntity::CheckIntersectionWithRay(Real& f_t_on_ray,
        const CRay& c_ray) const {
    cpSegmentQueryInfo tInfo;
    if(cpShapeSegmentQuery(m_ptShape,
                           cpv(c_ray.GetStart().GetX(), c_ray.GetStart().GetY()),
                           cpv(c_ray.GetEnd().GetX()  , c_ray.GetEnd().GetY()  ),
                           &tInfo)) {
        CVector3 cIntersectionPoint;
        c_ray.GetPoint(cIntersectionPoint, tInfo.t);
        if((cIntersectionPoint.GetZ() >= GetEmbodiedEntity().GetPosition().GetZ() - m_fHalfHeight) &&
                (cIntersectionPoint.GetZ() <= GetEmbodiedEntity().GetPosition().GetZ() + m_fHalfHeight) ) {
            f_t_on_ray = tInfo.t;
            return true;
        }
        else {
            return false;
        }
    }
    else {
        return false;
    }
}
Esempio n. 17
0
bool CheckRay(const CRay& ray, const CBoundingBox& bb, Vector3* hitPoint)
{
    //This algorithm is adapted from: http://tavianator.com/fast-branchless-raybounding-box-intersections/
    //Its based on the "Slab Technique" which treats a bounding box as a series of 2 planes in each axis.
    //It finds where the ray lies on each of these planes and compares those values across each axis.
	float tmin = -INFINITY;
	float tmax = INFINITY;

	float tx1 = (bb.GetMin().x - ray.GetOrigin().x) / ray.GetDirection().x;
	float tx2 = (bb.GetMax().x - ray.GetOrigin().x) / ray.GetDirection().x;

	tmin = max(tmin, min(tx1, tx2));
	tmax = min(tmax, max(tx1, tx2));
	
	float ty1 = (bb.GetMin().y - ray.GetOrigin().y) / ray.GetDirection().y;
	float ty2 = (bb.GetMax().y - ray.GetOrigin().y) / ray.GetDirection().y;

	tmin = max(tmin, min(ty1, ty2));
	tmax = min(tmax, max(ty1, ty2));
	
	float tz1 = (bb.GetMin().z - ray.GetOrigin().z) / ray.GetDirection().z;
	float tz2 = (bb.GetMax().z - ray.GetOrigin().z) / ray.GetDirection().z;

	tmin = max(tmin, min(tz1, tz2));
	tmax = min(tmax, max(tz1, tz2));
	
    //We end up with two hit values just like the sphere, if the max hit is less than 0 then it all happened behind the ray origin
	if (tmax < 0)
		return false;

    //If the max hit value is greater than the min hit (as it should be) then we have a hit!
	if (tmax >= tmin)
	{
		if (hitPoint)
		{
            //If we need to know the first hit point on the box then we should use tmin, unless it's negative then we use tmax.
            //This would come up in situations where the origin of the ray is within the box.
			float firstHitDistance = tmin < 0 ? tmax : tmin;
			Vector3 pointOnBox = (ray.GetDirection() * firstHitDistance) + ray.GetOrigin();
		
			hitPoint->x = pointOnBox.x;
			hitPoint->y = pointOnBox.y;
			hitPoint->z = pointOnBox.z;
		}
		return true;
	}
	return false;
}
Esempio n. 18
0
	bool intersect(CRay& _ray, float* _thit, CLocalGeo* _local, int& _id)  {
		if (_ray.m_id == m_id)
			return false; 
		float t; 
		V3f oc = _ray.m_pos - m_c; 
		float a = _ray.m_dir.dot(_ray.m_dir); // dir should be unit
		float b = _ray.m_dir.dot(oc);
		float c = oc.dot(oc) - m_r2; 
		float delta = b * b  - a * c; 
		if (delta < 0)   // no solution 
			return false; 
		else if (delta > -EPS && delta < EPS) {  // one solution
			t = - b / a;
			if (t > _ray.m_t_max || t < _ray.m_t_min)  // out of range
				return false; 
		} else {   // two solutions 
			float deltasqrt = sqrt(delta);
			float t1 = (- b - deltasqrt) / a;
			float t2 = (- b + deltasqrt) / a;
			bool flag = false; 
			t = _ray.m_t_max; 
			if (t1 <= _ray.m_t_max && t1 >= _ray.m_t_min) {
				flag = true; 
				t = min(t, t1);
			}

			if (t2 <= _ray.m_t_max && t2 >= _ray.m_t_min) {
				flag = true; 
				t = min(t, t2);
			}
			if (!flag)   // both out of range
				return false; 
		}

		// pass t, compute CLocalGeo
		*_thit = t; 
		_id = m_id; 
		_local->m_pos = _ray.Ray_t(t);
		_local->m_n = _local->m_pos - m_c; 
		_local->m_n = _local->m_n / _local->m_n.norm(); 
		return true; 
	} 
Esempio n. 19
0
void CGuardRobot::process()
{
	switch(state)
	{
	case LOOK:
		// animation
		if (animtimer > LOOK_ANIM_TIME)
		{
			frame ^= 1;
			animtimer = 0;
		}
		else
			animtimer++;

		sprite = LOOK_FRAME + frame;

		// when time is up go back to moving
		if (timer > LOOK_TOTALTIME)
		{
			timetillcanfire = (rnd()%(MAX_TIME_TILL_CAN_FIRE-MIN_TIME_TILL_CAN_FIRE))+MIN_TIME_TILL_CAN_FIRE;
			timetillcanfirecauseonsamelevel = TIME_BEFORE_FIRE_WHEN_SEE;
			firetimes = 0;
			state = WALK;
			frame = 0;
			animtimer = 0;
			timer = 0;
			dist_to_travel = TRAVELDIST;
		}
		else
			timer++;

		break;

	case WALK:
		// hover animation
		if (animtimer > WALK_ANIM_TIME)
		{
			if (frame>=3) frame=0;
			else frame++;
			animtimer = 0;
		} else animtimer++;

		if (movedir==LEFT)
			sprite = WALK_LEFT_FRAME + frame;
		else
			sprite = WALK_RIGHT_FRAME + frame;

		// if we're about to, or just did, fire a volley, don't move
		if (!hardmode)
		{
			if (pausetime)
			{
				pausetime--;
				return;
			}
		}
		else
			pausetime = 0;

		// are we firing a volley?
		if (firetimes)
		{
			// is it time to fire the next shot in the volley?
			if (!timetillnextshot)
			{
				CRay *newobject;
				if (onscreen)
					playSound(SOUND_TANK_FIRE);
				if (movedir==RIGHT)
					newobject = new CRay(mp_Map,getXRightPos()+(8<<STC), getYUpPos()+(5<<STC), RIGHT);
				else
					newobject = new CRay(mp_Map,getXPosition(), getYUpPos()+(5<<STC), LEFT);
				newobject->setOwner(OBJ_GUARDROBOT, m_index);
				newobject->sprite = ENEMYRAYEP2;

				m_ObjectVect.push_back(newobject);

				timetillnextshot = TIME_BETWEEN_SHOTS;
				if (!--firetimes)
				{
					pausetime = FIRE_PAUSE_TIME;
				}
			}
			else
			{
				timetillnextshot--;
			}

			// don't move when firing except on hard mode
			if (hardmode)
				return;

		}
		else
		{  // not firing a volley
			if (!timetillcanfire)
			{
				guard_fire();
			}
			else
			{
				timetillcanfire--;
			}

		}

		turnaroundtimer = 0;

		if (movedir==LEFT)
		{  // move left
			if (!blockedl)
			{
				xinertia = -WALK_SPEED;
				dist_to_travel--;
			}
			else
			{
				frame = 0;
				timer = 0;
				animtimer = 0;
				state = LOOK;
				movedir = RIGHT;
			}
		}
		else
		{  // move right
			sprite = WALK_RIGHT_FRAME + frame;
			if (!blockedr)
			{
				xinertia = WALK_SPEED;
				dist_to_travel--;
			}
			else
			{
				frame = 0;
				timer = 0;
				animtimer = 0;
				state = LOOK;
				movedir = LEFT;
			}
		}
		break;
	default : break;
	}
}
Esempio n. 20
0
void CTank::process()
{
	switch(state)
	{
	case TANK_WALK: // Walk in a direction
	{
		// is keen on same level?
		if (movedir==LEFT)
		{  // move left
			sprite = TANK_WALK_LEFT_FRAME + frame;
			xinertia = -TANK_WALK_SPEED;
			if( blockedl )
			{
				movedir = RIGHT;
				frame = 0;
				timer = 0;
				animtimer = 0;
				state = TANK_TURN;
			}

			dist_to_travel--;
		}
		else
		{  // move right
			sprite = TANK_WALK_RIGHT_FRAME + frame;
			xinertia = TANK_WALK_SPEED;
			if ( blockedr )
			{
				movedir = LEFT;
				frame = 0;
				timer = 0;
				animtimer = 0;
				state = TANK_TURN;
			}

			dist_to_travel--;
		}

		// walk animation
		if (animtimer > TANK_WALK_ANIM_TIME)
		{
			if (frame>=3) frame=0;
			else frame++;
			animtimer = 0;
		} else animtimer++;

		if(dist_to_travel==0)
		{
			frame = 0;
			timer = 0;
			animtimer = 0;
			state = TANK_WAIT;
		}
	default: break;
	}
	break;

	case TANK_WAIT:
		if ( (timer > TANK_PREPAREFIRE_TIME) ||
				(timer > TANK_PREPAREFIRE_TIME_FAST && hardmode) )
		{
			timer = 0;
			state = TANK_FIRE;
		}
		else
			timer++;

		break;

	case TANK_TURN:
		// If it gets stuck somewhere turn around
		sprite = TANK_LOOK_FRAME + frame;
		// animation
		if (animtimer > TANK_LOOK_ANIM_TIME)
		{
			frame ^= 1;
			animtimer = 0;
		} else animtimer++;

		// when time is up go back to moving
		if (timer > TANK_LOOK_TOTALTIME)
		{
			// decide what direction to go
			state = TANK_WALK;
			animtimer = 0;
			timer = 0;
		} else timer++;
		break;
	case TANK_FIRE:
	{
		int height_top = g_pBehaviorEngine->getPhysicsSettings().tankbot.shot_height_from_top<<STC;
		if(height_top!=0)
		{
			CRay *newobject;
			if (onscreen)
				playSound(SOUND_TANK_FIRE);
			if (movedir==RIGHT)
				newobject = new CRay(mp_Map, getXMidPos(), getYUpPos()+height_top, RIGHT);
			else
				newobject = new CRay(mp_Map, getXMidPos(), getYUpPos()+height_top, LEFT);
			newobject->setOwner(OBJ_TANK, m_index);
			newobject->setSpeed(108);
			newobject->sprite = ENEMYRAY;
			newobject->canbezapped = true;
			m_Object.push_back(newobject);
		}

		state = TANK_WAIT_LOOK;
		frame = 0;
		timer = 0;
		animtimer = 0;
		dist_to_travel = TANK_MINTRAVELDIST + (rnd()%10)*(TANK_MAXTRAVELDIST-TANK_MINTRAVELDIST)/10;
	}
	break;

	case TANK_WAIT_LOOK:
		// Happens after Robot has fired
		if ( timer > TANK_WAITAFTER_FIRE )
		{
			timer = 0;
			state = TANK_LOOK;
		}
		else
			timer++;

		break;

	case TANK_LOOK:
		sprite = TANK_LOOK_FRAME + frame;
		// animation
		if (animtimer > TANK_LOOK_ANIM_TIME)
		{
			frame ^= 1;
			animtimer = 0;
		} else animtimer++;

		// when time is up go back to moving
		if (timer > TANK_LOOK_TOTALTIME)
		{
			// decide what direction to go

			if(m_Player[0].getXMidPos() < getXMidPos())
			{
				movedir = LEFT;
				sprite = TANK_WALK_LEFT_FRAME;
			}
			else if(m_Player[0].getXMidPos() > getXMidPos())
			{
				movedir = RIGHT;
				sprite = TANK_WALK_RIGHT_FRAME;
			}
			state = TANK_WALK;
			animtimer = 0;
			timer = 0;
		} else timer++;
		break;
	}
}
void CVorticonElite::process()
{
	if (mHealthPoints <= 0 && state != VORTELITE_DYING)
	{
		animtimer = 0;
		frame = 0;
		state = VORTELITE_DYING;
		dying = true;

		if (onscreen)
			playSound(SOUND_VORT_DIE);
	}

	if(state == VORTELITE_CHARGE)
	{
		m_speed = CHARGE_SPEED;
	}
	else if(state == VORTELITE_WALK)
	{
		m_speed = WALK_SPEED;
	}

	reprocess: ;
	switch(state)
	{
	case VORTELITE_CHARGE:
	case VORTELITE_WALK:

		if (movedir==LEFT)
		{  // move left
			sprite = VORTELITE_WALK_LEFT_FRAME + frame;
			if (!blockedl)
			{
				xinertia = -m_speed;
			}
			else
			{
				movedir = RIGHT;

				// if we only traveled a tiny amount before hitting a wall, we've
				// probably fallen into a small narrow area, and we need to try
				// to jump out of it
				if (dist_traveled < VORTELITE_TRAPPED_DIST && !mp_Map->m_Dark && blockedd)
				{
					initiatejump();
					goto reprocess;
				}
                else if(mp_Map->m_Dark)
                {
                    dist_traveled = 0;
                }
			}
		}
		else
		{  // move right
			sprite = VORTELITE_WALK_RIGHT_FRAME + frame;
			if (!blockedr)
			{
				xinertia = m_speed;
			}
			else
			{
				movedir = LEFT;

				// if we only traveled a tiny amount before hitting a wall, we've
				// probably fallen into a small narrow area, and we need to try
				// to jump out of it
				if (dist_traveled < VORTELITE_TRAPPED_DIST && !mp_Map->m_Dark && blockedd)
				{
					initiatejump();
					goto reprocess;
				}
                else if(mp_Map->m_Dark)
                {
                    dist_traveled = 0;
                }
            }
		}

		// walk animation
		if (animtimer > VORTELITE_WALK_ANIM_TIME)
		{
			if (frame>=3) frame=0;
			else frame++;
			animtimer = 0;
		} else animtimer++;
		break;

	case VORTELITE_JUMP:
		if (movedir == RIGHT)
		{ if (!blockedr) moveRight(m_speed); }
		else
		{ if (!blockedl) moveLeft(m_speed); }

		if (blockedd && yinertia >= 0)
		{  // The Vorticon Has landed after the jump!
			state = VORTELITE_WALK;
			goto reprocess;
		}

		break;
	case VORTELITE_ABOUTTOFIRE:
		if (movedir==RIGHT)
		{ sprite = VORTELITE_FIRE_RIGHT_FRAME; }
		else
		{ sprite = VORTELITE_FIRE_LEFT_FRAME; }
		if (timer > VORTELITE_HOLD_GUN_OUT_TIME)
		{
			timer = 0;
			state = VORTELITE_FIRED;

			CRay *newobject;
			if (movedir==RIGHT)
                newobject = new CRay(mp_Map, getXRightPos()+1, getYPosition()+(9<<STC), RIGHT, CENTER, getSpriteVariantId());
			else
                newobject = new CRay(mp_Map, getXLeftPos()-1, getYPosition()+(9<<STC), LEFT, CENTER, getSpriteVariantId());
			newobject->setOwner( m_type, m_index);
			newobject->sprite = ENEMYRAYEP2;
			// don't shoot other vorticon elite
			spawnObj(newobject);

			if (onscreen)
				playSound(SOUND_KEEN_FIRE);
		}
		else timer++;
		break;
	case VORTELITE_FIRED:
		if (movedir==RIGHT)
		{ sprite = VORTELITE_FIRE_RIGHT_FRAME; }
		else
		{ sprite = VORTELITE_FIRE_LEFT_FRAME; }

		if (timer > VORTELITE_HOLD_GUN_AFTER_FIRE_TIME)
		{
			timer = 0;
			frame = 0;
			timesincefire = 0;
			state = VORTELITE_WALK;
		}
		else timer++;
		break;
	case VORTELITE_DYING:
		sprite = VORTELITE_DYING_FRAME;
		if (animtimer > VORTELITE_DIE_ANIM_TIME)
		{
			sprite = VORTELITE_DEAD_FRAME;
			dead = true;
		}
		else
		{
			animtimer++;
		}
		break;
	default: break;
	}
}
Esempio n. 22
0
 void CEPuckRangeAndBearingSensor::Update() {
    /* Clear the previous received packets */
    ClearRABReceivedPackets();
    /* Get robot position */
    const CVector3& cRobotPosition = m_pcEmbodiedEntity->GetPosition();
    /* Get robot orientation */
    CRadians cTmp1, cTmp2, cOrientationZ;
    m_pcEmbodiedEntity->GetOrientation().ToEulerAngles(cOrientationZ, cTmp1, cTmp2);
    /* Buffer for calculating the message--robot distance */
    CVector3 cVectorToMessage;
    CVector3 cVectorRobotToMessage;
    Real fMessageDistance;
    /* Buffer for the received packet */
    TEPuckRangeAndBearingReceivedPacket tPacket;
    /* Initialize the occlusion check ray start to the position of the robot */
    CRay cOcclusionCheckRay;
    cOcclusionCheckRay.SetStart(cRobotPosition);
    /* Buffer to store the intersection data */
    CSpace::SEntityIntersectionItem<CEmbodiedEntity> sIntersectionData;
    /* Ignore the sensing robot when checking for occlusions */
    TEmbodiedEntitySet tIgnoreEntities;
    tIgnoreEntities.insert(m_pcEmbodiedEntity);
    /*
     * 1. Go through all the CRABEquippedEntities<2> (those compatible with this sensor)
     * 2. For each of them
     *    a) Check that the receiver is not out of range
     *    b) Check if there is an occlusion
     *    c) If there isn't, get the info and set reading for that robot
     */
    CSpace::TAnyEntityMap& tEntityMap = m_cSpace.GetEntitiesByType("rab_equipped_entity<2>");
    for(CSpace::TAnyEntityMap::iterator it = tEntityMap.begin();
        it != tEntityMap.end();
        ++it) {
       CRABEquippedEntity<2>& cRABEntity = *(any_cast<CRABEquippedEntity<2>*>(it->second));
          
       /* Check the RAB equipped entity is not this robot (avoid self-messaging) */
       if(&cRABEntity != m_pcRABEquippedEntity) {
          /* Get the position of the RAB equipped entity */
          cVectorToMessage = cRABEntity.GetPosition();
          cVectorRobotToMessage = (cVectorToMessage - cRobotPosition) * 100; // in cms
          /* Check that the distance is lower than the range */
          fMessageDistance = cVectorRobotToMessage.Length();
          if(fMessageDistance < cRABEntity.GetRange()) {
             /* Set the ray end */
             cOcclusionCheckRay.SetEnd(cVectorToMessage);
             /* Check occlusion between robot and message location */
             if(!m_bCheckOcclusions ||
            		(! m_cSpace.GetClosestEmbodiedEntityIntersectedByRay(sIntersectionData, cOcclusionCheckRay, tIgnoreEntities)) ||
                sIntersectionData.IntersectedEntity->GetId() == cRABEntity.GetId()) {            
               /* The message is not occluded */
                if(m_bShowRays) m_pcControllableEntity->AddCheckedRay(false, cOcclusionCheckRay);
                /* Set the reading */
                tPacket.Id = m_unLatestPacketId++;
                CRadians cVertical = CRadians::ZERO;
                cVectorRobotToMessage.ToSphericalCoordsHorizontal(tPacket.Range,
                                                                  cVertical,
                                                                  tPacket.BearingHorizontal);
                tPacket.BearingHorizontal -= cOrientationZ;
                tPacket.BearingHorizontal.SignedNormalize();
                cRABEntity.GetData(tPacket.Data);
                m_tLastReceivedPackets.push_back(tPacket);
             }
             else {
                /* The message is occluded */
                if(m_bShowRays) {
                   m_pcControllableEntity->AddCheckedRay(true, cOcclusionCheckRay);
                   m_pcControllableEntity->AddIntersectionPoint(cOcclusionCheckRay, sIntersectionData.TOnRay);
                }
             }
          }
       }
    }
 }
Esempio n. 23
0
void CVorticonElite::process()
{
	if (HealthPoints <= 0 && state != VORTELITE_DYING)
	{
		animtimer = 0;
		frame = 0;
		state = VORTELITE_DYING;
		dying = true;

		if (onscreen)
			playSound(SOUND_VORT_DIE);
	}

	if(state == VORTELITE_CHARGE)
	{
		m_speed = CHARGE_SPEED;
	}
	else if(state == VORTELITE_WALK)
	{
		m_speed = WALK_SPEED;
	}

	reprocess: ;
	switch(state)
	{
	case VORTELITE_CHARGE:
	case VORTELITE_WALK:
		dist_traveled++;

		state = VORTELITE_WALK;

		// If Player is nearby, make vorticon go faster
		if(getYDownPos() > m_Player[0].getYDownPos()-(1<<CSF) and
		   getYDownPos() < m_Player[0].getYDownPos()+(1<<CSF) )
		{
			int dist;
			if(getXMidPos() > m_Player[0].getXMidPos())
				dist = getXMidPos()-m_Player[0].getXMidPos();
			else
				dist = m_Player[0].getXMidPos()-getXMidPos();

			if(dist < PLAYER_DISTANCE)
				state = VORTELITE_CHARGE;
		}


		if (getProbability(VORTELITE_JUMP_PROB) && !mp_Map->m_Dark && !blockedu)
		{  // let's jump.
			initiatejump();
			goto reprocess;
		}
		else
		{
			if (timesincefire > VORTELITE_MIN_TIME_BETWEEN_FIRE)
			{
				if (getProbability(VORTELITE_FIRE_PROB))
				{  	// let's fire
					// usually shoot toward keen
					if (rand()%5 != 0)
					{
						if (getXPosition() < m_Player[0].getXPosition())
						{
							movedir = RIGHT;
						}
						else
						{
							movedir = LEFT;
						}
					}
					timer = 0;
					state = VORTELITE_ABOUTTOFIRE;
				}
			}
			else timesincefire++;
		}

		if (movedir==LEFT)
		{  // move left
			sprite = VORTELITE_WALK_LEFT_FRAME + frame;
			if (!blockedl)
			{
				xinertia = -m_speed;
			}
			else
			{
				movedir = RIGHT;

				// if we only traveled a tiny amount before hitting a wall, we've
				// probably fallen into a small narrow area, and we need to try
				// to jump out of it
				if (dist_traveled < VORTELITE_TRAPPED_DIST && !mp_Map->m_Dark && blockedd)
				{
					initiatejump();
					goto reprocess;
				}
				else dist_traveled = 0;
			}
		}
		else
		{  // move right
			sprite = VORTELITE_WALK_RIGHT_FRAME + frame;
			if (!blockedr)
			{
				xinertia = m_speed;
			}
			else
			{
				movedir = LEFT;

				// if we only traveled a tiny amount before hitting a wall, we've
				// probably fallen into a small narrow area, and we need to try
				// to jump out of it
				if (dist_traveled < VORTELITE_TRAPPED_DIST && !mp_Map->m_Dark && blockedd)
				{
					initiatejump();
					goto reprocess;
				}
				else dist_traveled = 0;
			}
		}

		// walk animation
		if (animtimer > VORTELITE_WALK_ANIM_TIME)
		{
			if (frame>=3) frame=0;
			else frame++;
			animtimer = 0;
		} else animtimer++;
		break;

	case VORTELITE_JUMP:
		if (movedir == RIGHT)
		{ if (!blockedr) moveRight(m_speed); }
		else
		{ if (!blockedl) moveLeft(m_speed); }

		if (blockedd && yinertia >= 0)
		{  // The Vorticon Has landed after the jump!
			state = VORTELITE_WALK;
			goto reprocess;
		}

		break;
	case VORTELITE_ABOUTTOFIRE:
		if (movedir==RIGHT)
		{ sprite = VORTELITE_FIRE_RIGHT_FRAME; }
		else
		{ sprite = VORTELITE_FIRE_LEFT_FRAME; }
		if (timer > VORTELITE_HOLD_GUN_OUT_TIME)
		{
			timer = 0;
			state = VORTELITE_FIRED;

			CRay *newobject;
			if (movedir==RIGHT)
				newobject = new CRay(mp_Map, getXRightPos()+1, getYPosition()+(9<<STC), RIGHT);
			else
				newobject = new CRay(mp_Map, getXLeftPos()-1, getYPosition()+(9<<STC), LEFT);
			newobject->setOwner( m_type, m_index);
			newobject->sprite = ENEMYRAYEP2;
			// don't shoot other vorticon elite
			m_Object.push_back(newobject);

			if (onscreen)
				playSound(SOUND_KEEN_FIRE);
		}
		else timer++;
		break;
	case VORTELITE_FIRED:
		if (movedir==RIGHT)
		{ sprite = VORTELITE_FIRE_RIGHT_FRAME; }
		else
		{ sprite = VORTELITE_FIRE_LEFT_FRAME; }

		if (timer > VORTELITE_HOLD_GUN_AFTER_FIRE_TIME)
		{
			timer = 0;
			frame = 0;
			timesincefire = 0;
			state = VORTELITE_WALK;
			// head toward keen
			if (getXPosition() < m_Player[0].getXPosition())
			{
				movedir = RIGHT;
			}
			else
			{
				movedir = LEFT;
			}
		}
		else timer++;
		break;
	case VORTELITE_DYING:
		sprite = VORTELITE_DYING_FRAME;
		if (animtimer > VORTELITE_DIE_ANIM_TIME)
		{
			sprite = VORTELITE_DEAD_FRAME;
			dead = true;
		}
		else
		{
			animtimer++;
		}
		break;
	default: break;
	}
}
Esempio n. 24
0
   void CEPuckLightSensor::Update() {
      /* Here we assume that the e-puck is rotated only wrt to the Z axis */

      /* Erase readings */
      for(size_t i = 0; i < m_tReadings.size(); ++i) {
         m_tReadings[i].Value = 0.0f;
      }
      /* Get e-puck position */
      const CVector3& cEPuckPosition = GetEntity().GetEmbodiedEntity().GetPosition();
      /* Get e-puck orientation */
      CRadians cTmp1, cTmp2, cOrientationZ;
      GetEntity().GetEmbodiedEntity().GetOrientation().ToEulerAngles(cOrientationZ, cTmp1, cTmp2);
      /* Buffer for calculating the light--e-puck distance */
      CVector3 cLightDistance;
      /* Buffer for the angle of the sensor wrt to the e-puck */
      CRadians cLightAngle;
      /* Initialize the occlusion check ray start to the baseline of the e-puck */
      CRay cOcclusionCheckRay;
      cOcclusionCheckRay.SetStart(cEPuckPosition);
      /* Buffer to store the intersection data */
      CSpace::SEntityIntersectionItem<CEmbodiedEntity> sIntersectionData;
      /* Ignore the sensing ropuck when checking for occlusions */
      TEmbodiedEntitySet tIgnoreEntities;
      tIgnoreEntities.insert(&GetEntity().GetEmbodiedEntity());
      /*
       * 1. go through the list of light entities in the scene
       * 2. check if a light is occluded
       * 3. if it isn't, distribute the reading across the sensors
       *    NOTE: the readings are additive
       * 4. go through the sensors and clamp their values
       */
      try{
         CSpace::TAnyEntityMap& tEntityMap = m_cSpace.GetEntitiesByType("light_entity");
         for(CSpace::TAnyEntityMap::iterator it = tEntityMap.begin();
             it != tEntityMap.end();
             ++it) {
            /* Get a reference to the light */
            CLightEntity& cLight = *(any_cast<CLightEntity*>(it->second));
            /* Consider the light only if it has non zero intensity */
            if(cLight.GetIntensity() > 0.0f) {
               /* Get the light position */
               const CVector3& cLightPosition = cLight.GetPosition();
               /* Set the ray end */
               cOcclusionCheckRay.SetEnd(cLightPosition);
               /* Check occlusion between the e-puck and the light */
               if(! m_cSpace.GetClosestEmbodiedEntityIntersectedByRay(sIntersectionData,
                                                                      cOcclusionCheckRay,
                                                                      tIgnoreEntities)) {
                  /* The light is not occluded */
                  if(m_bShowRays) GetEntity().GetControllableEntity().AddCheckedRay(false, cOcclusionCheckRay);
                  /* Get the distance between the light and the e-puck */
                  cOcclusionCheckRay.ToVector(cLightDistance);
                  /* Linearly scale the distance with the light intensity
                     The greater the intensity, the smaller the distance */
                  cLightDistance /= cLight.GetIntensity();
                  /* Get the angle wrt to e-puck rotation */
                  cLightAngle = cLightDistance.GetZAngle();
                  cLightAngle -= cOrientationZ;
                  /* Transform it into counter-clockwise rotation */
                  cLightAngle.Negate().UnsignedNormalize();
                  /* Find reading corresponding to the sensor */
                  SInt16 nMin = 0;
                  for(SInt16 i = 1; i < NUM_READINGS; ++i){
                     if((cLightAngle - m_tReadings[i].Angle).GetAbsoluteValue() < (cLightAngle - m_tReadings[nMin].Angle).GetAbsoluteValue())
                        nMin = i;
                  }
                  /* Set the actual readings */
                  Real fReading = cLightDistance.Length();
                  m_tReadings[Modulo((SInt16)(nMin-1), NUM_READINGS)].Value += ComputeReading(fReading * Cos(cLightAngle - m_tReadings[Modulo(nMin-1, NUM_READINGS)].Angle));
                  m_tReadings[  nMin                                ].Value += ComputeReading(fReading);
                  m_tReadings[Modulo((SInt16)(nMin+1), NUM_READINGS)].Value += ComputeReading(fReading * Cos(cLightAngle - m_tReadings[Modulo(nMin+1, NUM_READINGS)].Angle));
               }
               else {
                  /* The ray is occluded */
                  if(m_bShowRays) {
                     GetEntity().GetControllableEntity().AddCheckedRay(true, cOcclusionCheckRay);
                     GetEntity().GetControllableEntity().AddIntersectionPoint(cOcclusionCheckRay, sIntersectionData.TOnRay);
                  }
               }
            }
         }
      }
      catch(argos::CARGoSException& e){

      }

      /* Now go through the sensors, add noise and clamp their values if above 1024 or under 1024 */
      for(size_t i = 0; i < m_tReadings.size(); ++i) {
         if(m_fNoiseLevel>0.0f)
            AddNoise(i);
         if(m_tReadings[i].Value > 1024.0f)
            m_tReadings[i].Value = 1024.0f;
         if(m_tReadings[i].Value < 0.0f)
            m_tReadings[i].Value = 0.0f;
      }
   }
Esempio n. 25
0
bool CUtils::IntersectTriangle(const CRay &i_Ray,
                               CIntersactionInfo &io_IntersectionInfo,
                               const CVector3DF &i_vA,
                               const CVector3DF &i_vB,
                               const CVector3DF &i_vC)
{

    //intersect stuff
    double lambda2;
    double lambda3;
    double closestdist = io_IntersectionInfo.m_fDistance;

    const CVector3DF a = i_vB - i_vA;
    const CVector3DF b = i_vC - i_vA;

    CVector3DF c = - (i_Ray.Direction());
    CVector3DF h = i_Ray.StartPoint() - i_vA;
    /* 2. Solve the equation:
         *
         * A + lambda2 * AB + lambda3 * AC = ray.start + gamma * ray.dir
         *
         * which can be rearranged as:
         * lambda2 * AB + lambda3 * AC - gamma * ray.dir = ray.start - A
         *
         * Which is a linear system of three rows and three unknowns, which we solve using Carmer's rule
         */
    //
    // Find the determinant of the left part of the equation
    const float Dcr = CVector3DF::Triple(a, b, c);
    // check for zero; if it is zero, then the triangle and the ray are parallel
    if (fabs(Dcr) < k_fSMALL)
    {
        return false;
    }
    // find the reciprocal of the determinant. We would use this quantity later in order
    // to multiply by rDcr instead of divide by Dcr (division is much slower)
    double rDcr = 1.0 / Dcr;
    // calculate `gamma' by substituting the right part of the equation in the third column of the matrix,
    // getting the determinant, and dividing by Dcr)
    const double gamma = CVector3DF::Triple(a, b, h) * rDcr;
    // Is the intersection point behind us?  Is the intersection point worse than what we currently have?
    if (gamma <= 0 || gamma > closestdist)
    {
        return false;
    }
    lambda2 = CVector3DF::Triple(h, b, c) * rDcr;
    // Check if it is in range (barycentric coordinates)
    if (lambda2 < 0 || lambda2 > 1)
    {
        return false;
    }
    lambda3 = CVector3DF::Triple(a, h, c) * rDcr;

    // Calculate lambda3 and check if it is in range as well
    if (lambda3 < 0 || lambda3 > 1)
    {
        return false;
    }
    if (lambda2 + lambda3 > 1)
    {
        return false;
    }

    closestdist = gamma;
    io_IntersectionInfo.m_fDistance = closestdist;
    
    io_IntersectionInfo.m_vIntersectionPoint = i_Ray.GetPointAtDistance(closestdist);

    io_IntersectionInfo.m_vBarCoordsLocal.SetX(1.0f - lambda2 - lambda3);
    io_IntersectionInfo.m_vBarCoordsLocal.SetY(lambda2);
    io_IntersectionInfo.m_vBarCoordsLocal.SetZ(lambda3);

    //Normal to the surface
    io_IntersectionInfo.m_vNormal = CVector3DF::Normal(a, b);

    return true;
}
Esempio n. 26
0
bool CBezierPatch::intersect(const CRay &ray, CIntersactionInfo &info, CVector3DF barCoord, unsigned int iterations, bool bDebug) const
{
    //Planes along ray
    CVector3DF N1 = ray.Direction().Cross(CVector3DF(-1.0f,-1.0f,-1.0f));
    CVector3DF N2 = ray.Direction().Cross(N1);
    const float d1 = -N1.Dot(ray.StartPoint());
    const float d2 = -N2.Dot(ray.StartPoint());

    float fSMall = 1e-3;

    CVector3DF dBu, dBv;

    for (unsigned int i = 0; i < iterations; i++)
    {
        const double &u(barCoord.X());
        const double &v(barCoord.Y());

        //partial U derivative of B
        dBu = GetdBu(u,v);

        //Partial V derivative of B
        dBv = GetdBv(u,v);

        const CVector3DF B = GetPointFromBarycentric(barCoord);

        const CVector3DF R = CVector3DF(N1.Dot(B) + d1,
                                        N2.Dot(B) + d2,
                                        0);

        if ( ( fabs(R.X()) < fSMall ) &&
             ( fabs(R.Y()) < fSMall ) )
        {
            break;
        }

        //Inverse Jacobian
        const float fN1dotdBu = N1.Dot(dBu);
        const float fN1dotdBv = N1.Dot(dBv);
        const float fN2dotdBu = N2.Dot(dBu);
        const float fN2dotdBv = N2.Dot(dBv);

        const float invConst = 1.0f / ( fN1dotdBu * fN2dotdBv - fN1dotdBv * fN2dotdBu );

        Matrix inverseJacobian;

        inverseJacobian[0][0] = fN2dotdBv  * invConst;
        inverseJacobian[0][1] = -fN2dotdBu * invConst;
        inverseJacobian[0][2] = 0;

        inverseJacobian[1][0] = -fN1dotdBv * invConst;
        inverseJacobian[1][1] = fN1dotdBu * invConst;
        inverseJacobian[1][2] = 0;

        inverseJacobian[2][0] = 0;
        inverseJacobian[2][1] = 0;
        inverseJacobian[2][2] = 1;

        //Newton Iteration

        barCoord = barCoord - R.MatrixMultiply(inverseJacobian);
        barCoord.SetZ(1.0 - barCoord.X() - barCoord.Y());

        if (barCoord.X() > k_fMAX || barCoord.X() < k_fMIN
                || barCoord.Y() > k_fMAX || barCoord.Y() < k_fMIN
                || barCoord.Z() > k_fMAX || barCoord.Z() < k_fMIN)
        {
            return false;
        }        
    }

    const float &u(barCoord.X());
    const float &v(barCoord.Y());
    const float w(1.0 - u - v);

    if (u < -k_fSMALL || u > 1.0f + k_fSMALL
            || v < -k_fSMALL || v > 1.0f + k_fSMALL
            || w < -k_fSMALL || w > 1.0f + k_fSMALL)
    {
        return false;
    }

    if (bDebug)
    {
        char str[100];
        sprintf( str, "u: %4.2f v: %4.2f w: %4.2f",  u, v, w);
        qDebug() << str;
    }

    //Calculating B
    const CVector3DF B = GetPointFromBarycentric(barCoord);

    if ( ( fabs(N1.Dot(B) + d1) > fSMall ) ||
         ( fabs(N2.Dot(B) + d2) > fSMall ) )
    {
        if (bDebug)
        {
            qDebug() << "error too big";
        }
        return false;
    }

    // calculate the intersection
    float len = (B - ray.StartPoint()).Length();
    if (len > info.m_fDistance)
    {
        if (bDebug)
        {
            qDebug() << "Len > Distance";
        }
        return false;
    }

    info.m_vIntersectionPoint = B;
    info.m_fDistance = len;

    info.m_vBarCoordsLocal.SetX(u);
    info.m_vBarCoordsLocal.SetY(v);
    info.m_vBarCoordsLocal.SetZ(w);

    info.m_vBarCoordsGlobal = info.m_vBarCoordsLocal;

    if (GetSettings()->m_bNormalSmoothing)
    {
        info.m_vNormal = GetSmoothedNormal(barCoord);
    }
    else
    {
//        info.m_vNormal = GetSmoothedNormal(barCoord);
        info.m_vNormal = CVector3DF::Normal(dBu, dBv);
    }

    if (bDebug)
    {
        qDebug()<< "Patch Hit!";
    }

    return true;
}
Esempio n. 27
0
bool CTriangleMesh::Hit(CRay const& ray, CIntersection & intersection) const
{
	// Вычисляем обратно преобразованный луч (вместо вполнения прямого преобразования объекта)
	CRay invRay = Transform(ray, GetInverseTransform());
	CVector3d const& invRayStart = invRay.GetStart();
	CVector3d const& invRayDirection = invRay.GetDirection();

	//////////////////////////////////////////////////////////////////////////
	// Здесь следует выполнить проверку на пересечение луча с ограничивающим
	// объемом (bounding volume) полигональной сетки.
	// При отсутствии такого пересечения луч гарантированно не будет пересекать
	// ни одну из граней сетки, что позволит избежать лишних проверок:
	// if (!ray_intesects_bounding_volume)
	//     return false;
	//////////////////////////////////////////////////////////////////////////
	
	// Получаем информацию о массиве треугольников сетки
	CTriangle const* const triangles = m_pMeshData->GetTriangles();
	const size_t numTriangles = m_pMeshData->GetTriangleCount();

	// Массив найденных пересечений луча с гранями сетки.
	std::vector<FaceHit> faceHits;

	//////////////////////////////////////////////////////////////////////////
	// Используется поиск пересечения луча со всеми гранями сетки.
	// Данный подход является очень неэффективным уже на полигональных сетках,
	// содержащих более нескольких десятков граней, а, тем более, сотни и тысячи граней.
	//
	// Для эффективного поиска столкновений следует представить полигональную сетку
	// не в виде массива граней, а в виде древовидной структуры (Oct-Tree или BSP-Tree),
	// что уменьшит вычислительную сложность поиска столкновений с O(N) до O(log N)
	//////////////////////////////////////////////////////////////////////////
	FaceHit hit;
	for (size_t i = 0; i < numTriangles; ++i)
	{
		CTriangle const& triangle = triangles[i];

		// Проверка на пересечение луча с треугольной гранью
		if (triangle.HitTest(invRayStart, invRayDirection, hit.hitTime, hit.hitPointInObjectSpace, hit.w0, hit.w1, hit.w2))
		{
			// Сохраняем индекс грани и добавляем информацию в массив найденных пересечений
			hit.faceIndex = i;

			if (faceHits.empty())
			{
				// При обнаружени первого пересечения резервируем
				// память сразу под 8 пересечений (для уменьшения количества операций выделения памяти)
				faceHits.reserve(8);
			}
			faceHits.push_back(hit);
		}
	}

	// При отсутствии пересечений выходим
	if (faceHits.empty())
	{
		return false;
	}

	//////////////////////////////////////////////////////////////////////////
	// Упорядочиваем найденные пересечения по возрастанию времени столкновения
	//////////////////////////////////////////////////////////////////////////
	size_t const numHits = faceHits.size();
	std::vector<FaceHit const *> hitPointers(numHits);
	{
		// Инициализируем массив указателей на точки пересечения
		for (size_t i = 0; i < numHits; ++i)
		{
			hitPointers[i] = &faceHits[i];
		}

		// Сортируем массив указателей по возрастанию времени столкновения
		// Сортируются указатели, а не сами объекты, чтобы сократить
		// издержки на обмен элементов массива:
		// На 32 битной платформе размер структуры FaceHit равен 64 байтам,
		// а размер указателя - всего 4 байта.
		if (numHits > 1)
		{
			std::sort(hitPointers.begin(), hitPointers.end(), HitPointerComparator());
			// Теперь указатели в массиве hitPointers отсортированы
			// в порядке возрастания времени столкновения луча с гранями
		}
	}

	//////////////////////////////////////////////////////////////////////////
	// Возвращаем информацию о найденных пересечениях
	//////////////////////////////////////////////////////////////////////////
	for (size_t i = 0; i < numHits; ++i)
	{
		// Получаем информацию о столкновении
		FaceHit const& faceHit = *hitPointers[i];

		// Сохраняем информацию только о первом пересечении
		if (i == 0)
		{
			ExtendedHitData *hd = (ExtendedHitData*)&m_lastHitData;
			hd->faceIndex = faceHit.faceIndex;
			hd->vc[0] = static_cast<float>(faceHit.w0);
			hd->vc[1] = static_cast<float>(faceHit.w1);
			hd->vc[2] = static_cast<float>(faceHit.w2);
		}

		// Точка столкновения в мировой системе координат
		CVector3d hitPoint = ray.GetPointAtTime(faceHit.hitTime);

		// Грань, с которой произошло столкновение
		CTriangle const& triangle = triangles[faceHit.faceIndex];

		// Нормаль "плоской грани" во всех точках столкновения равна нормали самой грани
		CVector3d normalInObjectSpace = triangle.GetPlaneEquation();

		if (!triangle.IsFlatShaded())
		{
			// Для неплоских граней выполняется интерполяция нормалей вершин треугольника
			// с учетом их весовых коэффициентов в точке пересечения
			Vertex const& v0 = triangle.GetVertex0();
			Vertex const& v1 = triangle.GetVertex1();
			Vertex const& v2 = triangle.GetVertex2();

			// Взвешенный вектор нормали
			normalInObjectSpace = 
				faceHit.w0 * v0.normal + 
				faceHit.w1 * v1.normal +
				faceHit.w2 * v2.normal;
		}

		// Нормаль в мировой системе координат
		CVector3d normal = GetNormalMatrix() * normalInObjectSpace;

		// Добавляем информацию о точке пересечения в объект intersection
		intersection.AddHit(
			CHitInfo(
				faceHit.hitTime, *this, 
				hitPoint,
				faceHit.hitPointInObjectSpace,
				normal, normalInObjectSpace
				)
			);
	}

	return true;
}
Esempio n. 28
0
// AI for the Spark object in the Tantalus Ray Machine's of ep2
void CSpark::process()
{
	int mx,my,x,y;

	mx = getXPosition() >> CSF;
	my = getYPosition() >> CSF;

	if (state==SPARK_ANIMATE)
	{
		sprite = SPARK_BASEFRAME + frame;
	}
	else
	{
		sprite = BLANKSPRITE;
	}

	switch(state)
	{
	case SPARK_ANIMATE:
		if (timer > SPARK_ANIMRATE)
		{
			frame++;
			if (frame > 3) frame = 0;
			timer = 0;
		} else timer++;

		if ( mHealthPoints <= 0 && state == SPARK_ANIMATE )
		{
			playSound(SOUND_SHOT_HIT);

			// break the glass and blow out the electric arcs
			mp_Map->setTile(mx - 2, my, 492, true);
			mp_Map->setTile(mx - 1, my, 546, true);
			mp_Map->setTile(mx, my, 547, true);
			mp_Map->setTile(mx + 1, my, 548, true);
			mp_Map->setTile(mx + 2, my, 492, true);
			// remove the unneeded dome tiles
			mp_Map->setTile(mx - 1, my-1, BG_GREY, true);
			mp_Map->setTile(mx, my-1, BG_GREY, true);
			mp_Map->setTile(mx + 1, my-1, BG_GREY, true);
			// break the switch
			mp_Map->setTile(mx - 3, my + 4, 506, true);

			// meltdown!
			state = SPARK_BLOWUP1;
			timer = 0;
			blowy = 0;
		}
		break;
	case SPARK_BLOWUP1:
		// one by one blow out the purple thingies below the device
		if (timer > SPARK_BLOW_DELAY)
		{
			timer = 0;
			my = my+3+blowy;
			mp_Map->setTile(mx, my, 505, true);
			// spawn a ZAP! or a ZOT!
            CRay *newobject = new CRay(mp_Map, mx<<CSF, my<<CSF, CENTER, DOWN, getSpriteVariantId());
			newobject->state = CRay::RAY_STATE_SETZAPZOT;
			newobject->setOwner(m_type, m_index);
			gEventManager.add( new EventSpawnObject(newobject) );
			playSound(SOUND_SHOT_HIT);

			blowy++;
			if (blowy >= 3)
			{
				state = SPARK_BLOWUP2;
				blowx = 0;
			}
		}
		else timer++;
		break;
	case SPARK_BLOWUP2:
		// blow out the glowing cells
		if (timer > SPARK_BLOW_DELAY)
		{
			if (blowx >= 4)
			{
				// done blowing up the glowcells
				// static the targeting display
				mx = mx - 7;
				my = my + 2;
				for(y=0;y<3;y++)
				{
					for(x=0;x<3;x++)
					{
						mp_Map->setTile(mx+x,my+y,533, true);
					}
				}
				exists = false;
				return;
			}

			timer = 0;
			mx = mx + blowx + 3;
			for(y=3;y<6;y++)
			{
				//my = my+3+y;
				//my = my+y;
				mp_Map->setTile(mx, my+y, 549, true);
				// spawn a ZAP! or a ZOT!
                CRay *newobject = new CRay(mp_Map, mx<<CSF, (my+y)<<CSF, CENTER, DOWN, getSpriteVariantId());
				newobject->setOwner(m_type ,m_index);
				newobject->state = CRay::RAY_STATE_SETZAPZOT;
				playSound(SOUND_SHOT_HIT);
				gEventManager.add(new EventSpawnObject(newobject));
			}

			blowx++;
		}
		else timer++;
		break;
	default: break;
	}  // end of state switch for SE_SPARK
}
Esempio n. 29
0
Color Union::rayTrace(CRay ray, int depth, CObject* &_object,IntersectResult*& res)
{
    if(depth>max_depth)  return Color::white();
    int size = (int)CVector.size();
    float distance = 100000000.0f;
    CObject* primitive_near = NULL;
    bool visible = true;
    Color totalColor = Color::black();
    CObject* pLight;
    int num=0;
    IntersectResult s = IntersectResult::noHit();
    for(int i=0;i<size;i++){
        CObject* primitive = CVector.at(i);
        IntersectResult result = primitive->isIntersected(ray);
        if(result.isHit){
            if(result.distance < distance){
                s = result;
                distance = result.distance;
                primitive_near = result.object;
                num = i;
            }
        }
    }
    _object = primitive_near;
    res = &s;
    if(primitive_near == NULL) {

        return Color::black();
    }
    else if(primitive_near->isLight()){

        return Color::white();
    }
    else if(!s.front){
        cout<<depth<<" "<<s.object->code<<endl;
        GVector3 v = ray.getDirection();
        v = v.normalize();
        GVector3 normal = s.normal.normalize();
        double cosA = v.dotMul(normal);
        double sinA = sqrt(1-cosA*cosA);
        double n = 1.000 / 1.500;
        //cout<<sinA<<endl;
        if(sinA >= n){
            //cout<<"zhixingle"<<endl;
            CRay newray;
            newray.setDirection(normal*(-cosA) + (ray.getDirection() - normal*cosA).normalize()*sinA);
            newray.setOrigin(s.position + ray.getDirection()*1e-3);
            CObject* no_use = NULL;
            IntersectResult* n0=NULL;
            Color refraction_second = rayTrace(newray,depth+1,no_use,n0);
            //cout<<refraction_second.r<<" "<<refraction_second.g<<" "<<refraction_second.b<<endl;
            Color absorbance(0,0,0);
            if(n0){
                Color absorbance = primitive_near->getMaterial()->getColor().multiply(0.15f * ((-1)*n0->distance));
            }
            Color transparancy = Color(exp(absorbance.r),exp(absorbance.g),exp(absorbance.b));
            return refraction_second.moderate(transparancy);
        }
        else{

            double sinB = sinA / n;

            double cosB = sqrt(1 - sinB*sinB);

            CRay newray;
            newray.setDirection(normal*cosB + (v-normal*cosA).normalize()*sinB);
            newray.setOrigin(s.position + newray.getDirection()*1e-3);
            //cout<<"Origin:"<<newray.getOrigin().getX()<<" "<<newray.getOrigin().getY()<<" "<<newray.getOrigin().getZ()<<endl;
            //cout<<"Direction:"<<newray.getDirection().getX()<<" "<<newray.getDirection().getY()<<" "<<newray.getDirection().getZ()<<endl;
            CObject* no_use = NULL;
            IntersectResult* n0=NULL;
            Color refraction_second = rayTrace(newray,depth+1,no_use,n0);
            //cout<<refraction_second.r<<" "<<refraction_second.g<<" "<<refraction_second.b<<endl;
            Color absorbance(0,0,0);
            if(n0){
                Color absorbance = primitive_near->getMaterial()->getColor().multiply(0.15f * ((-1)*n0->distance));
            }
            Color transparancy = Color(exp(absorbance.r),exp(absorbance.g),exp(absorbance.b));
            return refraction_second.moderate(transparancy);
        }
    }
    else{
        GVector3 point;
        point = ray.getPoint(distance);
        for(int i=0;i<size;i++){
            CObject* primitive = CVector.at(i);
            if(primitive->isLight()){
                pLight = primitive;
                GVector3 inDir = ((Lamp*) primitive)->getCenter() - point;
                inDir = inDir.normalize();
                CRay line(point+inDir*0.001,inDir);
                for(int j=0;j<size;j++){
                    CObject* ano_primitive = CVector.at(j);
                    if(!ano_primitive->isLight() && j!=num){
                        IntersectResult result = ano_primitive->isIntersected(line);
                        if(result.isHit && result.distance < inDir.getLength()){
                            visible = false;
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
    GVector3 point;
    point = ray.getPoint(distance);

    if(visible){
        GVector3 lig = ((Lamp*)pLight)->getCenter() - point;
        lig = lig.normalize();
        primitive_near->getMaterial()->setLightDir(lig);
        totalColor = totalColor.add( primitive_near->getMaterial()->sample(ray, point, primitive_near->getNormal(point)) );
    }
    float reflection = primitive_near->getMaterial()->getRef();
    if( (reflection>0.0f) && (depth<max_depth) ){
        GVector3 normal_point = primitive_near->getNormal(point);
        normal_point = normal_point.normalize();
        float s0 = ray.getDirection().dotMul(normal_point) * (-2.0f);
        CRay newRay;
        newRay.setDirection(normal_point * s0 + ray.getDirection());
        newRay.setOrigin(point + newRay.getDirection()*1e-3);
        CObject* no_use = NULL;
        IntersectResult* n0=NULL;
        Color reflectionColor = rayTrace(newRay,depth+1,no_use,n0);
        reflectionColor = reflectionColor.multiply(reflection);
        //reflectionColor = reflectionColor.moderate(primitive_near->getMaterial()->getColor());
        totalColor = totalColor.add(reflectionColor.moderate(primitive_near->getMaterial()->getColor()));
    }
    float refraction = primitive_near->getMaterial()->getRefr();
    //cout<<refraction<<endl;
    if((refraction>0.0f) && (depth<max_depth)){

        GVector3 normal_point = primitive_near->getNormal(point);
        GVector3 Direction = ray.getDirection().normalize();
        normal_point = normal_point.normalize();
        float cosA = -Direction.dotMul(normal_point);
        float sinA = sqrt(1-cosA*cosA);
        float sinB = sinA / 1.5;
        float cosB = sqrt(1 - sinB*sinB);
        //cout<<sinA<<" "<<cosA<<" "<<sinB<<" "<<cosB<<endl;
        CRay newray;
        newray.setDirection(normal_point*(-cosB) + (Direction + normal_point*cosA).normalize()*sinB);
        newray.setOrigin(point + newray.getDirection() * 1e-3);
        CObject* no_use = NULL;
        IntersectResult* n0=NULL;
        Color refractionColor = rayTrace(newray,depth+1,no_use,n0);
        refractionColor = refractionColor.multiply(refraction);
        //refractionColor = refractionColor.moderate(primitive_near->getMaterial()->getColor());
        totalColor = totalColor.add(refractionColor);
    }
    return totalColor;
}
Esempio n. 30
0
bool  CCone::trace(CRay ray, float& t)
{
  static float  R = r1,//max(r1,r2),
    r = r2;//min(r1,r2);
  CRay Ray = TransferToCanonical(ray);
  SavedEyeRay = ray;
  float Dirx = Ray._2.m[0], Diry = Ray._2.m[2], Dirz = Ray._2.m[1],
    Eyex = Ray._1.m[0], Eyey = Ray._1.m[2], Eyez = Ray._1.m[1],

    s = r / R, k = s - 1, d = k*Dirz, f = 1 + k*Eyez,

    A = Dirx*Dirx + Diry*Diry - d*d,
    B = (Eyex*Dirx + Eyey*Diry - f*d) * 2,
    C = Eyex*Eyex + Eyey*Eyey - f*f;

  float D = B*B - 4.0f*A*C;

  if (D >= 0) //бокова¤ поверхность
  {
    t = (-B - sqrtf(D)) / (2.0f*A);
    fl3 P = Ray.getPoint(t);

    if (t < 0) return false;

    fl3 Vscale = fl3(R, h, R),

      P1 = (Ray._1) ^ Vscale,
      P2 = P ^ Vscale;

    float norm1 = norm(P1 - P2);
    float norm2 = norm(ray._2);
    t = norm1 / norm2;

    SavedPoint = TransferToCanonical(ray.getPoint(t));

    SavedNormal = normalize(fl3(SavedPoint.m[0], (R - r) / h, SavedPoint.m[2]));

    if (P.m[1] <= 1 && P.m[1] >= 0) return true;
  }

  float t1 = -Eyez / Dirz,    //нижнее основание 
    t2 = t1 + 1.0f / Dirz; //верхнее
  t = min(t1, t2);
  fl3   P = Ray.getPoint(t);

  if (t < 0) return false;

  fl3 Vscale = fl3(R, h, R),
    P1 = (Ray._1) ^ Vscale,
    P2 = P ^ Vscale;
  float norm1 = norm(P1 - P2);
  float norm2 = norm(ray._2);
  t = norm1 / norm2;

  SavedPoint = TransferToCanonical(ray.getPoint(t));

  float px = P.m[0],
    py = P.m[2];
  if (t1 < t2)
  {
    SavedNormal = fl3(0, -1, 0);
    return (px*px + py*py <= 1);
  }
  else
  {
    SavedNormal = fl3(0, 1, 0);
    return (px*px + py*py <= s*s);
  }
}