// ( object ray -- intersections ) public override void Execute(Interpreter interp) { RayItem ray = (RayItem)interp.StackPop(); dynamic obj = interp.StackPop(); interp.StackPush(intersections(interp, obj, transformRay(interp, obj, ray))); }
RayItem transformRay(Interpreter interp, dynamic obj, RayItem ray) { interp.StackPush(obj); interp.Run("'transform' REC@ INVERSE"); interp.StackPush(ray); interp.Run("SWAP TRANSFORM"); RayItem result = (RayItem)interp.StackPop(); return(result); }
StackItem multiply(MatrixItem l, RayItem r) { Vector4Item origin = new Vector4Item(r.Origin); Vector4Item direction = new Vector4Item(r.Direction); Vector4Item newOrigin = (Vector4Item)multiply(l, origin); Vector4Item newDirection = (Vector4Item)multiply(l, direction); return(new RayItem(newOrigin.Vector4Value, newDirection.Vector4Value)); }
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); } }