ईपीएसलॉन द्वारा बढ़ती चीजें वास्तव में ऐसा करने का एक शानदार तरीका नहीं है, क्योंकि अब आपके पास अपने बॉक्स के किनारे पर आकार ईपीएसलॉन की सीमा है जिसके माध्यम से किरणें गुजर सकती हैं। तो आप त्रुटियों के अजीब सेट (अपेक्षाकृत आम) से छुटकारा पायेंगे, और अजीब त्रुटियों के दूसरे (दुर्लभ) सेट के साथ समाप्त हो जाएंगे।
मुझे लगता है कि आप पहले से ही कल्पना कर रहे हैं कि आपकी किरण अपने वेक्टर के साथ कुछ गति से यात्रा कर रही है और प्रत्येक विमान के साथ छेड़छाड़ का समय पाती है। इसलिए, उदाहरण के लिए, यदि आप विमान को x=x0
पर घुमा रहे हैं, और आपकी किरण (rx,ry,rz)
(0,0,0)
से दिशा में जा रही है, तो चौराहे का समय t = x0/rx
है। यदि t
नकारात्मक है, तो इसे अनदेखा करें - आप दूसरी तरफ जा रहे हैं। यदि t
शून्य है, तो आपको यह तय करना होगा कि उस विशेष मामले को कैसे संभालना है - यदि आप पहले से ही विमान में हैं, तो क्या आप इसे उछालते हैं, या इसके माध्यम से गुजरते हैं? आप एक विशेष मामले के रूप में rx==0
को भी संभाल सकते हैं (ताकि आप बॉक्स के किनारे पर हिट कर सकें)।
वैसे भी, अब आपके पास उस समन्वय हैं जहां आपने उस विमान को मारा था: वे (t*rx , t*ry , t*rz)
हैं। अब आप पढ़ सकते हैं कि t*ry
और t*rz
आयताकार के भीतर हैं, जिसमें वे होना चाहिए (यानी उन अक्षों के साथ घन के लिए न्यूनतम और अधिकतम के बीच)। आप एक्स समन्वय का परीक्षण नहीं करते हैं क्योंकि आप पहले ही जानते हैं कि आपने इसे मारा है, फिर आपको यह तय करना होगा कि एक विशेष मामले के रूप में मारने वाले कोनों को कैसे संभालना है या नहीं। इसके अलावा, अब आप समय के साथ विभिन्न सतहों के साथ अपने टकराव का ऑर्डर कर सकते हैं और अपने टकराव बिंदु के रूप में पहले को चुन सकते हैं।
यह आपको मनमाने ढंग से ईपीएसलॉन-कारकों का उपयोग किए बिना गणना करने की अनुमति देता है, भले ही आपकी किरण फ़्लोटिंग पॉइंट अंकगणित के साथ सटीकता के लिए आपके घन को छेड़छाड़ करे। परीक्षण के लिए एक है कि क्या आप यह सोचते हैं आप x
मारा yz
भीतर मारा, और xz
और xy
यह सोचते हैं कि आप y
और z
क्रमशः हिट के लिए इसी लोगों:
तो तुम सिर्फ तीन कार्यों एक आप पहले से ही मिल गया है की तरह की जरूरत है।
संपादित करें:
#define X_FACE 0
#define Y_FACE 1
#define Z_FACE 2
#define MAX_FACE 4
// true if we hit a box face, false otherwise
bool hit_face(double uhit,double vhit,
double umin,double umax,double vmin,double vmax)
{
return (umin <= uhit && uhit <= umax && vmin <= vhit && vhit <= vmax);
}
// 0.0 if we missed, the time of impact otherwise
double hit_box(double rx,double ry, double rz,
double min_x,double min_y,double min_z,
double max_x,double max_y,double max_z)
{
double times[6];
bool hits[6];
int faces[6];
double t;
if (rx==0) { times[0] = times[1] = 0.0; }
else {
t = min_x/rx;
times[0] = t; faces[0] = X_FACE;
hits[0] = hit_box(t*ry , t*rz , min_y , max_y , min_z , max_z);
t = max_x/rx;
times[1] = t; faces[1] = X_FACE + MAX_FACE;
hits[1] = hit_box(t*ry , t*rz , min_y , max_y , min_z , max_z);
}
if (ry==0) { times[2] = times[3] = 0.0; }
else {
t = min_y/ry;
times[2] = t; faces[2] = Y_FACE;
hits[2] = hit_box(t*rx , t*rz , min_x , max_x , min_z , max_z);
t = max_y/ry;
times[3] = t; faces[3] = Y_FACE + MAX_FACE;
hits[3] = hit_box(t*rx , t*rz , min_x , max_x , min_z , max_z);
}
if (rz==0) { times[4] = times[5] = 0.0; }
else {
t = min_z/rz;
times[4] = t; faces[4] = Z_FACE;
hits[4] = hit_box(t*rx , t*ry , min_x , max_x , min_y , max_y);
t = max_z/rz;
times[5] = t; faces[5] = Z_FACE + MAX_FACE;
hits[5] = hit_box(t*rx , t*ry , min_x , max_x , min_y , max_y);
}
int first = 6;
t = 0.0;
for (int i=0 ; i<6 ; i++) {
if (times[i] > 0.0 && (times[i]<t || t==0.0)) {
first = i;
t = times[i];
}
}
if (first>5) return 0.0; // Found nothing
else return times[first]; // Probably want hits[first] and faces[first] also....
}
(मैं सिर्फ यह आपके द्वारा लिखा गया है, यह संकलन नहीं किया, इसलिए कीड़े से सावधान: कोड (verbosely) दिखाने के प्रत्येक अक्ष के लिए अलग तरह से परीक्षण करने के लिए कैसे करने के लिए जोड़ा।) (संपादित करें: सिर्फ एक i
को सही ->first
)
वैसे भी, मुद्दा यह है कि आप तीन दिशाओं अलग से करते हैं, और परीक्षण देखने के लिए प्रभाव में सही बॉक्स के भीतर हुई है या नहीं है (यू, वी)। निर्देशांक, जहां (यू, वी) या तो हैं (एक्स , वाई), (एक्स, जेड), या (वाई, जेड) आप जिस विमान पर हिट करते हैं उसके आधार पर।
ग्रेट आरेख। यह वास्तव में समस्या को स्पष्ट करने में मदद करता है। –