home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / 2D_3D / Tree3D_3.1 / Source / ForestCamera.m < prev    next >
Encoding:
Text File  |  1995-06-12  |  7.1 KB  |  225 lines

  1. // ForestCamera.m -- render a scene of 1 (or someday more) trees
  2.  
  3. #import <appkit/appkit.h>
  4. #import "ForestCamera.h"
  5. #import "Tree.h"
  6.  
  7. /* 4/7/93 -- Derrived from /NextDeveloper/Examples/3Dkit/SimpleCamera 
  8.     (by Bill Bumgarner 6/1/92 with assistance from Dave Springer)
  9.    5/9/93 -- Derrived from Simple (By Allen King)
  10.  */
  11.  
  12. @implementation ForestCamera
  13.  
  14. - awakeFromNib
  15. {    return [self newParameter :nil];    // set values in parameter window
  16. }
  17.  
  18. - initFrame :(const NXRect *) theRect
  19. {    id ambientLight, pointLight;
  20.     RtPoint xAxis = {1.0, 0.0, 0.0};
  21.     RtPoint yAxis = {0.0, 1.0, 0.0};
  22.     RtPoint lFromP = {0.5,0.5,0.75};                // light position point
  23.     RtPoint fromP = {10.0,3.0,5.0}, toP = {0,0,0};    // camera position
  24.     [super initFrame :theRect];
  25.     
  26.      // initialize camera
  27.     [self setEyeAt :fromP toward :toP roll :90.0];
  28.     redraw_mode = 1;
  29.     dirty = 0;
  30.  
  31.      // create a shader that will shade surfaces with a simple matte surface.
  32.     globalShader = [[N3DShader alloc] init];
  33.     [(N3DShader *)globalShader setShader :"matte"];
  34.     
  35.      // initialize 1 tree in this ForestCamera
  36.     theTree = [[Tree alloc] init];
  37.     [theTree plantIn :self];
  38.  
  39.      // create an ambientlight source.
  40.     ambientLight=[[N3DLight alloc] init];
  41.     [ambientLight makeAmbientWithIntensity :0.25];
  42.     [self addLight :ambientLight];
  43.     
  44.      // create a Point light and put at lFromP at full intensity (1.0).
  45.     pointLight = [[N3DLight alloc] init];
  46.     [pointLight makePointFrom :lFromP intensity :2.0];
  47.     [self addLight :pointLight];
  48.     
  49.      // set the surface type to generate smooth solids. 
  50.     [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES];
  51.     
  52.      // the N3DRotator object that governs rotational control via the mouseDown
  53.     theRotator=[[N3DRotator alloc] initWithCamera :self];
  54.     
  55.     return self;
  56. }
  57.  
  58. - newParameter :sender;
  59. {    int oldBranchFactor=[theTree branchFactor], oldLevels=[theTree levels];
  60.     int SDoldBranchFactor=[theTree SDbranchFactor];
  61.     int SDoldLevels=[theTree SDlevels];
  62.     int update=1;
  63.  
  64.     if (sender == levelsText || sender == levelsSlider)
  65.         if ([theTree levels :[sender intValue]] == oldLevels)
  66.             update = 0;
  67.     if (sender == branchFactorText || sender == branchFactorSlider)
  68.         if ([theTree branchFactor :[sender intValue]] == oldBranchFactor)
  69.             update = 0;
  70.     if (sender==angleText || sender==angleSlider)
  71.         [theTree angle :[sender doubleValue]];
  72.     if (sender == twistText || sender == twistSlider)
  73.         [theTree twist :[sender doubleValue]];
  74.     if (sender == shrinkText || sender == shrinkSlider)
  75.         [theTree shrink :[sender doubleValue]];
  76.  
  77.     if (sender == SDbranchFactorText || sender == SDbranchFactorSlider)
  78.         if ([theTree SDbranchFactor :[sender doubleValue]] ==SDoldBranchFactor)
  79.             update = 0;
  80.     if (sender == SDlevelsText || sender == SDlevelsSlider)
  81.         if ([theTree SDlevels :[sender doubleValue]] == SDoldLevels)
  82.             update = 0;
  83.     if (sender == SDangleText || sender == SDangleSlider)
  84.         [theTree SDangle :[sender doubleValue]];
  85.     if (sender == SDtwistText || sender == SDtwistSlider)
  86.         [theTree SDtwist :[sender doubleValue]];
  87.     if (sender == SDshrinkText || sender == SDshrinkSlider)
  88.         [theTree SDshrink :[sender doubleValue]];
  89.  
  90.     [angleSlider setFloatValue :[theTree angle]];
  91.      [angleText setFloatValue :[theTree angle]];
  92.     [twistSlider setFloatValue :[theTree twist]];
  93.      [twistText setFloatValue :[theTree twist]];
  94.     [shrinkSlider setFloatValue :[theTree shrink]];
  95.      [shrinkText setFloatValue :[theTree shrink]];
  96.     [SDangleSlider setFloatValue :[theTree SDangle]];
  97.      [SDangleText setFloatValue :[theTree SDangle]];
  98.     [SDtwistSlider setFloatValue :[theTree SDtwist]];
  99.      [SDtwistText setFloatValue :[theTree SDtwist]];
  100.     [SDshrinkSlider setFloatValue :[theTree SDshrink]];
  101.      [SDshrinkText setFloatValue :[theTree SDshrink]];
  102.     if (update)
  103.     {    [levelsSlider setIntValue :[theTree levels]];
  104.          [levelsText setIntValue :[theTree levels]];
  105.         [branchFactorSlider setIntValue :[theTree branchFactor]];
  106.          [branchFactorText setIntValue :[theTree branchFactor]];
  107.         [SDbranchFactorSlider setIntValue :[theTree SDbranchFactor]];
  108.          [SDbranchFactorText setIntValue :[theTree SDbranchFactor]];
  109.         [SDlevelsSlider setIntValue :[theTree SDlevels]];
  110.          [SDlevelsText setIntValue :[theTree SDlevels]];
  111.  
  112.         dirty = 1;
  113.         if (redraw_mode)
  114.         {    [theTree plantIn :self];
  115.             [self redrawNow :nil];
  116.             dirty = 0;
  117.     }    }
  118.     return self;
  119. }
  120.  
  121. #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
  122. - mouseDown :(NXEvent *)theEvent
  123. {
  124.     int            oldMask;
  125.     NXPoint        oldMouse, newMouse, dMouse;
  126.     RtMatrix    rmat, irmat;
  127.     
  128.     [theRotator setRotationAxis :N3D_ZAxis];
  129.     
  130.      // track the mouse until a mouseUp event occurs, updating the display
  131.      // as tracking happens.
  132.     [self lockFocus];
  133.     oldMask = [window addToEventMask :ACTIVEBUTTONMASK];
  134.     
  135.      // switch to the N3D_WireFrame surface type.
  136.     [self setSurfaceTypeForAll :N3D_WireFrame chooseHider :YES];
  137.     
  138.     oldMouse = theEvent->location;
  139.     [self convertPoint :&oldMouse fromView :nil];
  140.     while (1)
  141.     {    newMouse = theEvent->location;
  142.         [self convertPoint :&newMouse fromView :nil];
  143.         dMouse.x = newMouse.x - oldMouse.x;
  144.         dMouse.y = newMouse.y - oldMouse.y;
  145.         if (dMouse.x != 0.0 || dMouse.y != 0.0) 
  146.         {    [theRotator trackMouseFrom :&oldMouse to :&newMouse
  147.             rotationMatrix :rmat andInverse :irmat];
  148.             [worldShape concatTransformMatrix :rmat premultiply :NO];
  149.             [self display];
  150.         }
  151.         theEvent = [NXApp getNextEvent :ACTIVEBUTTONMASK];
  152.         if (theEvent->type == NX_MOUSEUP)
  153.             break;
  154.         oldMouse = newMouse;
  155.     }
  156.      // switch back to the N3D_SmoothSolids surface type
  157.     [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES];    
  158.     [self display];
  159.     [self unlockFocus];
  160.     
  161.     [window setEventMask :oldMask];
  162.     return self;
  163. }
  164.  
  165. - redrawNow :sender;
  166. {    [self lockFocus];
  167.     [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES];    
  168.     [self display];
  169.     [self unlockFocus];
  170.     return self;
  171. }
  172.  
  173. - redrawMode :sender;
  174. {    int lastRedraw_mode = redraw_mode;
  175.     redraw_mode = [sender selectedTag]? 0: 1;
  176.     if (!(lastRedraw_mode &&  !redraw_mode))
  177.     {    if (dirty)
  178.             [theTree plantIn :self];
  179.         dirty = 0;
  180.         [self redrawNow :nil];
  181.     }
  182.     return self;
  183. }
  184.  
  185. - randomMode :sender    {[theTree randomMode :sender]; return self;}
  186. - specis :sender        {[theTree specis :sender]; return self;}
  187. - (int)redraw_mode        {return redraw_mode;}
  188.  
  189. - dumpRib :sender
  190. {
  191.     static id savePanel=nil;
  192.     NXStream *ts;
  193.     char buf[MAXPATHLEN+1];
  194.     
  195.     // initialize the savePanel, if it hasn''t been done so previously
  196.     if (!savePanel) 
  197.     {    savePanel=[SavePanel new];
  198.         [savePanel setRequiredFileType :"rib"];
  199.     }
  200.     
  201.     // run the savepanel.  
  202.     if([savePanel runModal])
  203.     {     // returned w/pathname, open a stream and
  204.         ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
  205.          // process the file name for a custom display line such that
  206.          // "prman <<filename>>.rib" will put the resulting image somewhere
  207.          // predictably useful.
  208.         strcpy(buf, [savePanel filename]);
  209.          // remove the .rib extension from the path returned by the SavePanel
  210.         strrchr(buf,'.')[0]='\0';
  211.          // feed to NXPrintf to put in the custom Display command
  212.         NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
  213.          // then feed the rib code to the stream and
  214.         [theTree copyRIBCode :ts];
  215.          // save the stream to the file selected in the savepanel
  216.         NXSaveToFile(ts, [savePanel filename]);
  217.          // and close the stream (which also flushes it), also making sure
  218.          // that the allocated memory is freed.
  219.         NXCloseMemory(ts,NX_FREEBUFFER);
  220.     }
  221.     return self;
  222. }
  223.  
  224. @end
  225.