Annotation of Examples/3Dkit/Simple/SimpleCamera.m, revision 1.1.1.1

1.1       root        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:   // Note that the camera vector is in a left-handed coordinate system; this
                     27:   // is the default for RenderMan.  In order to look at the front of the
                     28:   // scene, you have to step backwards along the z-axis; in other words, you
                     29:   // have to move the eye point negatively in z.  
                     30:   RtPoint fromP = {0,0,-5.0}, toP = {0,0,0};
                     31: 
                     32:   // light position point
                     33:   // Notice the "-0.75" z-coordinate.  This is because of the left-handed
                     34:   // coordinate system.
                     35:   RtPoint lFromP = {0.5,0.5,-0.75};
                     36: 
                     37:   // the various 3Dkit object id''s that we will initialize here
                     38:   id ambientLight;
                     39:   id aLight;
                     40:   id aShader;
                     41:   id aShape;
                     42: 
                     43:   // initialize camera and put it at (0,0,-5.0) looking at the origin (0,0,0)
                     44:   // roll specifies the roll angle of the camera...
                     45:   [super initFrame:theRect];
                     46:   [self setEyeAt:fromP toward:toP roll:0.0];
                     47:   
                     48:   // create a shader that will shade surfaces with a simple matte surface.
                     49:   aShader=[[N3DShader alloc] init];
                     50:   // Generate a blue matte surface.
                     51:   // This is slow on a monochrome system.
                     52:   [aShader setUseColor:YES];
                     53:   [aShader setColor:NX_COLORBLUE];
                     54:   [(N3DShader *)aShader setShader:"matte"];
                     55:   // Comment the previous line and uncomment the following lines to generate
                     56:   // a texture-mapped surface.  The N3DShader object does all the necessary
                     57:   // things to make a shader work properly: it sends all the Declare commands
                     58:   // and a complete parameter string.  All you need to do is change the
                     59:   // parameters you want with the -setShaderArg:fooValue: family of methods.
                     60:   // When you compile your own shader, all the information about the arguments
                     61:   // and their default values are stored in the .slo file, and the N3DShader
                     62:   // object knows how to read them.
                     63:   //[(N3DShader *)aShader setShader:"texmap"];
                     64:   //[aShader setShaderArg:"texname"
                     65:   //   stringValue:"/NextLibrary/Textures/pebbles.tx"];
                     66: 
                     67:   // initialize the world shape and set its shader to be aShader
                     68:   aShape=[[SimpleShape alloc] init];
                     69:   [(N3DShape *) aShape  setShader:aShader];
                     70:   [[self setWorldShape:aShape] free]; // free the default world shape
                     71: 
                     72:   // create an ambientlight source.
                     73:   ambientLight=[[N3DLight alloc] init];
                     74:   [ambientLight makeAmbientWithIntensity:0.1];
                     75:   [self addLight:ambientLight];
                     76:   
                     77:   // create a Point light and put it at (0.5, 0.5, -0.75) at 
                     78:   // full intensity (1.0).
                     79:   aLight=[[N3DLight alloc] init];
                     80:   [aLight makePointFrom:lFromP intensity:1.0];
                     81:   [self addLight:aLight];
                     82: 
                     83:   // create another Point light and put it at (-0.5, -0.5, -0.75) at 
                     84:   // full intensity (1.0).
                     85:   N3D_XComp( lFromP ) = -0.5;
                     86:   N3D_YComp( lFromP ) = -0.5;
                     87:   aLight=[[N3DLight alloc] init];
                     88:   [aLight makePointFrom:lFromP intensity:1.0];
                     89:   [self addLight:aLight];
                     90: 
                     91:   // set the surface type to generate smooth solids.  The mouseDown:
                     92:   // method automatically drops to N3D_WireFrame whenever the user manipulates
                     93:   // the scene via the mouse (see the mouseDown: implementation below).
                     94:   // This must be done after the setWorldShape: method (or after any new shape
                     95:   // is added to the hierarchy).
                     96:   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
                     97: 
                     98:   // allocate and initialize the N3DRotator object that governs
                     99:   // rotational control via the mouseDown: method
                    100:   theRotator=[[N3DRotator alloc] initWithCamera:self];
                    101: 
                    102:   return self;
                    103: }
                    104: 
                    105: - dumpRib:sender
                    106: {
                    107:   static id savePanel=nil;
                    108:   NXStream *ts;
                    109:   char buf[MAXPATHLEN+1];
                    110: 
                    111:   // initialize the savePanel, if it hasn''t been done so previously
                    112:   if (!savePanel) {
                    113:     savePanel=[SavePanel new];
                    114:     [savePanel setRequiredFileType:"rib"];
                    115:   }
                    116: 
                    117:   // run the savepanel.  
                    118:   if([savePanel runModal]){
                    119:     // returned w/pathname, open a stream and
                    120:     ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
                    121:     // process the file name for a custom display line such that
                    122:     // "prman <<filename>>.rib" will put the resulting image somewhere
                    123:     // predictably useful.
                    124:     strcpy(buf, [savePanel filename]);
                    125:     // remove the .rib extension from the path returned by the SavePanel
                    126:     strrchr(buf,'.')[0]='\0';
                    127:     // feed to NXPrintf to put in the custom Display command
                    128:     NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
                    129:     // then feed the rib code to the stream and
                    130:     [self copyRIBCode:ts];
                    131:     // save the stream to the file selected in the savepanel
                    132:     NXSaveToFile(ts, [savePanel filename]);
                    133:     // and close the stream (which also flushes it), also making sure
                    134:     // that the allocated memory is freed.
                    135:     NXCloseMemory(ts,NX_FREEBUFFER);
                    136:   }
                    137:   return self;
                    138: }
                    139: 
                    140: #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
                    141: - mouseDown:(NXEvent *)theEvent
                    142: {
                    143:   int                  oldMask;
                    144:   NXPoint              oldMouse, newMouse, dMouse;
                    145:   RtMatrix             rmat, irmat;
                    146: 
                    147:   // find out what axis of rotation the rotator should be constrained to
                    148:   switch([rotoMatrix selectedRow]){
                    149:   case 0: [theRotator setRotationAxis:N3D_AllAxes]; break;
                    150:   case 1: [theRotator setRotationAxis:N3D_XAxis]; break;
                    151:   case 2: [theRotator setRotationAxis:N3D_YAxis]; break;
                    152:   case 3: [theRotator setRotationAxis:N3D_ZAxis]; break;
                    153:   case 4: [theRotator setRotationAxis:N3D_XYAxes]; break;
                    154:   case 5: [theRotator setRotationAxis:N3D_XZAxes]; break;
                    155:   case 6: [theRotator setRotationAxis:N3D_YZAxes]; break;
                    156:   }
                    157: 
                    158:   // track the mouse until a mouseUp event occurs, updating the display
                    159:   // as tracking happens.
                    160:   [self lockFocus];
                    161:   oldMask = [window addToEventMask:ACTIVEBUTTONMASK];
                    162:   
                    163:   // switch to the N3D_WireFrame surface type
                    164:   [self setSurfaceTypeForAll:N3D_WireFrame chooseHider:YES];
                    165:   
                    166:   oldMouse = theEvent->location;
                    167:   [self convertPoint:&oldMouse fromView:nil];
                    168:   while (1)
                    169:   {
                    170:     newMouse = theEvent->location;
                    171:     [self convertPoint:&newMouse fromView:nil];
                    172:     dMouse.x = newMouse.x - oldMouse.x;
                    173:     dMouse.y = newMouse.y - oldMouse.y;
                    174:     if (dMouse.x != 0.0 || dMouse.y != 0.0) {
                    175:       [theRotator trackMouseFrom:&oldMouse to:&newMouse
                    176:        rotationMatrix:rmat andInverse:irmat];
                    177:       [worldShape concatTransformMatrix:rmat premultiply:NO];
                    178:       [self display];
                    179:     }
                    180:     theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK];
                    181:     if (theEvent->type == NX_MOUSEUP)
                    182:       break;
                    183:     oldMouse = newMouse;
                    184:   }
                    185:   // switch back to the N3D_SmoothSolids surface type
                    186:   [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];        
                    187:   [self display];
                    188:   [self unlockFocus];
                    189: 
                    190:   [window setEventMask:oldMask];
                    191:   return self;
                    192: }
                    193: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.