simple 3d question

Started by
6 comments, last by alvaro 9 years, 6 months ago

1. The problem statement, all variables and given/known data

A man is standing in his home , his position , his facing direction and the position of the sweet dish are given ,if he faces the sweet dish , he eats it .
Translating it into CS programming question : write a function ->
bool IsManInFrontofDish( vector3& manPosition, vector3& manFacingPos, vector3& dishPos )
which return true when the man faces the dish;

The programming part is easy , I was worried about the physics part .
Is the manPosition really important in this , or is it just to deceive?
I am attempting a physics programming question for the first time...
2. Relevant equations
A.B = ||A||.||B||

3. The attempt at a solution
the angle between 2 vectors is 0 if they are in the same direction so simply by replacing manFacingPos with A and
dishPos with B and checking the equation i will be able to get the answer:
translating it into program if it helps :

bool IsManInFrontofDish( vector3& manPosition, vector3& manFacingPos, vector3& dishPos ) {
int magnitude1 = sqrt( dot(manFacingPos, manFacingPos) );
int magnitude2 = sqrt( dot(dishPos,dishPos) );
if(dot(manFacingPos, dishPos) == magnitude1*magnitude2) return true;
else return false;
}

?don't worry about the vector3 class it is already defined ...

Advertisement
The relevant vector is not `dishPos', but `dishPos - manPosition'. If you had a separate type for positions, the type system would prevent you from computing `dot(manFacingPos, dishPos)', which is a meaningless quantity.

Why are you using `Pos' sometimes and `Position' some other times? Why are you calling the facing direction `manFacingPos', when it is not a position at all?

Why are you using `int'? You probably meant to use floating-point numbers.

Comparing floating-point numbers for equality is asking for trouble. The more reasonable thing to do is return true if the angle is small or, equivalently, if the cosine is close to 1.

You should also avoid computing square roots if you can. In this case, you can square both sides of what you are computing, so your test now becomes "is the cosine squared larger than 0.98?".

Give it another try and post back.

have you tried doing a vector/dish collision detection?

Simply project a vector in the direction the man is facing and move the origin to the center of the players camera. Perform a collision test between the vector and the dish.

The method you are using could work, if you created a vector that went from the center of the dish to the area between the mans eyes, and you performed a dot product between the man look vector, and the dish look vector, but it assumes a spherical shaped object.

View my game dev blog here!

@Alvaro Did it as you said … is this correct,will it do the job... :


bool IsManInFrontofDish( vector3& manPos, vector3& manFacingDirection, vector3& dishPos ) {
double magnitude1 = sqrt( dot(manPos, manPos)  ) ; 
double magnitude2 =  sqrt( dot(dishPos,dishPos)  ) ;
double dotProduct =  dot(manPos,dishPos);
double cosValue = dotProduct/ (magnitude1*magnitude2)

if(cosValue > .9) return true
 return false;  
}

@Alvaro Did it as you said … is this correct,will it do the job... :


bool IsManInFrontofDish( vector3& manPos, vector3& manFacingDirection, vector3& dishPos ) {
double magnitude1 = sqrt( dot(manPos, manPos)  ) ; 
double magnitude2 =  sqrt( dot(dishPos,dishPos)  ) ;
double dotProduct =  dot(manPos,dishPos);
double cosValue = dotProduct/ (magnitude1*magnitude2)

if(cosValue > .9) return true
 return false;  
}

It looks like you didn't even use the manFacingDirection, or compute the direction from the dishPos to the manPos. Just find the direction of both objects, and don't forget to normalize, then perform a dot product, and check if it is close to -1.

View my game dev blog here!

these are the functions available to me :


vector3 operator-(const vector3 &v);
vector3 operator+(const vector3 &v0, const vector3 &v1);
vector3 operator-(const vector3 &v0, const vector3 &v1);
vector3 operator*(const vector3 &v0, const vector3 &v1);
vector3 operator*(const vector3 &v, float s);
vector3 operator*(float s, const vector3 &v);
vector3 operator/(const vector3 &v, float s);

float dot(const vector3 &v0, const vector3 &v1);
vector3 cross(const vector3 &v0, const vector3 &v1);
vector3 reflect(const vector3 &v, const vector3 &n);
float norm(const vector3 &v);
vector3 unit(const vector3 &v);

so it should be :


bool IsManInFrontofDish( vector3& manPos, vector3& manFacingDirection, vector3& dishPos ) {

vector3 v0(0,0,0);
vector3 veyes = manFacingDirection -v0;
vector3 vdiffPos = dishPos - manPos;
norm(veyes)
norm(vdiffPos)
double dotProduct =  dot(veyes,vdiffPos);
if( dotProduct <-0.9) return true;
else return  false;


That seems correct although you don't need the v0 vector.

manFacingDirection - v0 is going to produce the same value as whatever was in manFacingDirection to begin with.

This is what I would do:

struct Vector3 {
  double x, y, z;
  
  Vector3(double x, double y, double z) : x(x), y(y), z(z) {
  }
};

double dot(Vector3 v1, Vector3 v2) {
  return v1.x * v2.x + v1.y * v2.y + v1.z + v2.z;
}

double length_squared(Vector3 v) {
  return dot(v, v);
}

struct Point3 {
  double x, y, z;
  
  Point3(double x, double y, double z) : x(x), y(y), z(z) {
  }
};

Vector3 operator-(Point3 p1, Point3 p2) {
  return Vector3(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z);
}

bool is_man_in_front_of_dish(Point3 man_position, Vector3 man_facing_direction, Point3 dish_position) {
  Vector3 direction_to_dish = dish_position - man_position;
  double dot_product = dot(man_facing_direction, direction_to_dish);
  
  if (dot_product <= 0.0)
    return false;
  
  double ls1 = length_squared(man_facing_direction);
  double ls2 = length_squared(direction_to_dish);
  double cosine_squared = (dot_product * dot_product) / (ls1 * ls2);
  
  return cosine_squared > 0.98;
}

This topic is closed to new replies.

Advertisement