home *** CD-ROM | disk | FTP | other *** search
- #import <appkit/appkit.h>
- #import "SimpleCamera.h"
- #import "SimpleShape.h"
-
- /* SimpleCamera -- by Bill Bumgarner 6/1/92
- * with assistance from Dave Springer.
- *
- * SimpleCamera demonstrates the creation of a very simple 3Dkit scene
- * that has mouse control via the N3DRotator class, supports dumping RIB
- * code to a file, contains light sources (ambient light and a point light),
- * has a surface shader, supports both WireFrame and SmoothSolid rendering,
- * and has a single custom N3DShape that generates a Torus (or teapot).
- *
- * Simple.app was created as an example of using the 3Dkit. Parts of it
- * come from Teapot.app by Dave Springer (see SimpleShape.m).
- *
- * You may freely copy, distribute and reuse the code in this example.
- * NeXT disclaims any warranty of any kind, expressed or implied,
- * as to its fitness for any particular use.
- */
-
- @implementation SimpleCamera
- - initFrame:(const NXRect *) theRect
- {
- // camera position points
- RtPoint fromP = {0,0,5.0}, toP = {0,0,0};
-
- // light position point
- RtPoint lFromP = {0.5,0.5,0.75};
-
- // the various 3Dkit object id''s that we will initialize here
- id ambientLight;
- id aLight;
- id aShader;
- id aShape;
-
- // initialize camera and put it at (0,0,5.0) looking at the origin (0,0,0)
- // roll specifies the roll angle of the camera...
- [super initFrame:theRect];
- [self setEyeAt:fromP toward:toP roll:0.0];
-
- // create a shader that will shade surfaces with a simple matte surface.
- aShader=[[N3DShader alloc] init];
- // uncomment the following lines to generate a blue matte surface.
- // This is slow on a monochrome system.
- // [aShader setUseColor:YES];
- // [aShader setColor:NX_COLORBLUE];
- [(N3DShader *)aShader setShader:"matte"];
-
- // initialize the world shape and set its shader to be aShader
- aShape=[[SimpleShape alloc] init];
- [(N3DShape *) aShape setShader:aShad@I
- [[self setWorldShape:aShape] free]; // free the default world shape
-
- // create an ambientlight source.
- ambientLight=[[N3DLight alloc] init];
- [ambientLight makeAmbientWithIntensity:0.1];
- [self addLight:ambientLight];
-
- // create a Point light and put it at (0.5, 0.5, 0.75) at
- // full intensity (1.0).
- aLight=[[N3DLight alloc] init];
- [aLight makePointFrom:lFromP intensity:1.0];
- [self addLight:aLight];
-
- // set the surface type to generate smooth solids. The mouseDown:
- // method automatically drops to N3D_WireFrame whenever the user manipulates
- // the scene via the mouse (see the mouseDown: implementation below).
- // This must be done after the setWorldShape: method (or after any new shape
- // is added to the hierarchy).
- [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
-
- // allocate and initialize the N3DRotator object that governs
- // rotational control via the mouseDown: method
- theRotator=[[N3DRotator alloc] initWithCamera:self];
-
- return self;
- }
-
- - dumpRib:sender
- {
- static id savePanel=nil;
- NXStream *ts;
- char buf[MAXPATHLEN+1];
-
- // initialize the savePanel, if it hasn''t been done so previously
- if (!savePanel) {
- savePanel=[SavePanel new];
- [savePanel setRequiredFileType:"rib"];
- }
-
- // run the savepanel.
- if([savePanel runModal]){
- // returned w/pathname, open a stream and
- ts=NXOpenMemory(NULL, 0, NX_WRITEONLY);
- // process the file name for a custom display line such that
- // "prman <<filename>>.rib" will put the resulting image somewhere
- // predictably useful.
- strcpy(buf, [savePanel filename]);
- // remove the .rib extension from the path returned by the SavePanel
- strrchr(buf,'.')[0]='\0';
- // feed to NXPrintf to put in the custom Display command
- NXPrintf(ts, "Display \"%s.tiff\" \"file\" \"rgba\"\n", buf);
- // then feed the rib code to the stream and
- [self copyRIBCode:ts];
- // save the stream to the file selected in the savepanel
- NXSaveToFile(ts, [savePanel filename]);
- // and close the stream (which also flushes it), also making sure
- // that the allocated memory is freed.
- NXCloseMemory(ts,NX_FREEBUFFER);
- }
- return self;
- }
-
- #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK)
- - mouseDown:(NXEvent *)theEvent
- {
- int oldMask;
- NXPoint oldMouse, new@Pe, dMouse;
- RtMatrix rmat, irmat;
-
- // find out what axis of rotation the rotator should be constrained to
- switch([rotoMatrix selectedRow]){
- case 0: [theRotator setRotationAxis:N3D_AllAxes]; break;
- case 1: [theRotator setRotationAxis:N3D_XAxis]; break;
- case 2: [theRotator setRotationAxis:N3D_YAxis]; break;
- case 3: [theRotator setRotationAxis:N3D_ZAxis]; break;
- case 4: [theRotator setRotationAxis:N3D_XYAxes]; break;
- case 5: [theRotator setRotationAxis:N3D_XZAxes]; break;
- case 6: [theRotator setRotationAxis:N3D_YZAxes]; break;
- }
-
- // track the mouse until a mouseUp event occurs, updating the display
- // as tracking happens.
- [self lockFocus];
- oldMask = [window addToEventMask:ACTIVEBUTTONMASK];
-
- // switch to the N3D_WireFrame surface type
- [self setSurfaceTypeForAll:N3D_WireFrame chooseHider:YES];
-
- oldMouse = theEvent->location;
- [self convertPoint:&oldMouse fromView:nil];
- while (1)
- {
- newMouse = theEvent->location;
- [self convertPoint:&newMouse fromView:nil];
- dMouse.x = newMouse.x - oldMouse.x;
- dMouse.y = newMouse.y - oldMouse.y;
- if (dMouse.x != 0.0 || dMouse.y != 0.0) {
- [theRotator trackMouseFrom:&oldMouse to:&newMouse
- rotationMatrix:rmat andInverse:irmat];
- [worldShape concatTransformMatrix:rmat premultiply:NO];
- [self display];
- }
- theEvent = [NXApp getNextEvent:ACTIVEBUTTONMASK];
- if (theEvent->type == NX_MOUSEUP)
- break;
- oldMouse = newMouse;
- }
- // switch back to the N3D_SmoothSolids surface type
- [self setSurfaceTypeForAll:N3D_SmoothSolids chooseHider:YES];
- [self display];
- [self unlockFocus];
-
- [window setEventMask:oldMask];
- return self;
- }
- @end
-