Example #1
0
        GeometryRayTestResult Intersects(const Sphere& Ball, const Ray& Cast)
        {
            // Code in this function is based on the equivalent in Ogre
            const Vector3 CastDir = Cast.GetNormal();
            const Vector3 CastOrigin = Cast.GetOrigin() - Ball.Center; // Makes math easier to do this in sphere local coordinates
            const Real Radius = Ball.Radius;

            // Build coefficients for our formula
            // t = (-b +/- sqrt(b*b + 4ac)) / 2a
            Real ACoEff = CastDir.DotProduct(CastDir);
            Real BCoEff = 2 * CastOrigin.DotProduct(CastDir);
            Real CCoEff = CastOrigin.DotProduct(CastOrigin) - ( Radius * Radius );

            // Get the Determinate
            Real Determinate = ( BCoEff * BCoEff ) - ( 4 * ACoEff * CCoEff );
            if( Determinate < 0 ) {
                return GeometryRayTestResult(false,Ray());
            }else{
                Real NearDist = ( -BCoEff - MathTools::Sqrt( Determinate ) ) / ( 2 * ACoEff );
                Real FarDist = ( -BCoEff + MathTools::Sqrt( Determinate ) ) / ( 2 * ACoEff );

                Ray Ret( Cast.GetOrigin() + (CastDir * NearDist), Cast.GetOrigin() + (CastDir * FarDist) );
                return GeometryRayTestResult(true,Ret);
            }
        }
Example #2
0
File: Ray.cpp Project: PeteX/Urho3D
float Ray::HitDistance(const Sphere& sphere) const
{
    Vector3 centeredOrigin = origin_ - sphere.center_;
    float squaredRadius = sphere.radius_ * sphere.radius_;
    
    // Check if ray originates inside the sphere
    if (centeredOrigin.LengthSquared() <= squaredRadius)
        return 0.0f;
    
    // Calculate intersection by quadratic equation
    float a = direction_.DotProduct(direction_);
    float b = 2.0f * centeredOrigin.DotProduct(direction_);
    float c = centeredOrigin.DotProduct(centeredOrigin) - squaredRadius;
    float d = b * b - 4.0f * a * c;
    
    // No solution
    if (d < 0.0f)
        return M_INFINITY;
    
    // Get the nearer solution
    float dSqrt = sqrtf(d);
    float dist = (-b - dSqrt) / (2.0f * a);
    if (dist >= 0.0f)
        return dist;
    else
        return (-b + dSqrt) / (2.0f * a);
}
Example #3
0
//---------------------------
//
//---------------------------
void Matrix44::SetView( const Vector3& vPos, const Vector3& vDir_, const Vector3& vUp_ )
{
	Vector3 vDir;
	Vector3 vUp;
	Vector3 vCross;

	vDir = vDir_.Normal();
	vCross = vUp_.CrossProduct( vDir );
	vCross.Normalize();
	vUp = vDir.CrossProduct( vCross );

	_11 = vCross.x;
	_12 = vUp.x;
	_13 = vDir.x;
	_14 = 0.0F;
	_21 = vCross.y;
	_22 = vUp.y;
	_23 = vDir.y;
	_24 = 0.0F;
	_31 = vCross.z;
	_32 = vUp.z;
	_33 = vDir.z;
	_34 = 0.0F;
	_41 = -vPos.DotProduct( vCross );
	_42 = -vPos.DotProduct( vUp );
	_43 = -vPos.DotProduct( vDir );
	_44 = 1.0F;
} //Matrix44::SetView
Example #4
0
void Matrix44::SetView( const Vector3& pos, const Vector3& dir0, const Vector3& up0 )
{
	Vector3 vDir;
	Vector3 vUp;
	Vector3 vCross;

	vDir = dir0.Normal();
	vCross = up0.CrossProduct( vDir );
	vCross.Normalize();
	vUp = vDir.CrossProduct( vCross );

	_11 = vCross.x;
	_12 = vUp.x;
	_13 = vDir.x;
	_14 = 0.0f;
	_21 = vCross.y;
	_22 = vUp.y;
	_23 = vDir.y;
	_24 = 0.0f;
	_31 = vCross.z;
	_32 = vUp.z;
	_33 = vDir.z;
	_34 = 0.0f;
	_41 = -pos.DotProduct( vCross );
	_42 = -pos.DotProduct( vUp );
	_43 = -pos.DotProduct( vDir );
	_44 = 1.0f;
}
Example #5
0
/**
*  @brief
*    Calculate the intersection of a ray and a triangle
*/
dFloat BodyTerrain::RayCastTriangle(const Vector3 &p0, const Vector3 &dp, const Vector3 &origin, const Vector3 &e1, const Vector3 &e2)
{
	dFloat t;
	dFloat b0;
	dFloat b1;
	dFloat b00;
	dFloat b11;
	dFloat a00;
	dFloat a10;
	dFloat a11;
	dFloat det;
	dFloat dot;
	dFloat tol;

	// Clip line again first triangle
	Vector3 normal(e2.CrossProduct(e1));

	dot = normal.DotProduct(dp);
	if (dot <= 1.0e-6f) {
		t = ((origin - p0).DotProduct(normal)) / dot;
		if (t > 0.0f) {
			if (t < 1.0f) {
				Vector3 q = p0 + dp*t;
				a00 = e1.DotProduct(e1);
				a11 = e2.DotProduct(e2);
				a10 = e1.DotProduct(e2);
				det = a00*a11 - a10*a10;
				// det must be positive and different than zero
//				_ASSERTE(det > 0.0f);
				
				Vector3 q0p0 = q - origin;
				b0 = q0p0.DotProduct(e1);
				b1 = q0p0.DotProduct(e2);

				tol = -det*1.0e-3f;
				b00 = b0*a11 - b1*a10;
				if (b00 >= tol) {
					b11 = b1*a00 - b0*a10;
					if (b11 >= tol) {
						if ((b00 + b11) <= (det*1.001f)) {
							// Found a hit return this value
							return t;
						}
					}
				}
			}
		}
	}

	// If it come here the there no intersection
	return 1.2f;
}
Example #6
0
void IK::DefineM(const Vector3 p, const Vector3 d)
{
	Vector3 mX,mY,mZ;

	// Minv defines a coordinate system whose x axis contains P, so X = unit(P).
	mX = p.Normalized();

	// The y axis of Minv is perpendicular to P, so Y = unit( D - X(D·X) ).

    float  dDOTx = d.DotProduct(mX);
   	mY.x_ = d.x_ - dDOTx * mX.x_;
   	mY.y_ = d.y_ - dDOTx * mX.y_;
   	mY.z_ = d.z_ - dDOTx * mX.z_;
    mY.Normalize();

	// The z axis of Minv is perpendicular to both X and Y, so Z = X×Y.

    mZ=mX.CrossProduct(mY);

    Minv = Matrix3(mX.x_,mX.y_,mX.z_,mY.x_,mY.y_,mY.z_,mZ.x_,mZ.y_,mZ.z_);
    //Minv = Minv.Transpose();
    Mfwd = Minv.Transpose();
	// Mfwd = (Minv)T, since transposing inverts a rotation matrix.

}
Example #7
0
Vector3 Vector3::Refract(const Vector3& n, double r_coeff) const
{
	Vector3 result;
	
	//TODO: Calculate the refraction of this vector given the input normal n and the refractive coefficient r_index
	//Store the result in result
	//Refraction is governed by the Snell's law

	// DONE


	double cosI = n.DotProduct(*this) * -1;

	// if cosI is negative then the normal is pointing the wrong way
	if (cosI < 0)
	{
		cosI *= -1;
	}

	double sinT2 = r_coeff * r_coeff * (1.0 - cosI * cosI);
	double cosT = sqrt(1.0 - sinT2);

	result = *this * r_coeff + n * (r_coeff * cosI - cosT);
	return result;
}
Example #8
0
void Quaternion::FromRotationTo(const Vector3& start, const Vector3& end)
{
    Vector3 normStart = start.Normalized();
    Vector3 normEnd = end.Normalized();
    float d = normStart.DotProduct(normEnd);
    
    if (d > -1.0f + M_EPSILON)
    {
        Vector3 c = normStart.CrossProduct(normEnd);
        float s = sqrtf((1.0f + d) * 2.0f);
        float invS = 1.0f / s;
        
        x_ = c.x_ * invS;
        y_ = c.y_ * invS;
        z_ = c.z_ * invS;
        w_ = 0.5f * s;
    }
    else
    {
        Vector3 axis = Vector3::RIGHT.CrossProduct(normStart);
        if (axis.Length() < M_EPSILON)
            axis = Vector3::UP.CrossProduct(normStart);
        
        FromAngleAxis(180.f, axis);
    }
}
Example #9
0
void OptimizeLigandGeomety(Conformer& ligand, double chi_increment, std::vector<double> chi_stdev, std::string lp_atom,
                           double unit_cell_length, double angle_tolerance, std::string output_dir) {
  if (ligand.parent()->conformer_states() == NULL)
    Log->error(FLERR, "There are no conformer states for the ligand!");
  const std::vector<Linkage<std::string> >& chi_names = ligand.parent()->conformer_states()->degrees_of_freedom();

  std::vector<double> chi_values = GetChiValues(ligand);
  //adjust chi to values between [0, 360]
  for (size_t i = 0; i < chi_values.size(); ++i) {
    chi_values[i] = (chi_values[i] < 0 ? chi_values[i] += 360 : chi_values[i]);
  }

  //loop through the possible chi angles, filling the ligand geometry map
  std::map<std::vector<double>, std::vector<double> > ligand_geometry;
  for(double chi1 = floor(chi_values[0] - chi_stdev[0]); chi1 < ceil(chi_values[0] + chi_stdev[0]); chi1 += chi_increment) {
    for(double chi2 = floor(chi_values[1] - chi_stdev[1]); chi2 < ceil(chi_values[1] + chi_stdev[1]); chi2 += chi_increment) {
      ligand.AdjustLinkage(chi_names[0], chi1);
      ligand.AdjustLinkage(chi_names[1], chi2);

      std::vector<double> chis;
      chis.push_back(chi1);
      chis.push_back(chi2);
      Vector3 v = CalculateLonePairDirection(ligand, lp_atom);

      //Calculate the dot product of v and z axis unit vector
      //cos(q) = v*w / (|v|*|w|)
      double angle_z = RADIANS_TO_DEGREES * acos(v.DotProduct(Vector3(0, 0, 1)) / v.Length());
      //Calculate the dot product of v and the vector from the N to the metal (where the C4 symmetry axis is)
      Atom* N = ligand.Find(lp_atom);
      Vector3 N_metal(unit_cell_length - N->x(), - N->y(), 0);
      double angle_metal = RADIANS_TO_DEGREES * acos(v.DotProduct(N_metal) / (v.Length() * N_metal.Length()));

      if ((angle_z < (90.0 + angle_tolerance) && angle_z > (90.0 - angle_tolerance)) && (angle_metal < angle_tolerance)) {
        ligand_geometry[chis].push_back(angle_z);
        ligand_geometry[chis].push_back(angle_metal);

        //OutputStructure(ligand.parent()->parent()->parent()->parent()->parent()->parent(), chis, lp_atom, output_dir);
        Log->print("Optimized Cu binding PDB with chi1 " + Log->to_str(chi1) + ", chi2 " + Log->to_str(chi2));

        OutputLatticeStructure(ligand.parent()->parent()->parent()->parent()->parent()->parent(), chis, unit_cell_length, lp_atom, output_dir);
      }
    }
  }

  OutputStat(ligand_geometry, lp_atom, output_dir);
}
Example #10
0
	Matrix4& Matrix4::LookAtLH( const Vector3& eye, const Vector3& at, const Vector3& up )
	{
		Vector3 zaxis = at - eye;
		zaxis.Normalize();

		Vector3 nup = up;
		nup.Normalize();

		Vector3 xaxis = zaxis.CrossProduct( nup );
		Vector3 yaxis = xaxis.CrossProduct( zaxis );

		A[0][0] = xaxis.X;	A[1][0] = xaxis.Y;	A[2][0] = xaxis.Z;	A[3][0] = 0.0f;
		A[0][1] = yaxis.X;	A[1][1] = yaxis.Y;	A[2][1] = yaxis.Z;	A[3][1] = 0.0f;
		A[0][2] = zaxis.X;	A[1][2] = zaxis.Y;	A[2][2] = zaxis.Z;	A[3][2] = 0.0f;
		A[0][3] = -xaxis.DotProduct( eye );		A[1][3] = -yaxis.DotProduct( eye );		A[2][3] = -zaxis.DotProduct( eye );		A[3][3] = 1.0f;

		return *this;
	}
Example #11
0
bool Plane3::isPointOnPlane( const Vector3& pointToCheck ) const
{
	if( pointToCheck.DotProduct( normal ) == distanceFromOrigin )
	{
		return true;
	}

	return false;
}
Example #12
0
    bool Collider::Check(const OrientedBoundingBox2D &OBB2D, const Sphere &SP)
    {

        Vector3 pt = OBB2D.ClosestPoint(SP.position);

        Vector3 v = pt - SP.position;


        return v.DotProduct(v) <= SP.radious*SP.radious;
    }
Example #13
0
Vector3 CalculateLonePairDirection(Conformer& ligand, std::string LP_atom) {
  Atom* NE = ligand.Find("NE2");
  Atom* ND = ligand.Find("ND1");
  Atom* CG = ligand.Find("CG");
  Atom* CD = ligand.Find("CD2");
  Atom* CE = ligand.Find("CE1");
  if (NE == NULL || ND == NULL || CG == NULL || CD == NULL || CE == NULL)
    Log->error(FLERR, "Check the atom names in the ligand");

  Vector3 v;
  if (LP_atom == "NE2") {
    //define theta
    Vector3 r1(*CE, *NE);
    Vector3 r2(*CD, *NE);
    double theta = acos(r1.DotProduct(r2) / (r1.Length() * r2.Length()));

    //define gamma, gamma = 0.5 * theta
    Point middle;
    double a = 0.49969;
    middle.set_x(a * ND->x() + (1 - a) * CG->x());
    middle.set_y(a * ND->y() + (1 - a) * CG->y());
    middle.set_z(a * ND->z() + (1 - a) * CG->z());
    v = Vector3(middle, *NE);
    double gamma = acos(v.DotProduct(r2) / (v.Length() * r2.Length()));
  } else if (LP_atom == "ND1") {
    //define theta
    Vector3 r1(*CE, *ND);
    Vector3 r2(*CG, *ND);
    double theta = acos(r1.DotProduct(r2) / (r1.Length() * r2.Length()));

    //define gamma, gamma = 0.5 * theta
    Point middle;
    double a = 0.495;
    middle.set_x(a * NE->x() + (1 - a) * CD->x());
    middle.set_y(a * NE->y() + (1 - a) * CD->y());
    middle.set_z(a * NE->z() + (1 - a) * CD->z());
    v = Vector3(middle, *ND);
    double gamma = acos(v.DotProduct(r2) / (v.Length() * r2.Length()));
  }

  return v;
}
Example #14
0
void Quaternion::SetRotationArc(const Vector3& v0, const Vector3& v1, const Vector3 &norm)
{
	Vector3 vCross = v0.CrossProduct(v1);
	const float len = vCross.Length();
	if (len <= 0.01f)
	{
		// v0 - v1 벡터가 정확히 반대 방향이거나, 정확히 같은 방향을 가르킬때,
		// 두 벡터에 직교하는 벡터 norm 에서 180도 회전하거나, 회전하지 않거나
		// 결정한다.
		*this = Quaternion(norm, v0.DotProduct(v1) > 0 ? 0 : MATH_PI);
		return;
	}

	float fDot = v0.DotProduct(v1);
	float s = (float)sqrtf((1.0f + fDot) * 2.0f);

	x = vCross.x / s;
	y = vCross.y / s;
	z = vCross.z / s;
	w = s * 0.5f;
} //Quaternion::SetRotationArc
// ----------------------------------------------------------------------------
Vector3 Face::Intersect(const Vector3& origin, const Vector3& direction) const
{
#define NO_INTERSECTION Vector3(-1, -1, -1)
#define DO_CULL 0

    // Algorithm taken from:
    // "Fast, Minimum Storage Ray/Triangle Intersection"
    // See doc/research/
    Vector3 edge1 = vertex_[1]->position_ - vertex_[0]->position_;
    Vector3 edge2 = vertex_[2]->position_ - vertex_[0]->position_;

    Vector3 p = direction.CrossProduct(edge2);
    float determinant = p.DotProduct(edge1);
#if DO_CULL
    if(determinant == 0.0f)
        return NO_INTERSECTION;
#endif

    Vector3 ray = origin - vertex_[0]->position_;
    float u = p.DotProduct(ray);
#if DO_CULL
    if(u < 0.0f || u > determinant)
        return NO_INTERSECTION;
#endif

    Vector3 q = ray.CrossProduct(edge1);
    float v = q.DotProduct(direction);
#if DO_CULL
    if(v < 0.0f || v > determinant)
        return NO_INTERSECTION;
#endif

    determinant = 1.0f / determinant;
    u *= determinant;
    v *= determinant;

    return Vector3(1.0f - u - v, u, v);
}
Example #16
0
Colour RayTracer::CalculateSpecularLighting(Vector3 &surfacePoint, Vector3 &surfaceNormal, Vector3 &lightPosition, Vector3 &cameraPosition, Light &light, Material &material)
{
	Colour specular;

	Vector3 halfVector = Vector3::HalfVector(cameraPosition, surfacePoint, lightPosition);
	double angle = halfVector.DotProduct(surfaceNormal);
	double power = powf(angle, material.GetSpecPower());

	specular.red = light.GetLightColour().red * material.GetSpecularColour().red * power;
	specular.green = light.GetLightColour().green * material.GetSpecularColour().green * power;
	specular.blue = light.GetLightColour().blue * material.GetSpecularColour().blue * power;

	return specular;
}
Example #17
0
Colour RayTracer::CalculateDiffuseLighting(Vector3 &lightNormal, Vector3 &surfaceNormal, Light &light, Material &material)
{
	Colour diffuse;
	
	double angle = lightNormal.DotProduct(surfaceNormal);

	if (angle > 0.0)
	{
		diffuse.red = light.GetLightColour().red * material.GetDiffuseColour().red * angle;
		diffuse.green = light.GetLightColour().red * material.GetDiffuseColour().green * angle;
		diffuse.blue = light.GetLightColour().red * material.GetDiffuseColour().blue * angle;
	}

	return diffuse;
}
Example #18
0
VCNBool VCNRay::Intersects( const VCNSphere& sphere, VCNFloat& t ) const
{
  Vector3 w = sphere.GetCenter() - m_vcOrig;
  VCNFloat c = w.Length();
  VCNFloat v = w.DotProduct(m_vcDir);
  VCNFloat d = (sphere.GetRadius() * sphere.GetRadius()) - (c*c - v*v);

  t = -1.0f;

  // If there was no intersection, return -1
  if (d < 0.0f)
    return false;

  // Return the distance to the [first] intersecting point
  t = v - sqrt(d);
  return true;
}
Example #19
0
	//! test a sphere against the frustum
	Frustum::E_TestResult Frustum::Test(const Vector3& vCenter, f32 fRadius) const
	{
		for(u32 i=0; i<P_Count; ++i)
		{
			f32 fDist = vCenter.DotProduct(m_Planes[i].Normal) - m_Planes[i].D;
			if(fDist > fRadius)
			{
				return TR_Out;
			}

			if(Math::FAbs(fDist) < fRadius)
			{
				return TR_Intersect;
			}
		}

		return TR_In;
	}
Example #20
0
//! returns the closest point on a line segment [A B]
Vector3 Math::GetClosestPointOnLine(const Vector3& vPoint, const Vector3& vA, const Vector3& vB)
{
    Vector3 vC = vPoint-vA;
    Vector3 vD = vB-vA;
    float fLength = vD.GetLength();

    vD = vD / fLength;
    float t = vD.DotProduct(vC);

    if(t < 0.0f)
    {
        return vA;
    }
    else if(t > fLength)
    {
        return vB;
    }

    return vA + vD*t;
}
Example #21
0
//--------------------------------
//
//--------------------------------
void Quaternion::SetRotationArc( const Vector3& v0, const Vector3& v1 )
{
    Vector3 vCross = v0.CrossProduct( v1 );

    float fDot = v0.DotProduct( v1 );
    float s = (float)sqrt( ( 1.0F + fDot ) * 2.0F );
    if( 0.1f >  s )
    {
        x = 0;
        y = 1;
        z = 0;
        w = 0;
        return;
    }

    x = vCross.x / s;
    y = vCross.y / s;
    z = vCross.z / s;
    w = s * 0.5F;
} //Quaternion::SetRotationArc
Example #22
0
// 광선 orig, dir 에 충돌된 면이 있다면 true 를 리턴하고, 충돌 위치를 out에 
// 저장해서 리턴한다.
bool cGrid2::Pick( const Vector3 &orig, const Vector3 &dir, Vector3 &out )
{
	bool isFirst = true;
	sVertexNormTex *vertices = (sVertexNormTex*)m_vtxBuff.Lock();
	WORD *indices = (WORD*)m_idxBuff.Lock();
	RETV(!vertices || !indices, false);

	for (int i=0; i < m_idxBuff.GetFaceCount()*3; i+=3)
	{
		const Vector3 &p1 = vertices[ indices[ i]].p;
		const Vector3 &p2 = vertices[ indices[ i+1]].p;
		const Vector3 &p3 = vertices[ indices[ i+2]].p;

		const Triangle tri(p1, p2, p3);
		const Plane p(p1, p2, p3);

		const float dot = dir.DotProduct( p.N );
		if (dot >= 0)
			continue;

		float t;
		if (tri.Intersect(orig, dir, &t))
		{
			if (isFirst)
			{
				isFirst = false;
				out = orig + dir * t;
			}
			else
			{
				const Vector3 v = orig + dir * t;
				if (orig.LengthRoughly(v) < orig.LengthRoughly(out))
					out = v;
			}
		}
	}
	m_vtxBuff.Unlock();
	m_idxBuff.Unlock();

	return !isFirst;
}
Example #23
0
void CollisionShape2D::OnMarkedDirty(Node* node)
{
    Vector3 newWorldScale = node_->GetWorldScale();

    Vector3 delta = newWorldScale - cachedWorldScale_;
    if (delta.DotProduct(delta) < 0.01f)
        return;

    // Physics operations are not safe from worker threads
    Scene* scene = GetScene();
    if (scene && scene->IsThreadedUpdate())
    {
        scene->DelayedMarkedDirty(this);
        return;
    }
    
    cachedWorldScale_ = newWorldScale;

    if (fixture_)
        ApplyNodeWorldScale();
}
Example #24
0
//--------------------------------
//
//--------------------------------
void Quaternion::SetRotationArc( const Vector3& v0, const Vector3& v1 )
{
	Vector3 vCross = v0.CrossProduct(v1);
	const float len = vCross.Length();
	if (len <= 0.01f)
	{
		x = 0; y = 0; z = 0; w = 1;
		return;
	}

	float fDot = v0.DotProduct( v1 );
	float s = (float)sqrtf((1.0f + fDot) * 2.0f);
	//if (0.1f >  s)
	//{
	//	x = 0; y = 1; z = 0; w = 0;
	//	return;
	//}

	x = vCross.x / s;
	y = vCross.y / s;
	z = vCross.z / s;
	w = s * 0.5f;
} //Quaternion::SetRotationArc
Example #25
0
//THIS NEEDS TESTING MAJORLY
void Sphere::ResolveCollision(Sphere& rhs, const float& time){
	
	//Calculate the depth of the penetration
	float penDepth = this->radius + rhs.radius - this->position.GetDistance(rhs.position);

	//Calculate the contact normal
	Vector3 conNormal = (this->position - rhs.position).GetNormalised();

	//Calculate the point of contact
	Vector3 conPoint = this->position - conNormal * (this->radius - penDepth);

	//Calculate the rough combined elasticity of the two spheres in
	//the collision. An application of the smoke and mirrors technique!
	float elasticity = (this->elasticity + rhs.elasticity) * 0.5f;
	
	//Calculate the velocities of both spheres
	Vector3 va = this->getVelocity(time);
	Vector3 vb = rhs.getVelocity(time);

	//Calculate the Vn of the collision
	float veloNormal = (va - vb).DotProduct(conNormal);

	//Calculate the impulse of the collision
	float impulse = ( -(1 + elasticity) * veloNormal ) / conNormal.DotProduct(conNormal * ( (1 / this->mass) + (1 / rhs.mass) ));
	
	//Calculate the resultant velocties of the collision
	Vector3 vaAfter = va + ((impulse/this->mass) * conNormal);
	Vector3 vbAfter = vb - ((impulse/rhs.mass) * conNormal);

	//Translate the shapes out of contact with each other
	this->translate(conNormal * (penDepth*0.5f));
	rhs.translate(0.0f - (conNormal * (penDepth*0.5f)));

	//Apply the calculated velocties to them
	this->setVelocity(vaAfter, time);
	rhs.setVelocity(vbAfter, time);
}
	//! 3D sphere vs ray intersection check
	bool CollisionUtils::SphereIntersectsWithRay(const Vector3& vCenter, f32 fRadius, const Vector3& vRayStart, const Vector3& vRayDir, f32* fRayLength /*= 0*/, f32* fDistToIntersection /*= 0*/)
	{
		Vector3 vToSphere = vCenter-vRayStart;
		f32 fDist = vToSphere.GetLength();
		f32 fV = vToSphere.DotProduct(vRayDir);
		f32 fD = fRadius*fRadius - (fDist*fDist - fV*fV);
		f32 _fDistToIntersection = fV - Math::SquareRoot(fD);

		if(fD < 0.0f || _fDistToIntersection < 0.0f)
		{
			return false;
		}
		
		if(fRayLength && (*fRayLength < _fDistToIntersection))
		{
			return false;
		}

		if(fDistToIntersection)
		{
			*fDistToIntersection = _fDistToIntersection;
		}
		return true;
	}
Example #27
0
/**
*  @brief
*    Called when the scene node needs to be updated
*/
void PGLeaf::OnUpdate()
{
	// If this scene node wasn't drawn at the last frame, we can skip some update stuff
	if ((GetFlags() & ForceUpdate) || m_bUpdate) {
		m_bUpdate = false;

		// If there are free particles, create new particles
		Particle *pParticle = AddParticle();
		while (pParticle) {
			InitParticle(*pParticle);

			// Next particle, please
			pParticle = AddParticle();
		}

		{ // Update particles
			float fTimeDiff = Timing::GetInstance()->GetTimeDifference();
			Iterator<Particle> cIterator = GetParticleIterator();
			while (cIterator.HasNext()) {
				Particle &cParticle = cIterator.Next();

				// Update forces
				// One: gravity
				cParticle.vVelocity[1] -= fTimeDiff*(cParticle.vPos[1]-FloorHeight)/5;

				// Two wind (dot wind vector normal)
				Vector3 vRot;
				EulerAngles::FromQuaternion(*cParticle.pRot, vRot.x, vRot.y, vRot.z);
				vRot.x *= static_cast<float>(Math::RadToDeg);
				vRot.y *= static_cast<float>(Math::RadToDeg);
				vRot.z *= static_cast<float>(Math::RadToDeg);
				cParticle.vVelocity += Wind.Get()*fTimeDiff*Math::Abs(vRot.DotProduct(Wind.Get()));

				// Four collision (just check whether leaf would end up on wrong side)
				if (cParticle.vPos.y + cParticle.vVelocity.y*fTimeDiff < FloorHeight) {
					// Random bouncy and some friction
					cParticle.vVelocity.y *= -1.0;
					cParticle.vVelocity.z *= Math::GetRandNegFloat();
					cParticle.vVelocity.x *= Math::GetRandNegFloat();
					cParticle.nCustom1     = ((static_cast<int>(Math::GetRandNegFloat()*255.0f*8.0f))<<8) | (cParticle.nCustom1&0xff);
				}

				// Five check whether particle has left area and can die... if it is outside, let it die
				float  fDistx		 = GetTransform().GetPosition().x - cParticle.vPos.x;
				float  fDisty		 = GetTransform().GetPosition().z - cParticle.vPos.z;
				float  fDistToCenter = fDistx*fDistx + fDisty*fDisty;
				uint32 nStart		 = cParticle.nCustom1 & 0xff;
				if (nStart < 0xff) { // It is being spawned
					nStart += static_cast<uint32>(fTimeDiff*512.0f + 0.5f);
					if (nStart > 0xff)
						nStart = 0xff; // Clamp
					cParticle.nCustom1 = (cParticle.nCustom1&0xffffff00)|nStart; // Write to lower 8 bits
				}

				if (fDistToCenter > Radius*Radius) {
					// Start dying... set alpha according to how far it is away
					fDistToCenter = 255 - (Math::Sqrt(fDistToCenter) - Radius)*3.0f;
					cParticle.fSize = static_cast<float>(static_cast<int>(fDistToCenter*(cParticle.nCustom1 & 0xff))>>8)/255*cParticle.fCustom1;
					if (cParticle.fSize < 0.2f)
						InitParticle(cParticle);
				} else {
					cParticle.fSize = static_cast<float>(cParticle.nCustom1 &0xff)/255*cParticle.fCustom1;
				}

				// Update position
				cParticle.vPos += cParticle.vVelocity*fTimeDiff*cParticle.fSize/2;

				// Update spin
				Vector3 vAxis = cParticle.vVelocity;
				vAxis.SetLength(1);

				// Transform normal and distortion
				vAxis *= ((static_cast<float>(cParticle.nCustom1>>8))/255.0f)*fTimeDiff/10;
				Quaternion qRotInc;
				EulerAngles::ToQuaternion(static_cast<float>(vAxis.x*Math::DegToRad), static_cast<float>(vAxis.y*Math::DegToRad), static_cast<float>(vAxis.z*Math::DegToRad), qRotInc);
				*cParticle.pRot *= qRotInc;

				Vector3 d = cParticle.vDistortion;
				d.SetLength(cParticle.fSize);
				cParticle.vDistortion = (*cParticle.pRot)*d;

				// Update color
				EulerAngles::FromQuaternion(*cParticle.pRot, vRot.x, vRot.y, vRot.z);
				vRot.x *= static_cast<float>(Math::RadToDeg);
				vRot.y *= static_cast<float>(Math::RadToDeg);
				vRot.z *= static_cast<float>(Math::RadToDeg);
				vAxis = vRot.Normalize();
				fDistx  = vAxis.x+vAxis.y*2+vAxis.z*3;
				if (fDistx > 1.0f)
					fDistx = 1.0f;
				if (fDistx < 0.5f)
					fDistx = 0.5f;
				cParticle.vColor[0] = cParticle.vFixPos.x*fDistx;
				cParticle.vColor[1] = cParticle.vFixPos.y*fDistx;
				cParticle.vColor[2] = cParticle.vFixPos.z*fDistx;
			}
Example #28
0
void Terrain::CreatePatchGeometry(TerrainPatch* patch)
{
    URHO3D_PROFILE(CreatePatchGeometry);

    unsigned row = (unsigned)(patchSize_ + 1);
    VertexBuffer* vertexBuffer = patch->GetVertexBuffer();
    Geometry* geometry = patch->GetGeometry();
    Geometry* maxLodGeometry = patch->GetMaxLodGeometry();
    Geometry* occlusionGeometry = patch->GetOcclusionGeometry();

    if (vertexBuffer->GetVertexCount() != row * row)
        vertexBuffer->SetSize(row * row, MASK_POSITION | MASK_NORMAL | MASK_TEXCOORD1 | MASK_TANGENT);

    SharedArrayPtr<unsigned char> cpuVertexData(new unsigned char[row * row * sizeof(Vector3)]);
    SharedArrayPtr<unsigned char> occlusionCpuVertexData(new unsigned char[row * row * sizeof(Vector3)]);

    float* vertexData = (float*)vertexBuffer->Lock(0, vertexBuffer->GetVertexCount());
    float* positionData = (float*)cpuVertexData.Get();
    float* occlusionData = (float*)occlusionCpuVertexData.Get();
    BoundingBox box;

    unsigned occlusionLevel = occlusionLodLevel_;
    if (occlusionLevel > numLodLevels_ - 1)
        occlusionLevel = numLodLevels_ - 1;

    if (vertexData)
    {
        const IntVector2& coords = patch->GetCoordinates();
        int lodExpand = (1 << (occlusionLevel)) - 1;
        int halfLodExpand = (1 << (occlusionLevel)) / 2;
        
        for (int z = 0; z <= patchSize_; ++z)
        {
            for (int x = 0; x <= patchSize_; ++x)
            {
                int xPos = coords.x_ * patchSize_ + x;
                int zPos = coords.y_ * patchSize_ + z;

                // Position
                Vector3 position((float)x * spacing_.x_, GetRawHeight(xPos, zPos), (float)z * spacing_.z_);
                *vertexData++ = position.x_;
                *vertexData++ = position.y_;
                *vertexData++ = position.z_;
                *positionData++ = position.x_;
                *positionData++ = position.y_;
                *positionData++ = position.z_;

                box.Merge(position);
                
                // For vertices that are part of the occlusion LOD, calculate the minimum height in the neighborhood
                // to prevent false positive occlusion due to inaccuracy between occlusion LOD & visible LOD
                float minHeight = position.y_;
                if (halfLodExpand > 0 && (x & lodExpand) == 0 && (z & lodExpand) == 0)
                {
                    int minX = Max(xPos - halfLodExpand, 0);
                    int maxX = Min(xPos + halfLodExpand, numVertices_.x_ - 1);
                    int minZ = Max(zPos - halfLodExpand, 0);
                    int maxZ = Min(zPos + halfLodExpand, numVertices_.y_ - 1);
                    for (int nZ = minZ; nZ <= maxZ; ++nZ)
                    {
                        for (int nX = minX; nX <= maxX; ++nX)
                            minHeight = Min(minHeight, GetRawHeight(nX, nZ));
                    }
                }
                *occlusionData++ = position.x_;
                *occlusionData++ = minHeight;
                *occlusionData++ = position.z_;

                // Normal
                Vector3 normal = GetRawNormal(xPos, zPos);
                *vertexData++ = normal.x_;
                *vertexData++ = normal.y_;
                *vertexData++ = normal.z_;

                // Texture coordinate
                Vector2 texCoord((float)xPos / (float)numVertices_.x_, 1.0f - (float)zPos / (float)numVertices_.y_);
                *vertexData++ = texCoord.x_;
                *vertexData++ = texCoord.y_;

                // Tangent
                Vector3 xyz = (Vector3::RIGHT - normal * normal.DotProduct(Vector3::RIGHT)).Normalized();
                *vertexData++ = xyz.x_;
                *vertexData++ = xyz.y_;
                *vertexData++ = xyz.z_;
                *vertexData++ = 1.0f;
            }
        }

        vertexBuffer->Unlock();
        vertexBuffer->ClearDataLost();
    }

    patch->SetBoundingBox(box);

    if (drawRanges_.Size())
    {
        unsigned occlusionDrawRange = occlusionLevel << 4;

        geometry->SetIndexBuffer(indexBuffer_);
        geometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false);
        geometry->SetRawVertexData(cpuVertexData, MASK_POSITION);
        maxLodGeometry->SetIndexBuffer(indexBuffer_);
        maxLodGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[0].first_, drawRanges_[0].second_, false);
        maxLodGeometry->SetRawVertexData(cpuVertexData, MASK_POSITION);
        occlusionGeometry->SetIndexBuffer(indexBuffer_);
        occlusionGeometry->SetDrawRange(TRIANGLE_LIST, drawRanges_[occlusionDrawRange].first_, drawRanges_[occlusionDrawRange].second_, false);
        occlusionGeometry->SetRawVertexData(occlusionCpuVertexData, MASK_POSITION);
    }

    patch->ResetLod();
}
Example #29
0
void DecalSet::GetFace(Vector<PODVector<DecalVertex> >& faces, Drawable* target, unsigned batchIndex, unsigned i0, unsigned i1,
    unsigned i2, const unsigned char* positionData, const unsigned char* normalData, const unsigned char* skinningData,
    unsigned positionStride, unsigned normalStride, unsigned skinningStride, const Frustum& frustum, const Vector3& decalNormal,
    float normalCutoff)
{
    bool hasNormals = normalData != 0;
    bool hasSkinning = skinned_ && skinningData != 0;

    const Vector3& v0 = *((const Vector3*)(&positionData[i0 * positionStride]));
    const Vector3& v1 = *((const Vector3*)(&positionData[i1 * positionStride]));
    const Vector3& v2 = *((const Vector3*)(&positionData[i2 * positionStride]));

    // Calculate unsmoothed face normals if no normal data
    Vector3 faceNormal = Vector3::ZERO;
    if (!hasNormals)
    {
        Vector3 dist1 = v1 - v0;
        Vector3 dist2 = v2 - v0;
        faceNormal = (dist1.CrossProduct(dist2)).Normalized();
    }

    const Vector3& n0 = hasNormals ? *((const Vector3*)(&normalData[i0 * normalStride])) : faceNormal;
    const Vector3& n1 = hasNormals ? *((const Vector3*)(&normalData[i1 * normalStride])) : faceNormal;
    const Vector3& n2 = hasNormals ? *((const Vector3*)(&normalData[i2 * normalStride])) : faceNormal;

    const unsigned char* s0 = hasSkinning ? &skinningData[i0 * skinningStride] : (const unsigned char*)0;
    const unsigned char* s1 = hasSkinning ? &skinningData[i1 * skinningStride] : (const unsigned char*)0;
    const unsigned char* s2 = hasSkinning ? &skinningData[i2 * skinningStride] : (const unsigned char*)0;

    // Check if face is too much away from the decal normal
    if (decalNormal.DotProduct((n0 + n1 + n2) / 3.0f) < normalCutoff)
        return;

    // Check if face is culled completely by any of the planes
    for (unsigned i = PLANE_FAR; i < NUM_FRUSTUM_PLANES; --i)
    {
        const Plane& plane = frustum.planes_[i];
        if (plane.Distance(v0) < 0.0f && plane.Distance(v1) < 0.0f && plane.Distance(v2) < 0.0f)
            return;
    }

    faces.Resize(faces.Size() + 1);
    PODVector<DecalVertex>& face = faces.Back();
    if (!hasSkinning)
    {
        face.Reserve(3);
        face.Push(DecalVertex(v0, n0));
        face.Push(DecalVertex(v1, n1));
        face.Push(DecalVertex(v2, n2));
    }
    else
    {
        const float* bw0 = (const float*)s0;
        const float* bw1 = (const float*)s1;
        const float* bw2 = (const float*)s2;
        const unsigned char* bi0 = s0 + sizeof(float) * 4;
        const unsigned char* bi1 = s1 + sizeof(float) * 4;
        const unsigned char* bi2 = s2 + sizeof(float) * 4;
        unsigned char nbi0[4];
        unsigned char nbi1[4];
        unsigned char nbi2[4];

        // Make sure all bones are found and that there is room in the skinning matrices
        if (!GetBones(target, batchIndex, bw0, bi0, nbi0) || !GetBones(target, batchIndex, bw1, bi1, nbi1) ||
            !GetBones(target, batchIndex, bw2, bi2, nbi2))
            return;

        face.Reserve(3);
        face.Push(DecalVertex(v0, n0, bw0, nbi0));
        face.Push(DecalVertex(v1, n1, bw1, nbi1));
        face.Push(DecalVertex(v2, n2, bw2, nbi2));
    }
}
Example #30
0
 double DotProduct( Vector3 const& i_lhs, Vector3 const& i_rhs )
 {
     return i_lhs.DotProduct( i_rhs );
 }