home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / 3Dkit / Simple / SimpleCamera.m < prev    next >
Text File  |  1992-06-02  |  6KB  |  169 lines

  1. #import <appkit/appkit.h>
  2. #import "SimpleCamera.h"
  3. #import "SimpleShape.h"
  4.  
  5. /* SimpleCamera -- by Bill Bumgarner 6/1/92
  6.  *                   with assistance from Dave Springer.
  7.  *
  8.  * SimpleCamera demonstrates the creation of a very simple 3Dkit scene 
  9.  * that has mouse control via the N3DRotator class, supports dumping RIB 
  10.  * code to a file, contains light sources (ambient light and a point light), 
  11.  * has a surface shader, supports both WireFrame and SmoothSolid rendering, 
  12.  * and has a single custom N3DShape that generates a Torus (or teapot).
  13.  *
  14.  * Simple.app was created as an example of using the 3Dkit.  Parts of it
  15.  * come from Teapot.app by Dave Springer (see SimpleShape.m).
  16.  *
  17.  *  You may freely copy, distribute and reuse the code in this example.
  18.  *  NeXT disclaims any warranty of any kind, expressed or implied,
  19.  *  as to its fitness for any particular use.
  20.  */
  21.  
  22. @implementation SimpleCamera
  23. - initFrame:(const NXRect *) theRect
  24. {
  25.   // camera position points
  26.   RtPoint fromP = {0,0,5.0}, toP = {0,0,0};
  27.  
  28.   // light position point
  29.   RtPoint lFromP = {0.5,0.5,0.75};
  30.  
  31.   // the various 3Dkit object id''s that we will initialize here
  32.   id ambientLight;
  33.   id aLight;
  34.   id aShader;
  35.   id aShape;
  36.  
  37.   // initialize camera and put it at (0,0,5.0) looking at the origin (0,0,0)
  38.   // roll specifies the roll angle of the camera...
  39.   [super initFrame:theRect];
  40.   [self setEyeAt:fromP toward:toP roll:0.0];
  41.   
  42.   // create a shader that will shade surfaces with a simple matte surface.
  43.   aShader=[[N3DShader alloc] init];
  44.   // uncomment the following lines to generate a blue matte surface.
  45.   // This is slow on a monochrome system.
  46.   // [aShader setUseColor:YES];
  47.   // [aShader setColor:NX_COLORBLUE];
  48.   [(N3DShader *)aShader setShader:"matte"];
  49.  
  50.   // initialize the world shape and set its shader to be aShader
  51.   aShape=[[SimpleShape alloc] init];
  52.   [(N3DShape *) aShape  setShader:aShad@I
  53.   [[self setWorldShape:aShape] free]; // free the default world shape
  54.  
  55.   // create an ambientlight source.
  56.   ambientLight=[[N3DLight alloc] init];
  57.   [ambientLight makeAmbientWithIntensity:0.1];
  58.   [self addLight:ambientLight];
  59.   
  60.   // create a Point light and put it at (0.5, 0.5, 0.75) at 
  61.   // full intensity (1.0).
  62.   aLight=[[N3DLight alloc] init];
  63.   [aLight makePointFrom:lFromP intensity:1.0];
  64.   [self addLight:aLight];
  65.  
  66.   // set the surface type to generate smooth solids.  The mouseDown:
  67.   // method automatically drops to N3D_WireFrame whenever the user manipulates
  68.   // the scene via the mouse (see the mouseDown: implementation below).
  69.   // This must be done after the setWorldShape: method (or after any new shape
  70.   // is added to the hierarchy).
  71.   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
  72.  
  73.   // allocate and initialize the N3DRotator object that governs
  74.   // rotational control via the mouseDown: method
  75.   theRotator=[[N3DRotator alloc] initWithCamera:self];
  76.  
  77.   return self;
  78. }
  79.  
  80. - dumpRib:sender
  81. {
  82.   static id savePanel=nil;
  83.   NXStream *ts;
  84.   char buf[MAXPATHLEN+1];
  85.  
  86.   // initialize the savePanel, if it hasn''t been done so previously
  87.   if (!savePanel) {
  88.     savePanel=[SavePanel new];
  89.     [savePanel setRequiredFileType:"rib"];
  90.   }
  91.  
  92.   // run the savepanel.  
  93.   if([savePanel runModal]){
  94.     // returned w/pathname, open a stream and
  95.     ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
  96.     // process the file name for a custom display line such that
  97.     // "prman <<filename>>.rib" will put the resulting image somewhere
  98.     // predictably useful.
  99.     strcpy(buf, [savePanel filename]);
  100.     // remove the .rib extension from the path returned by the SavePanel
  101.     strrchr(buf,'.')[0]='\0';
  102.     // feed to NXPrintf to put in the custom Display command
  103.     NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
  104.     // then feed the rib code to the stream and
  105.     [self copyRIBCode:ts];
  106.     // save the stream to the file selected in the savepanel
  107.     NXSaveToFile(ts, [savePanel filename]);
  108.     // and close the stream (which also flushes it), also making sure
  109.     // that the allocated memory is freed.
  110.     NXCloseMemory(ts,NX_FREEBUFFER);
  111.   }
  112.   return self;
  113. }
  114.  
  115. #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
  116. - mouseDown:(NXEvent *)theEvent
  117. {
  118.   int                     oldMask;
  119.   NXPoint        oldMouse, new@Pe, dMouse;
  120.   RtMatrix        rmat, irmat;
  121.  
  122.   // find out what axis of rotation the rotator should be constrained to
  123.   switch([rotoMatrix selectedRow]){
  124.   case 0: [theRotator setRotationAxis:N3D_AllAxes]; break;
  125.   case 1: [theRotator setRotationAxis:N3D_XAxis]; break;
  126.   case 2: [theRotator setRotationAxis:N3D_YAxis]; break;
  127.   case 3: [theRotator setRotationAxis:N3D_ZAxis]; break;
  128.   case 4: [theRotator setRotationAxis:N3D_XYAxes]; break;
  129.   case 5: [theRotator setRotationAxis:N3D_XZAxes]; break;
  130.   case 6: [theRotator setRotationAxis:N3D_YZAxes]; break;
  131.   }
  132.  
  133.   // track the mouse until a mouseUp event occurs, updating the display
  134.   // as tracking happens.
  135.   [self lockFocus];
  136.   oldMask = [window addToEventMask:ACTIVEBUTTONMASK];
  137.   
  138.   // switch to the N3D_WireFrame surface type
  139.   [self setSurfaceTypeForAll:N3D_WireFrame chooseHider:YES];
  140.   
  141.   oldMouse = theEvent->location;
  142.   [self convertPoint:&oldMouse fromView:nil];
  143.   while (1)
  144.   {
  145.     newMouse = theEvent->location;
  146.     [self convertPoint:&newMouse fromView:nil];
  147.     dMouse.x = newMouse.x - oldMouse.x;
  148.     dMouse.y = newMouse.y - oldMouse.y;
  149.     if (dMouse.x != 0.0 || dMouse.y != 0.0) {
  150.       [theRotator trackMouseFrom:&oldMouse to:&newMouse
  151.        rotationMatrix:rmat andInverse:irmat];
  152.       [worldShape concatTransformMatrix:rmat premultiply:NO];
  153.       [self display];
  154.     }
  155.     theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK];
  156.     if (theEvent->type == NX_MOUSEUP)
  157.       break;
  158.     oldMouse = newMouse;
  159.   }
  160.   // switch back to the N3D_SmoothSolids surface type
  161.   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];    
  162.   [self display];
  163.   [self unlockFocus];
  164.  
  165.   [window setEventMask:oldMask];
  166.   return self;
  167. }
  168. @end
  169.