This is Tree.m in view mode; [Download] [Up]
// Tree.m -- a tree object, subclass and formed of Branches #import <appkit/appkit.h> #import "ForestCamera.h" #import "Tree.h" extern long random(); id globalShader; @implementation Tree - init { [super init]; random_mode = 1; [self inzVars :0]; return self; } // access generation parmaeters - (double) angle {return angle;} - (double) angle :(double)angleArg {return angle = angleArg;} - (double) twist {return twist;} - (double) twist :(double)twistArg {return twist = twistArg;} - (double) shrink {return shrink;} - (double) shrink :(double)shrinkArg {return shrink = shrinkArg;} - (int) branchFactor {return branchFactor;} - (int) branchFactor :(int)branchFactorArg {return branchFactor=branchFactorArg;} - (int) levels {return levels;} - (int) levels :(int)levelsArg {return levels = levelsArg;} - (double) SDangle {return SDangle;} - (double) SDangle :(double)SDangleArg {return SDangle = SDangleArg;} - (double) SDtwist {return SDtwist;} - (double) SDtwist :(double)SDtwistArg {return SDtwist = SDtwistArg;} - (double) SDshrink {return SDshrink;} - (double) SDshrink :(double)SDshrinkArg{return SDshrink = SDshrinkArg;} - (double) SDbranchFactor {return SDbranchFactor;} - (double) SDbranchFactor :(double)SDbranchFactorArg {return SDbranchFactor = SDbranchFactorArg;} - (double) SDlevels {return SDlevels;} - (double) SDlevels :(double)SDlevelsArg{return SDlevels = SDlevelsArg;} - plantIn :(ForestCamera *)forestArg { RtBound box; RtPoint eyePt, viewPt; float rollAng, dist, d, size, x,y,z; int i; Branch *trunk = [[Branch alloc] init]; id oldWorldShape = [forestArg setWorldShape :self]; srandom(lastSeed = random_mode? time(0): lastSeed); if (oldWorldShape == self) oldWorldShape = descendant; [oldWorldShape freeAll]; // free any old (parts of) trees forest = forestArg; [trunk setShader :globalShader]; [trunk setBoundingBox :0 :0 :0 :0 :0 :1]; //[[self descendant] free]; [self linkDescendant :trunk]; [trunk tree :self]; [trunk addBranches :1 inTree :self]; [self getBoundingBox :&box]; // Position viewpoint at center of box: [forest getEyeAt :&eyePt toward :&viewPt roll :&rollAng]; viewPt[0] = x = (box[0]+box[1])*0.5; viewPt[1] = y = (box[2]+box[3])*0.5; viewPt[2] = z = (box[4]+box[5])*0.5; [forest setEyeAt :eyePt toward :viewPt roll :-90.0]; // Position the camera at a distance so the tree fills screen: for (i=0, size=0.01; i<6; i+=2) /* compute the largest dimension of the */ { d = box[i] - box[i+1]; /* surrounding box.*/ if (d < 0) d = -d; if (d > size) size = d; } dist = sqrt((x-=eyePt[0])*x + (y-=eyePt[1])*y + (z-=eyePt[2])*z); [forest moveEyeBy :0.0 :0.0 :2.2*size - dist]; return self; } typedef struct { int levels, branchFactor; float angle, twist, shrink; int SDbranchFactor, SDlevels; float SDangle, SDtwist,SDshrink; } treeType; #define nTrees 6 treeType trees[nTrees] = { {4, 2, 45.0, 90.0, 0.70}, // inz {5, 2, 20.0, 73.0, 0.83}, // elm {3, 5, 35.0, 73.0, 0.75}, // queen annes lace {7, 2, 23.0, 0.0, 0.80}, // fan {7, 2, 90.0, 90.0, 0.67}, // tv antenna {20, 1, 20.7, 0.7, 0.85}, // hook }; - specis :sender { [self inzVars :[sender selectedTag]]; [self plantIn :forest]; [forest newParameter :nil]; [forest redrawNow :nil]; return self; } - (int) inzVars :(int) index { treeType *nt = &trees[index]; if (index < 0 || index >= nTrees) return 0; angle = nt->angle; twist = nt->twist; shrink = nt->shrink; branchFactor = nt->branchFactor; levels = nt->levels; SDangle = nt->SDangle; SDtwist = nt->SDtwist; SDshrink = nt->SDshrink; SDbranchFactor = nt->SDbranchFactor; SDlevels = nt->SDlevels; return 1; } - randomMode :sender; { int lastRandom_mode = random_mode; random_mode = [sender selectedTag]; if ((lastRandom_mode && random_mode) || (!lastRandom_mode && !random_mode)) { if ([forest redraw_mode]) { [self plantIn :forest]; [forest redrawNow :nil]; } } return self; } - (float) randVal :(treeParameter) param; { float r = ((random()&0xfffffff)/(float)0x8000000 - 1.0), val=0, sd=0; switch (param) { case ANGLE: return (angle + r * SDangle); case TWIST: return (twist + r * SDtwist); case SHRINK: return (shrink + r * SDshrink); case BRANCHFACTOR: return (branchFactor + r * SDbranchFactor); case LEVELS: return (levels + r * SDlevels); } return 0.0; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.