void normal_at(Interpreter interp, SphereItem s, Vector4Item p) { // ( -- object_point ) interp.StackPush(s); interp.Run("'transform' REC@ INVERSE"); interp.StackPush(p); interp.Run("*"); // ( object_point -- object_normal ) interp.Run("0 0 0 Point -"); // ( object_normal -- world_normal ) interp.StackPush(s); interp.Run("'transform' REC@ INVERSE TRANSPOSE SWAP * 0 'W' <REC! NORMALIZE"); }
ArrayItem intersections(Interpreter interp, SphereItem sphere, RayItem ray) { // Compute sphere_to_ray interp.StackPush(ray); interp.Run("'origin' REC@ 0 0 0 Point -"); Vector4Item sphere_to_ray = (Vector4Item)interp.StackPop(); // Compute a interp.StackPush(ray); interp.Run("'direction' REC@ DUP DOT"); DoubleItem a = (DoubleItem)interp.StackPop(); // Compute b interp.StackPush(sphere_to_ray); interp.StackPush(ray); interp.Run("'direction' REC@ DOT 2 *"); DoubleItem b = (DoubleItem)interp.StackPop(); // Compute c interp.StackPush(sphere_to_ray); interp.Run("DUP DOT 1 -"); DoubleItem c = (DoubleItem)interp.StackPop(); float discriminant = b.FloatValue * b.FloatValue - 4.0f * a.FloatValue * c.FloatValue; ArrayItem result = new ArrayItem(); if (discriminant < 0) { return(result); } else { double t1 = (-b.FloatValue - Math.Sqrt(discriminant)) / 2.0f / a.FloatValue; double t2 = (-b.FloatValue + Math.Sqrt(discriminant)) / 2.0f / a.FloatValue; result.Add(new IntersectionItem(t1, sphere)); result.Add(new IntersectionItem(t2, sphere)); return(result); } }