Я пытаюсь реализовать пересечение лучей с эллипсоидами путем "сжатия" пространства и создания лучей и сфер:
создание mat3 S с радиусом эллипсоида по диагонали
слабый луч путем умножения начала и направления на обратное значение S
пересекающийся луч со сферой радиуса 1.0 в локальном пространстве
умножить HitPoint на S, чтобы расшатать его.
Вот луч против сферы:
float P = glm::dot(dir, sphereCenter-start);
float L = glm::distance(start, sphereCenter);
float d = sqrt(L*L - P*P);
if (d < radius) {
float x0 = sqrt(1.f - d*d);
hitPoint = start + dir*(P - x0);
hitNormal = glm::normalize(hitPoint - sphereCenter);
}
else if (d == radius) {
hitPoint = start + dir*P;
hitNormal = glm::normalize(hitPoint - sphereCenter);
}
else {
return false;
}
if (glm::distance(start, hitPoint) > dist) return false;
return true;
Вот хлюпающая часть:
glm::vec3 S = start;
glm::vec3 Dir = dir;
auto sphereCenter = thisEntity()->transform()->getPosition();
auto scale = thisEntity()->transform()->getScale();
glm::mat3 q = glm::mat3(0);
float x = _radius.x * scale.x;
float y = _radius.y * scale.y;
float z = _radius.z * scale.z;
q[0][0] = x;
q[1][1] = y;
q[2][2] = z;
glm::mat3 qI = glm::inverse(q);
S = qI * S;
Dir = qI * Dir;
//calculate hit point in world space squished
glm::vec3 hitPoint, hitNormal;
if (!IntersectionsMath::instance()->segmentVsSphere(sphereCenter, S, Dir, dist, 1.f, hitPoint, hitNormal)) return;
hitPoint = q * hitPoint;
hit.pushHit(hitPoint, hitNormal, this);
Текущий код сферы лучей предназначен для положения в мире, я пытаюсь заставить его работать в начале координат, поэтому это не должно иметь значения. Луч против обычной сферы работает нормально, проблема в эллипсоиде.
Я потратил много времени на это, и что-то где-то не так.