2013-06-01 3 views
0

Я пишу простой трамвайчик, и я ударил стену, пытаясь получить нормальный вектор для оси, выровненной по оси, с учетом точки пересечения.Пересечение луча-ящика нормальное

Я использую this intersection algorithm:

float tmin, tmax, tymin, tymax, tzmin, tzmax; 
if (ray.direction.x >= 0) { 
    tmin = (min.x - ray.origin.x)/ray.direction.x; 
    tmax = (max.x - ray.origin.x)/ray.direction.x; 
} 
else { 
    tmin = (max.x - ray.origin.x)/ray.direction.x; 
    tmax = (min.x - ray.origin.x)/ray.direction.x; 
} 
if (ray.direction.y >= 0) { 
    tymin = (min.y - ray.origin.y)/ray.direction.y; 
    tymax = (max.y - ray.origin.y)/ray.direction.y; 
} else { 
    tymin = (max.y - ray.origin.y)/ray.direction.y; 
    tymax = (min.y - ray.origin.y)/ray.direction.y; 
} 
if ((tmin > tymax) || (tymin > tmax)) { 
    return -1; 
} 
if (tymin > tmin) { 
    tmin = tymin; 
} 
if (tymax < tmax) { 
    tmax = tymax; 
} 
if (ray.direction.z >= 0) { 
    tzmin = (min.z - ray.origin.z)/ray.direction.z; 
    tzmax = (max.z - ray.origin.z)/ray.direction.z; 
} else { 
    tzmin = (max.z - ray.origin.z)/ray.direction.z; 
    tzmax = (min.z - ray.origin.z)/ray.direction.z; 
} 
if ((tmin > tzmax) || (tzmin > tmax)) { 
    return -1; 
} 
if (tzmin > tmin) { 
    tmin = tzmin; 
} 
if (tzmax < tmax) { 
    tmax = tzmax; 
} 
return tmin; 

Хотя я уверен, что я мог бы разложить поле в плоскости вместо того, чтобы рассматривать его как отдельный примитив, делая вычисления нормального тривиальным, я хотел бы сохранить этот оптимизированный код пересечения и как-то вычислить нормаль от точки пересечения.

ответ

2

Я нашел способ сделать это:

v3 Box::normalAt(const v3 &point) { 
    v3 normal; 
    v3 localPoint = point - center; 
    float min = std::numeric_limits<float>::max(); 
    float distance = std::abs(size.x - std::abs(localPoint.x)); 
    if (distance < min) { 
     min = distance; 
     normal.set(1, 0, 0); 
     normal *= SIGN(localPoint.x); 
    } 
    distance = std::abs(size.y - std::abs(localPoint.y)); 
    if (distance < min) { 
     min = distance; 
     normal.set(0, 1, 0); 
     normal *= SIGN(localPoint.y); 
    } 
    distance = std::abs(size.z - std::abs(localPoint.z)); 
    if (distance < min) { 
     min = distance; 
     normal.set(0, 0, 1); 
     normal *= SIGN(localPoint.z); 
    } 
    return normal; 
} 

Он производит неправильные результаты по краям коробки, но это приемлемо сейчас.

sample

Смежные вопросы