This is ForestCamera.m in view mode; [Download] [Up]
// ForestCamera.m -- render a scene of 1 (or someday more) trees #import <appkit/appkit.h> #import "ForestCamera.h" #import "Tree.h" /* 4/7/93 -- Derrived from /NextDeveloper/Examples/3Dkit/SimpleCamera (by Bill Bumgarner 6/1/92 with assistance from Dave Springer) 5/9/93 -- Derrived from Simple (By Allen King) */ @implementation ForestCamera - awakeFromNib { return [self newParameter :nil]; // set values in parameter window } - initFrame :(const NXRect *) theRect { id ambientLight, pointLight; RtPoint xAxis = {1.0, 0.0, 0.0}; RtPoint yAxis = {0.0, 1.0, 0.0}; RtPoint lFromP = {0.5,0.5,0.75}; // light position point RtPoint fromP = {10.0,3.0,5.0}, toP = {0,0,0}; // camera position [super initFrame :theRect]; // initialize camera [self setEyeAt :fromP toward :toP roll :90.0]; redraw_mode = 1; dirty = 0; // create a shader that will shade surfaces with a simple matte surface. globalShader = [[N3DShader alloc] init]; [(N3DShader *)globalShader setShader :"matte"]; // initialize 1 tree in this ForestCamera theTree = [[Tree alloc] init]; [theTree plantIn :self]; // create an ambientlight source. ambientLight=[[N3DLight alloc] init]; [ambientLight makeAmbientWithIntensity :0.25]; [self addLight :ambientLight]; // create a Point light and put at lFromP at full intensity (1.0). pointLight = [[N3DLight alloc] init]; [pointLight makePointFrom :lFromP intensity :2.0]; [self addLight :pointLight]; // set the surface type to generate smooth solids. [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES]; // the N3DRotator object that governs rotational control via the mouseDown theRotator=[[N3DRotator alloc] initWithCamera :self]; return self; } - newParameter :sender; { int oldBranchFactor=[theTree branchFactor], oldLevels=[theTree levels]; int SDoldBranchFactor=[theTree SDbranchFactor]; int SDoldLevels=[theTree SDlevels]; int update=1; if (sender == levelsText || sender == levelsSlider) if ([theTree levels :[sender intValue]] == oldLevels) update = 0; if (sender == branchFactorText || sender == branchFactorSlider) if ([theTree branchFactor :[sender intValue]] == oldBranchFactor) update = 0; if (sender==angleText || sender==angleSlider) [theTree angle :[sender doubleValue]]; if (sender == twistText || sender == twistSlider) [theTree twist :[sender doubleValue]]; if (sender == shrinkText || sender == shrinkSlider) [theTree shrink :[sender doubleValue]]; if (sender == SDbranchFactorText || sender == SDbranchFactorSlider) if ([theTree SDbranchFactor :[sender doubleValue]] ==SDoldBranchFactor) update = 0; if (sender == SDlevelsText || sender == SDlevelsSlider) if ([theTree SDlevels :[sender doubleValue]] == SDoldLevels) update = 0; if (sender == SDangleText || sender == SDangleSlider) [theTree SDangle :[sender doubleValue]]; if (sender == SDtwistText || sender == SDtwistSlider) [theTree SDtwist :[sender doubleValue]]; if (sender == SDshrinkText || sender == SDshrinkSlider) [theTree SDshrink :[sender doubleValue]]; [angleSlider setFloatValue :[theTree angle]]; [angleText setFloatValue :[theTree angle]]; [twistSlider setFloatValue :[theTree twist]]; [twistText setFloatValue :[theTree twist]]; [shrinkSlider setFloatValue :[theTree shrink]]; [shrinkText setFloatValue :[theTree shrink]]; [SDangleSlider setFloatValue :[theTree SDangle]]; [SDangleText setFloatValue :[theTree SDangle]]; [SDtwistSlider setFloatValue :[theTree SDtwist]]; [SDtwistText setFloatValue :[theTree SDtwist]]; [SDshrinkSlider setFloatValue :[theTree SDshrink]]; [SDshrinkText setFloatValue :[theTree SDshrink]]; if (update) { [levelsSlider setIntValue :[theTree levels]]; [levelsText setIntValue :[theTree levels]]; [branchFactorSlider setIntValue :[theTree branchFactor]]; [branchFactorText setIntValue :[theTree branchFactor]]; [SDbranchFactorSlider setIntValue :[theTree SDbranchFactor]]; [SDbranchFactorText setIntValue :[theTree SDbranchFactor]]; [SDlevelsSlider setIntValue :[theTree SDlevels]]; [SDlevelsText setIntValue :[theTree SDlevels]]; dirty = 1; if (redraw_mode) { [theTree plantIn :self]; [self redrawNow :nil]; dirty = 0; } } return self; } #define ACTIVEBUTTONMASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK) - mouseDown :(NXEvent *)theEvent { int oldMask; NXPoint oldMouse, newMouse, dMouse; RtMatrix rmat, irmat; [theRotator setRotationAxis :N3D_ZAxis]; // 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; } - redrawNow :sender; { [self lockFocus]; [self setSurfaceTypeForAll :N3D_SmoothSolids chooseHider :YES]; [self display]; [self unlockFocus]; return self; } - redrawMode :sender; { int lastRedraw_mode = redraw_mode; redraw_mode = [sender selectedTag]? 0: 1; if (!(lastRedraw_mode && !redraw_mode)) { if (dirty) [theTree plantIn :self]; dirty = 0; [self redrawNow :nil]; } return self; } - randomMode :sender {[theTree randomMode :sender]; return self;} - specis :sender {[theTree specis :sender]; return self;} - (int)redraw_mode {return redraw_mode;} - 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 [theTree 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; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.