DECLARE SUB normalize (v AS ANY) DECLARE FUNCTION dot! (v AS ANY, w AS ANY) TYPE vec x AS SINGLE y AS SINGLE z AS SINGLE END TYPE DIM N AS vec DIM I AS vec DIM r AS vec '-------------------------------------------------------------------- ' REFRACT.BAS - refraction demo by Toshi July 24, 2001 ' This demonstrates a 12 multiplication method of calculating ' the refracted ray from a normalized normal and incident ray. ' ' The equations used here are general enough to do 3D refraction ' but the demo is in 2D so it is easier to see that the results ' are physically accurate. ' ' Actually for 2D, refraction can be calculated using a single ' table look up and no multiplications, given that small precision ' errors are acceptable. '------------------------------------------------------------------- SCREEN 13 COLOR 14: PRINT "12 mul Refraction demo" COLOR 15: PRINT "Toshi Horie 07/24/2001" ki = 1 'refraction coeff vacuum refract = 1.3 'precalcs rr = 1 / refract r2 = rr * rr invr = 1 / rr invr2 = 1 / r2 N.x = 0 N.y = 1 N.z = 0 DO 'main loop FOR angle = -1.8 TO 3.14 STEP .04 I.x = COS(angle) I.y = SIN(angle) I.z = 0 'CALL normalize(I) 'needed if I is not a unit vector oldix% = 160 + I.x * 30 oldiy% = 100 - I.y * 30 LINE (160, 100)-(oldix%, oldiy%), 15 'draw incident ray LINE (120, 100)-(220, 100), 4 'draw interface plane ndoti = dot(N, I) IF ndoti >= 0 THEN 'entering vacuum from object b = rr b2 = r2 ELSE 'entering object from vacuum b = invr b2 = invr2 END IF ndoti2 = ndoti * ndoti D2 = 1 + b2 * (ndoti2 - 1) IF D2 >= 0 THEN D = SQR(D2) IF ndoti > 0 THEN a = -b * ndoti + D ELSE a = -b * ndoti - D END IF r.x = a * N.x + b * I.x r.y = a * N.y + b * I.y r.z = a * N.z + b * I.z oldrx% = 160 - r.x * 50 oldry% = 100 + r.y * 50 LINE (160, 100)-(oldrx%, oldry%), 14 WAIT &H3DA, 8, 8 'reduce flicker IF INKEY$ <> "" THEN END WAIT &H3DA, 8 ' WAIT &H3DA, 8, 8 'slow it down more so the user can see WAIT &H3DA, 8 'what's going on. LINE (160, 100)-(oldrx%, oldry%), 0 ELSE LOCATE 5, 1: PRINT "total internal refraction" LOCATE 5, 1: PRINT SPACE$(30) END IF LINE (160, 100)-(oldix%, oldiy%), 0 NEXT angle LOOP FUNCTION dot (v AS vec, w AS vec) dot = v.x * w.x + v.y * w.y + v.z * w.z END FUNCTION SUB normalize (v AS vec) mag = SQR(v.x * v.x + v.y * v.y + v.z * v.z) 'should make this beep in debug mode IF mag = 0 THEN v.x = 0 v.y = 0 v.z = 0 EXIT SUB END IF v.x = v.x / mag v.y = v.y / mag v.z = v.z / mag END SUB