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;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.