/* * Draws the plant. */ void drawPlant(int i,float scale,float radscale,int string) { char *ptr = lsystem[string]; char ch[] = { '\0','\0' }; GLfloat c1[] = { 0.6549f,0.4901f,0.2392f }; /* light brown */ GLfloat c2[] = { 0.3607f,0.2510f,0.2000f }; /* dark brown */ GLfloat c3[] = { 0.1373f,0.5568f,0.1373f }; /* forest green */ if(i==0) return; PushMatrix(); while(*ptr != '\0') { switch(*ptr) { case 'F': Rotate(tilt/10000,0.0,0.0,1.0); /* tilt very very slightly */ LoadMatrix(); if(do_growth && floor(growth)==i) { draw_branch(LENGTH*scale*(growth-1),RADIUS*radscale,BASE_TRI,c1,c2); Translate(0.0,LENGTH*scale*(growth-1),0.0); } else { draw_branch(LENGTH*scale,RADIUS*radscale,BASE_TRI,c1,c2); Translate(0.0,LENGTH*scale,0.0); } break; case '[': PushMatrix(); break; case ']': PopMatrix(); break; case 'L': if(do_growth && floor(growth)==i) draw_leaf(4*(growth-1)*scale,1*(growth-1)*scale,25,c3); else draw_leaf(4*scale,1*scale,25,c3); break; case 'R': Rotate(yrotate,0.0,1.0,0.0); break; case 'T': Rotate(tilt,0.0,0.0,1.0); break; default: if(isdigit(*ptr)) { ch[0] = *ptr; drawPlant(i-1,scale*SCALE,radscale*RADSCALE,atoi(ch)); } break; } ptr++; } PopMatrix(); }
void fltr_herb_stems(texture *tx, void const * const fargs) { herb_leaves_filter_args *hlfargs = (herb_leaves_filter_args *) fargs; ptrdiff_t hash; int i = 0; float noise; int nstalks; float spread; leaf_filter_args lfargs; // stores individual leaf parameters curve c; // stores individual leaf shapes c.from.y = BLOCK_TEXTURE_SIZE; c.to.y = 0; c.from.z = 0; c.come_from.z = 0; c.go_towards.z = 0; c.to.z = 0; herb_setup(hlfargs, &hash, &noise, &nstalks, &spread, &lfargs); lfargs.shape = LS_LINEAR; float th_base = 0; float mid = (BLOCK_TEXTURE_SIZE / 2); for (i = 0; i < nstalks; ++i) { // generate x in [mid - spread, mid + spread] // for stems, we use the same top/bottom values so that they'll fit // together vertically. c.from.x = mid - spread; c.from.x += 2 * spread * ptrf(hash + i); c.to.x = c.from.x; hash = prng(hash + i + c.from.x); // pick the same starting angle that leaves use [-1, 1] noise = 1.0 - 2 * ptrf(hash); hash = prng(hash + i); th_base = hlfargs->angle * noise; // An extra hash to maintain stride with fltr_herb_leaves: hash = prng(hash + i); // stems use the same angle at the top and bottom so that they can stack. c.come_from.x = c.to.x - sinf(th_base) * hlfargs->length*hlfargs->shape; c.come_from.y = c.to.y + cosf(th_base) * hlfargs->length*hlfargs->shape; c.go_towards.x = c.from.x + sinf(th_base) * hlfargs->length*hlfargs->shape; c.go_towards.y = c.from.y - cosf(th_base) * hlfargs->length*hlfargs->shape; // pick a base width in [0.75, 1.25] noise = 0.75 + 0.5 * ptrf(hash); hash = prng(hash + i); lfargs.width = hlfargs->width * noise; // draw the leaf: draw_leaf(tx, &c, &lfargs); } }
void fltr_leaf(texture *tx, void const * const fargs) { leaf_filter_args *lfargs = (leaf_filter_args *) fargs; ptrdiff_t hash = prng(lfargs->seed); float noise = 0; float angle = 0, bend = 0; float mid = LEAF_TEXTURE_SIZE / 2.0; curve c; c.from.x = 0; c.from.y = 0; c.from.z = 0; c.go_towards.x = 0; c.go_towards.y = 0; c.go_towards.z = 0; c.come_from.x = 0; c.come_from.y = 0; c.come_from.z = 0; c.to.x = 0; c.to.y = 0; c.to.z = 0; tx_clear(tx); if (lfargs->type == LT_SIMPLE) { // pick an angle in [-1, 1] * lfargs->angle_var (0 will be straight down) noise = -1 + 2.0 * ptrf(prng(hash + lfargs->seed)); angle = lfargs->angle + lfargs->angle_var * noise; // the leaf starts opposite that angle: c.from.x = mid + (mid - 1) * sinf(angle + M_PI); c.from.y = mid + (mid - 1) * cosf(angle + M_PI); // its midpoint is in the direction of the given angle: c.go_towards.x = c.from.x + (lfargs->length / 2.0) * sinf(angle); c.go_towards.y = c.from.y + (lfargs->length / 2.0) * cosf(angle); // make sure we're still inside the texture: if (c.go_towards.x < 1) { c.go_towards.x = 1; } else if (c.go_towards.x > LEAF_TEXTURE_SIZE - 2) { c.go_towards.x = LEAF_TEXTURE_SIZE - 2; } // its endpoint bends: noise = 0.7 + 0.6 * ptrf((hash + 2)*noise); // [0.7, 1.3] bend = lfargs->bend * noise; if ((angle > 0 && angle < M_PI) || (angle < -M_PI) ) { bend = angle - bend; } else { bend = angle + bend; } c.to.x = c.go_towards.x + (lfargs->length / 2.0) * sinf(bend); c.to.y = c.go_towards.y + (lfargs->length / 2.0) * cosf(bend); // check bounds again: if (c.to.x < 1) { c.go_towards.x += (1 - c.to.x) / 2.0; c.to.x = 1; } else if (c.to.x > LEAF_TEXTURE_SIZE - 2) { c.go_towards.x -= (c.to.x - (LEAF_TEXTURE_SIZE - 2)) / 2.0; c.to.x = LEAF_TEXTURE_SIZE - 2; } // copy the go_towards point as the come_from point: vcopy_as(&c.come_from, &c.go_towards); // draw the leaf: draw_leaf(tx, &c, lfargs); } else if (lfargs->type == LT_TRIPARTITE) { // TODO: Tripartite leaves! } else if (lfargs->type == LT_NEEDLES) { // TODO: Needles! } #ifdef DEBUG else { fprintf(stderr, "Bad leaf filter type %d!\n", lfargs->type); } #endif }
void fltr_herb_leaves(texture *tx, void const * const fargs) { herb_leaves_filter_args *hlfargs = (herb_leaves_filter_args *) fargs; ptrdiff_t hash; int i = 0; float noise; int nstalks; float spread; leaf_filter_args lfargs; // stores individual leaf parameters curve c; // stores individual leaf shapes c.from.y = BLOCK_TEXTURE_SIZE; c.from.z = 0; c.come_from.z = 0; c.go_towards.z = 0; c.to.z = 0; herb_setup(hlfargs, &hash, &noise, &nstalks, &spread, &lfargs); lfargs.shape = LS_DELTOID; float th_base = 0, th_mid = 0; float mid = (BLOCK_TEXTURE_SIZE / 2); for (i = 0; i < nstalks; ++i) { // generate x in [mid - spread, mid + spread] c.from.x = mid - spread; c.from.x += 2 * spread * ptrf(hash + i); hash = prng(hash + i + c.from.x); // pick a starting angle in [-1, 1] noise = 1.0 - 2 * ptrf(hash); hash = prng(hash + i); th_base = hlfargs->angle * noise; // pick a bend angle in [0.6, 1.4] of the specified angle noise = 0.6 + 0.8 * ptrf(hash); hash = prng(hash + i); th_mid = hlfargs->bend * noise * th_base / hlfargs->angle; th_mid += th_base; // compute midpiont and endpoint c.go_towards.x = c.from.x + sinf(th_base) * hlfargs->length*hlfargs->shape; c.go_towards.y = c.from.y - cosf(th_base) * hlfargs->length*hlfargs->shape; c.to.x = c.go_towards.x + sinf(th_mid) * hlfargs->length*(1-hlfargs->shape); c.to.y = c.go_towards.y - cosf(th_mid) * hlfargs->length*(1-hlfargs->shape); // keep things in-bounds /* if (c.to.x < 1) { c.go_towards.x += (1 - c.to.x) / 2.0; c.to.x = 1; } else if (c.to.x > BLOCK_TEXTURE_SIZE - 2) { c.go_towards.x -= (c.to.x - (BLOCK_TEXTURE_SIZE - 2)) / 2.0; c.to.x = BLOCK_TEXTURE_SIZE - 2; } if (c.to.y < 1) { c.go_towards.y += (1 - c.to.y) / 2.0; c.to.y = 1; } // */ // Copy the come_from vector from the go_towards vector: vcopy_as(&c.come_from, &c.go_towards); /* DEBUG: printf("th_base: %.3f\n", th_base); printf("th_mid: %.3f\n", th_mid); printf("th_mid_atten: %.3f\n", th_base / hlfargs->angle); printf("th_mid_roll: %.3f\n", noise); printf("xy_mid: %.2f, %.2f\n", c.go_towards.x, c.go_towards.y); printf("xy_end: %.2f, %.2f\n", c.to.x, c.to.y); // */ // pick a base width in [0.75, 1.25] noise = 0.75 + 0.5 * ptrf(hash); hash = prng(hash + i); lfargs.width = hlfargs->width * noise; // draw the leaf: draw_leaf(tx, &c, &lfargs); } }
/** * Draws given node as a node in a tree - first draws element, * then calls the draw function of all children */ int draw_node(Control* node, Control* parent) { if (draw_children(node, NULL )) { return draw_leaf(node, parent); } return 0; }