Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Insipred by this question and the corresponding answer I've written a code for full-screen exploration of 3D scenes using standard WASD and mouse look controls. Here it is.

enter image description here

Begin["wasd`"];
prmWORLDWIDTH = 300;
prmVIEWERHEIGHT = 2.5;
prmMOUSESENS = 0.01;
prmKEYSENS = 2;

pos = {-146.2715891902948`, -154.52068004641723`, 2.5`}(*{0.,-200,prmVIEWERHEIGHT}*);
moveDir = {0.6365371822219685`, 0.7712460149971068`, 0.`}(*{0,1,0}*);
viewDir = moveDir;
strafeDir = {0.7712460149971068`, -0.6365371822219685`, 0.`}(*{1,0,0}*);

cube = {Gray, EdgeForm[None],
   CapForm[None], Tube[{{-150, -150, 0}, {-50, 0, 0}, {50, 0, 0}}, 20
    ],
   Blue // Lighter,
   Translate[
    ExampleData[{"Geometry3D", "SpaceShuttle"}, "PolygonObjects"]~
     Scale~3, {0, 0, 6}]
   };
floor = {
    Texture@ExampleData[{"ColorTexture", "GreenMarble"}],
    EdgeForm@None,
    Polygon[{{-w, -w, 0}, {-w, w, 0}, {w, w, 0}, {w, -w, 0}},
     VertexTextureCoordinates -> {{0, 0}, {1, 0}, {1, 1}, {0, 1}}]
    } /. w -> prmWORLDWIDTH;

rotTrans := Function[x, Evaluate[RotationTransform[x, {0., 0., 1.}]]];
mp0 = MousePosition[];
getMouseOffset := (mousePos = MousePosition[];
   {mouseDx, mouseDy} = mousePos - mp0;
   mp0 = mousePos;
   );
processMouse := (getMouseOffset;
   viewDir = 
    RotationTransform[-prmMOUSESENS mouseDy, strafeDir]@viewDir;
   {moveDir, strafeDir, viewDir} = 
    rotTrans[-prmMOUSESENS mouseDx] /@ {moveDir, strafeDir, viewDir}; 
   );

processKeyboard := Switch[CurrentValue["EventKey"],
   "w", pos += prmKEYSENS moveDir,
   "s", pos -= prmKEYSENS moveDir,
   "a", pos -= prmKEYSENS strafeDir,
   "d", pos += prmKEYSENS strafeDir
   ];

actions = {
   "MouseMoved" :> processMouse,
   "KeyDown" :> processKeyboard
   };

hideMouse[expr_] := 
  MouseAppearance[expr, Graphics[{Opacity@.01, Point@{0, 0}}]];

nb = MessageDialog[
   Dynamic@EventHandler[
     hideMouse@
      Style[
       Graphics3D[{cube, floor},
        ViewVector -> {pos, pos + viewDir},
        ViewRange -> {0.1, 300},
        Lighting -> "Neutral",
        Boxed -> False,
        ImageSize -> Full,
        Background -> LightBlue,
        PlotRangePadding -> 0
        ],
       Selectable -> False,
       Editable -> False
       ],
     actions
     ],
   CellMargins -> 0,
   ShowCellBracket -> False,
   ShowCellLabel -> False,
   "TrackCellChangeTimes" -> False,
   WindowElements -> {},
   WindowFrame -> "Normal",
   WindowSize -> Full,
   WindowMargins -> Automatic,
   WindowTitle -> "WASD"
   ];

SetOptions[nb, NotebookEventActions -> actions];
End[];

To implement 'pure' full screen look I used this answer.

Though I'm pretty satisfied with the result there are some issues here which require tweaking.

  1. Since mouse offset events are implemented using MousePosition it is quite easy to get mouse look stucked (e.g. when you try to turn around). This happens when hidden mouse cursor hits screen borders. So, how to correctly handle mouse offset events?

  2. It is impossible to move diagonally because KeyDown events do not handle simultaneous keystrokes. Can something be done with this?

  3. The duplication of event handlers at the end (SetOptions[nb, NotebookEventActions -> actions]) does not seem logical to me, but without it KeyDown events do not work. Why?

  4. hideMouse hack is what I discussed here. Unfortunately the elegant construction MouseAppearance[expr, Spacer[0]] proposed by Mike does not work on v. 8.0.4 and WinXP and Win7.

  5. And finally are there any possibilities for speeding this up?

share|improve this question
2  
Next up: "How do I implement Quake 3 in Mathematica?" =) –  rm -rf Jan 11 '13 at 1:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Browse other questions tagged or ask your own question.