(* :Title: RealTime3D *)

(* :Author: Don Neufeld *)

(* :Summary:
This package changes the default $DisplayFunction to support the
experimental interactive 3D graphics in Version 4.
*)
	
(* :Context: Graphics`RealTime3D` *)

(* :Copyright: Copyright 1999, Wolfram Research, Inc.*)

(* :Package Version: 1.2.3 *)

(* :History:
	V1.0 by Don Neufeld, April 1998.
	V1.1 modified by John M. Novak, April 1998.
	V1.2 by John M. Novak, April 1998 -- added a cache for $DisplayFunction.
	   so that it may be reset to original value (by Default3D.m), added
	   check for a Windows notebook front end when package loads.
    V1.2.1 by John M. Novak, September 1998 -- allow Macintosh without
       issuing warning message.
    V1.2.2 by Don Neufeld, January 1999 -- add BoxRatios to allowed options
       now that the Front End supports it.
    V1.2.3 by John M. Novak, February 1999 -- force numericalization of
       input, since FE doesn't understand rationals, etc.
*)

(* :Keywords: RealTime, RealTime3D,interactive, Graphics, 3D *)

(* :Sources: *)

(* :Mathematica Version: 4.0 *)

(* :Limitation:
Only works in front ends where the Geometry celltype is supported
(in 4.0, this means only Windows and Mac).
*)

BeginPackage["RealTime3D`", "Utilities`FilterOptions`"]

RealTime3D::warn =
"RealTime3D` is an experimental feature for rendering three-dimensional
graphics via OpenGL. It currently renders only in Windows and Macintosh
notebook front ends. Evaluate <<Default3D` to return to previous
values for display functions.";

If[Head[$FrontEnd] =!= FrontEndObject ||
   !MemberQ[{"Windows", "PowerMac", "Mac", "Macintosh"},
   (LinkWrite[First[$FrontEnd], FrontEnd`Value["$SystemID"]];
    LinkRead[First[$FrontEnd]])],
 Message[RealTime3D::warn]
]

RealTimeGraphicsDisplayFunction::usage =
"RealTimeGraphicsDisplayFunction is display function which allows
Graphics3D and SurfaceGraphics objects to be rotated interactively in
the front end.";

Begin["`Private`"]

SupportedGraphicsOptions=
   {Boxed, Lighting, Mesh,
    SphericalRegion, ViewPoint, BoxRatios};

(* Note that input is numericalized via N, since the FE won't understand
   exact non-integer input. Hopefully the rendering engine can be modified
   in the future so that numericalization can occur after a scaling, to
   allow easier plotting of small values... *)
RealTimeGraphicsDisplayFunction[
        (h:(Graphics3D | SurfaceGraphics))[gr_, opts___], rtopts___] :=
   (CellPrint[
        Cell[BoxData[N[h[gr, FilterOptions[SupportedGraphicsOptions, opts, rtopts]]]],
             "Graphics"
        ]
    ];h[gr, opts])/;Head[$FrontEnd] === FrontEndObject

RealTimeGraphicsDisplayFunction[anygr_] := Display[$Display, anygr]

End[]

EndPackage[]

(* set $DisplayFunction -- first cache current value (if value hasn't already
   been cached) *)
If[!ValueQ[System`Private`$OriginalDisplayFunction],
    System`Private`$OriginalDisplayFunction = $DisplayFunction
];
$DisplayFunction = RealTimeGraphicsDisplayFunction;

(* $Display, $SoundDisplay, $SoundDisplayFunction, $AnimationFunction,
   and $RasterFunction are left unchanged by this mode *)

Null
