मेरे पास एक समान रे ट्रेसर (पायथन में लिखा गया है) है और एक ही समस्या पर ठोकर खाई है: भौतिकी को सही तरीके से काम करने के लिए एक को चौराहे सीमा के प्रत्येक तरफ अपवर्तक सूचकांक को अवश्य जानना चाहिए। इस सुंदर ढंग से हल करने के लिए काफी समय लगा, लेकिन अंत में मैं इस समाधान/डिजाइन के साथ चला गया:
डिजाइन
1) दृश्य - मैं एक मास्टर दृश्य वस्तु है (मूल रूप से एक सभी वस्तुओं की सरणी दृश्य में), आप शायद कुछ समान होगा। यह ज्यामितीय वस्तुओं को स्टोर करता है।
तरीके:
intersection_points(ray)
- सभी चौराहे अंक, रे से दूरी के अनुसार क्रमबद्ध की एक सूची देता है।
intersection_objects(ray)
- किरण से दूरी से क्रमबद्ध सभी चौराहे वस्तुओं की एक सूची देता है।
containing_object(ray)
- उस वस्तु को लौटाता है जिसमें किरण है।
objects()
- मनमानी क्रम में सभी वस्तुओं की एक सूची देता है।
नोट: Scene_Boundary: दृश्य सूची के लिए एक अतिरिक्त वस्तु कहते हैं। यह एक विशाल बॉक्स (या क्षेत्र) है जो पूरे दृश्य को घेरता है यानी इस सीमा के अंदर सबकुछ है।
2) ऑब्जेक्ट्स - ज्यामितीय वस्तुओं (जैसे आपका क्षेत्र) इन विधियों को लागू करें।
तरीके:
contains(ray)
- यह सच है देता है रे सतह पर है - यह सच है देता है रे मूल, ऑब्जेक्ट के अंदर है झूठी अगर सतह पर और झूठी अगर बाहर
ray_is_on_surface(ray)
है केवल, अन्यथा झूठा।
intersection_points(ray)
- रिटर्न प्रतिच्छेदन बिंदु (रों) कि रे वस्तु
surface_normal(ray)
के साथ बनाता है - सतह सतह है जो रे मारा के सामान्य वेक्टर
(इस Fresnel प्रतिबिंब और अपवर्तन के साथ में मदद मिलेगी) रिटर्न
ऑप्टिकल गणना के लिए वस्तुओं में एक अपवर्तक सूचकांक भी होना चाहिए।
उदाहरण चर: अपवर्तनांक अंदर की (n1) और बाहर (एन 2) क्या है:
सीमा समस्या
समस्या
हम हल करना चाहते सीमा? ऐसा करने के लिए हम इस प्रक्रिया का पालन:
1) पूरे दृश्य के माध्यम से रे ट्रेस:
sphere # origin = (0,0,0), radius = 1
ray # origin = (0,0,0), direction = (0,0,1) Note: the ray is inside the sphere
scene.add_object(sphere)
ipoints = scene.intersection_points(ray) # [ (0,0,1), (0,0,10) ]
iobjects = scene.intersection_objects(ray) # [ Sphere, Scene_Boundary]
याद रखें इन रे मूल से दूरी के अनुसार क्रमबद्ध कर रहे हैं। आईपॉइंट्स और आईबोजेक्ट्स में आखिरी वस्तु दृश्य सीमा के साथ किरण को छेड़छाड़ करती है। हम बाद में इसका इस्तेमाल करेंगे!
2) n1 युक्त वस्तु, उदा .:
obj1 = scene.containing_object(ray) # Scene_Boundary
n1 = obj1.refractive_index() # n1 = 1. Scene_Boundary always has refractive index of Air
3) n2 iobject सूची में आगे एक वस्तु देखकर पाया जाता है, उदा का पता लगाकर बस पाया जाता है स्यूडोकोड में:
normal = obj1.surface_normal(ray)
आप सभी जानकारी आप सही प्रतिबिंब और अपवर्तन की गणना करने की जरूरत है:
index = iobjects.index_of_object(obj1)
obj2 = iobjects[index+1]
n2 = obj2.refractive_index() # n2 = 1.5 e.g. Glass
4) सतह बाद में उपयोग के लिए सामान्य है। यह सामान्य रूप से काम करने के लिए पर्याप्त है, भले ही किरण वस्तु के बाहर है, लेकिन कभी-कभी मुझे एल्गोरिदम को और अधिक मजबूत बनाने के लिए कुछ लॉजिकल फ़िल्टरिंग को लागू करने की आवश्यकता होती है, लेकिन यह मूल रूप से यह है!
परावर्तन और अपवर्तन
तुम सिर्फ सतह सामान्य जानने से एक सदिश को प्रतिबिंबित कर सकते हैं। अजगर numpy का उपयोग करने में मैं इसे इस तरह करते हैं,
def reflect_vector(normal, vector):
d = numpy.dot(normal, vector)
return vector - 2 * d * normal
अपवर्तन (के रूप में चर्चा) की जरूरत है N1 और N2 मान:
def fresnel_refraction(normal, vector, n1, n2):
n = n1/n2
dot = np.dot(norm(vector), norm(normal))
c = np.sqrt(1 - n**2 * (1 - dot**2))
sign = 1
if dot < 0.0:
sign = -1
refraction = n * vector + sign*(c - sign*n*dot) * normal
return norm(refraction)
अंत में आप रे के लिए प्रतिबिंब गुणांक की गणना करने की आवश्यकता होगी जहां कोण रे दिशा और सतह सामान्य के बीच कोण है (यह माना जाता है कि आपकी किरण 'unpolarised' है)। प्रतिबिंब होने पर यह तय करने के लिए 0 और 1 के बीच एक यादृच्छिक संख्या के साथ तुलना करें।
def fresnel_reflection(angle, n1, n2):
assert 0.0 <= angle <= 0.5*np.pi, "The incident angle must be between 0 and 90 degrees to calculate Fresnel reflection."
# Catch TIR case
if n2 < n1:
if angle > np.arcsin(n2/n1):
return 1.0
Rs1 = n1 * np.cos(angle) - n2 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2)
Rs2 = n1 * np.cos(angle) + n2 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2)
Rs = (Rs1/Rs2)**2
Rp1 = n1 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2) - n2 * np.cos(angle)
Rp2 = n1 * np.sqrt(1 - (n1/n2 * np.sin(angle))**2) + n2 * np.cos(angle)
Rp = (Rp1/Rp2)**2
return 0.5 * (Rs + Rp)
अंतिम टिप्पणी
यह सब मेरी अजगर ऑप्टिकल रे अनुरेखण परियोजना जो अभी तक जारी नहीं किया गया है से आता है, लेकिन आप यहां कुछ विस्तार के लिए जाँच कर सकते हैं (!): http://daniel.farrell.name/freebies/pvtrace। मुझे पायथन पसंद है! यहां सूचीबद्ध कई पायथन रे ट्रेसिंग परियोजनाएं हैं, http://groups.google.com/group/python-ray-tracing-community/web/list-of-python-statistical-ray-tracers। अंत में, अपने उदाहरण में आंशिक अपवर्तक सूचकांक से सावधान रहें, समीकरण टूट जाएगा।
अद्यतन
यह मेरा रे ट्रेसर में लागू करने का स्क्रीनशॉट, http://github.com/danieljfarrell/pvtrace
बस एक नोट पर उपलब्ध, कि अपवर्तक होना चाहिए अधिक से अधिक> = 1, मेरा उत्तर में समीकरण के लिए नीचे होने वैध। यही है, जब तक कि आप रे ट्रेसिंग मेटा-सामग्री में दिलचस्पी नहीं रखते हैं :) –