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.