texture *gen_aquatic_plant_texture(block b) { aquatic_plant_species *asp = get_aquatic_plant_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad aquatic plant block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_AQUATIC_PLANT_SEEDS: return gen_herbaceous_seeds_texture(&(asp->appearance)); case B_AQUATIC_PLANT_CORE: case B_AQUATIC_PLANT_ANCHORS: return gen_herbaceous_roots_texture(&(asp->appearance)); case B_AQUATIC_PLANT_SHOOTS: return gen_herbaceous_shoots_texture(&(asp->appearance)); case B_AQUATIC_PLANT_STEMS: return gen_herbaceous_stems_texture(&(asp->appearance)); case B_AQUATIC_PLANT_LEAVES_GROWN: return gen_herbaceous_leaves_texture(&(asp->appearance)); case B_AQUATIC_PLANT_LEAVES_BUDDING: return gen_herbaceous_budding_texture(&(asp->appearance)); case B_AQUATIC_PLANT_LEAVES_FLOWERING: return gen_herbaceous_flowering_texture(&(asp->appearance)); case B_AQUATIC_PLANT_LEAVES_FRUITING: return gen_herbaceous_fruiting_texture(&(asp->appearance)); } }
texture *gen_herb_texture(block b) { herb_species *hsp = get_herb_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad herb block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_HERB_SEEDS: return gen_herbaceous_seeds_texture(&(hsp->appearance)); case B_HERB_CORE: case B_HERB_ROOTS: return gen_herbaceous_roots_texture(&(hsp->appearance)); case B_HERB_SHOOTS: return gen_herbaceous_shoots_texture(&(hsp->appearance)); case B_HERB_STEMS: return gen_herbaceous_stems_texture(&(hsp->appearance)); case B_HERB_LEAVES: return gen_herbaceous_leaves_texture(&(hsp->appearance)); case B_HERB_BUDDING: return gen_herbaceous_budding_texture(&(hsp->appearance)); case B_HERB_FLOWERING: return gen_herbaceous_flowering_texture(&(hsp->appearance)); case B_HERB_FRUITING: return gen_herbaceous_fruiting_texture(&(hsp->appearance)); } }
texture *gen_vine_texture(block b) { vine_species *vsp = get_vine_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad vine block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_VINE_SEEDS: return gen_bush_seeds_texture(&(vsp->appearance)); case B_VINE_CORE: case B_VINE_ROOTS: return gen_bush_roots_texture(&(vsp->appearance)); case B_VINE_SHOOTS: return gen_bush_shoots_texture(&(vsp->appearance)); case B_VINE_SPROUTING: return gen_bush_sprouting_branches_texture(&(vsp->appearance)); case B_VINE_GROWN: return gen_bush_branches_texture(&(vsp->appearance)); case B_VINE_BUDDING: return gen_bush_budding_branches_texture(&(vsp->appearance)); case B_VINE_FLOWERING: return gen_bush_flowering_branches_texture(&(vsp->appearance)); case B_VINE_FRUITING: return gen_bush_fruiting_branches_texture(&(vsp->appearance)); case B_VINE_SHEDDING: return gen_bush_shedding_branches_texture(&(vsp->appearance)); case B_VINE_DORMANT: return gen_bush_dormant_branches_texture(&(vsp->appearance)); } }
texture *gen_tree_texture(block b) { tree_species *tsp = get_tree_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad tree block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_TREE_SEEDS: return gen_tree_seeds_texture(&(tsp->appearance)); case B_TREE_ROOTS: return gen_tree_roots_texture(&(tsp->appearance)); case B_TREE_CORE: case B_TREE_THICK_ROOTS: return gen_tree_thick_roots_texture(&(tsp->appearance)); case B_TREE_HEART_CORE: case B_TREE_HEART_ROOTS: return gen_tree_heart_roots_texture(&(tsp->appearance)); case B_TREE_SHOOTS: return gen_tree_shoots_texture(&(tsp->appearance)); case B_TREE_TRUNK: return gen_tree_trunk_texture(&(tsp->appearance)); case B_TREE_BRANCHES_SPROUTING: return gen_tree_sprouting_branches_texture(&(tsp->appearance)); case B_TREE_BRANCHES_GROWN: return gen_tree_branches_texture(&(tsp->appearance)); case B_TREE_BRANCHES_BUDDING: return gen_tree_budding_branches_texture(&(tsp->appearance)); case B_TREE_BRANCHES_FLOWERING: return gen_tree_flowering_branches_texture(&(tsp->appearance)); case B_TREE_BRANCHES_FRUITING: return gen_tree_fruiting_branches_texture(&(tsp->appearance)); case B_TREE_BRANCHES_SHEDDING: return gen_tree_shedding_branches_texture(&(tsp->appearance)); case B_TREE_BARE_BRANCHES: case B_TREE_BRANCHES_DORMANT: return gen_tree_dormant_branches_texture(&(tsp->appearance)); case B_TREE_LEAVES_SPROUTING: return gen_tree_sprouting_leaves_texture(&(tsp->appearance)); case B_TREE_LEAVES_GROWN: return gen_tree_leaves_texture(&(tsp->appearance)); case B_TREE_LEAVES_BUDDING: return gen_tree_budding_leaves_texture(&(tsp->appearance)); case B_TREE_LEAVES_FLOWERING: return gen_tree_flowering_leaves_texture(&(tsp->appearance)); case B_TREE_LEAVES_FRUITING: return gen_tree_fruiting_leaves_texture(&(tsp->appearance)); case B_TREE_LEAVES_SHEDDING: return gen_tree_shedding_leaves_texture(&(tsp->appearance)); case B_TREE_LEAVES_DORMANT: return gen_tree_dormant_leaves_texture(&(tsp->appearance)); } }
texture *gen_mushroom_texture(block b) { switch (b_id(b)) { default: #ifdef DEBUG printf("Bad mushroom block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_MUSHROOM_SPORES: return NULL; case B_MUSHROOM_SHOOTS: return NULL; case B_MUSHROOM_GROWN: return NULL; } }
float species_compatability(frequent_species fqsp, block substrate) { // TODO: This function! if (b_id(substrate) == B_STONE) { return 0.0; } return 1.0; }
texture *gen_shrub_texture(block b) { shrub_species *ssp = get_shrub_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad shrub block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_SHRUB_SEEDS: return gen_bush_seeds_texture(&(ssp->appearance)); case B_SHRUB_ROOTS: return gen_bush_roots_texture(&(ssp->appearance)); case B_SHRUB_CORE: case B_SHRUB_THICK_ROOTS: return gen_bush_thick_roots_texture(&(ssp->appearance)); case B_SHRUB_SHOOTS: return gen_bush_shoots_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_SPROUTING: return gen_bush_sprouting_branches_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_GROWN: return gen_bush_branches_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_BUDDING: return gen_bush_budding_branches_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_FLOWERING: return gen_bush_flowering_branches_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_FRUITING: return gen_bush_fruiting_branches_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_SHEDDING: return gen_bush_shedding_branches_texture(&(ssp->appearance)); case B_SHRUB_BRANCHES_DORMANT: return gen_bush_dormant_branches_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_SPROUTING: return gen_bush_sprouting_leaves_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_GROWN: return gen_bush_leaves_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_BUDDING: return gen_bush_budding_leaves_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_FLOWERING: return gen_bush_flowering_leaves_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_FRUITING: return gen_bush_fruiting_leaves_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_SHEDDING: return gen_bush_shedding_leaves_texture(&(ssp->appearance)); case B_SHRUB_LEAVES_DORMANT: return gen_bush_dormant_leaves_texture(&(ssp->appearance)); } }
texture *gen_coral_texture(block b) { coral_species *csp = get_coral_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad aquatic plant block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_YOUNG_CORAL: return gen_young_coral_texture(&(csp->appearance)); case B_CORAL_CORE: case B_CORAL_BODY: return gen_coral_body_texture(&(csp->appearance)); case B_CORAL_FROND: return gen_coral_frond_texture(&(csp->appearance)); } }
texture *gen_moss_texture(block b) { moss_species *msp = get_moss_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad moss block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_MOSS_SPORES: return gen_herbaceous_seeds_texture(&(msp->appearance)); case B_MOSS_SHOOTS: return gen_herbaceous_shoots_texture(&(msp->appearance)); case B_MOSS_GROWN: return gen_herbaceous_leaves_texture(&(msp->appearance)); case B_MOSS_FLOWERING: return gen_herbaceous_flowering_texture(&(msp->appearance)); case B_MOSS_FRUITING: return gen_herbaceous_fruiting_texture(&(msp->appearance)); } }
void BlenderSession::builtin_image_info(const string &builtin_name, void *builtin_data, bool &is_float, int &width, int &height, int &depth, int &channels) { /* empty image */ is_float = false; width = 0; height = 0; depth = 0; channels = 0; if(!builtin_data) return; /* recover ID pointer */ PointerRNA ptr; RNA_id_pointer_create((ID*)builtin_data, &ptr); BL::ID b_id(ptr); if(b_id.is_a(&RNA_Image)) { /* image data */ BL::Image b_image(b_id); is_float = b_image.is_float(); width = b_image.size()[0]; height = b_image.size()[1]; depth = 1; channels = b_image.channels(); } else if(b_id.is_a(&RNA_Object)) { /* smoke volume data */ BL::Object b_ob(b_id); BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); if(!b_domain) return; if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) || builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) channels = 1; else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) channels = 4; else return; int3 resolution = get_int3(b_domain.domain_resolution()); int amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1; width = resolution.x * amplify; height = resolution.y * amplify; depth = resolution.z * amplify; is_float = true; } }
texture *gen_giant_mushroom_texture(block b) { switch (b_id(b)) { default: #ifdef DEBUG printf("Bad giant mushroom block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_GIANT_MUSHROOM_SPORES: return NULL; case B_GIANT_MUSHROOM_CORE: return NULL; case B_GIANT_MUSHROOM_MYCELIUM: return NULL; case B_GIANT_MUSHROOM_SPROUT: return NULL; case B_GIANT_MUSHROOM_STALK: return NULL; case B_GIANT_MUSHROOM_CAP: return NULL; } }
ptrdiff_t get_species_growth_strength(block b) { block id = b_id(b); growth_properties *grp = get_growth_properties(b); if (id == B_VOID) { return BIO_GS_ALWAYS_GROW; } else if (id == B_AIR || id == B_ETHER) { return BIO_GS_PRIORITY_GROW; } else if (grp == NULL) { // A non-air non-water non-plant block: can't grow here. return BIO_GS_CANT_GROW; } return grp->growth_strength; }
texture *gen_aquatic_grass_texture(block b) { aquatic_grass_species *asp = get_aquatic_grass_species(b_species(b)); switch (b_id(b)) { default: #ifdef DEBUG printf("Bad aquatic grass block type during txgen: %d\n", b_id(b)); #endif return NULL; case B_AQUATIC_GRASS_SEEDS: return gen_herbaceous_seeds_texture(&(asp->appearance)); case B_AQUATIC_GRASS_ROOTS: return gen_herbaceous_roots_texture(&(asp->appearance)); case B_AQUATIC_GRASS_SHOOTS: return gen_herbaceous_shoots_texture(&(asp->appearance)); case B_AQUATIC_GRASS_GROWN: return gen_herbaceous_leaves_texture(&(asp->appearance)); case B_AQUATIC_GRASS_BUDDING: return gen_herbaceous_budding_texture(&(asp->appearance)); case B_AQUATIC_GRASS_FLOWERING: return gen_herbaceous_flowering_texture(&(asp->appearance)); case B_AQUATIC_GRASS_FRUITING: return gen_herbaceous_fruiting_texture(&(asp->appearance)); } }
void add_biology(chunk *c) { world_map_pos wmpos; world_region *wr, *wr_second; float strbest, strsecond; world_region *wr_neighborhood[9]; biome *local_biome; list *sp_list; frequent_species fqsp; chunk_neighborhood ch_nbh; cell_neighborhood cl_nbh; cell* cl; block_index idx; block substrate; global_pos glpos; ptrdiff_t seed_hash = prng(chunk_hash(c) + 616485); ptrdiff_t spacing_hash = prng(THE_WORLD->seed + 44544); if (c->chunk_flags & CF_HAS_BIOLOGY) { return; // Already has biology } fill_chunk_neighborhood(&(c->glcpos), &ch_nbh); if (ch_nbh.members[0] == NULL) { return; // Return without setting the CF_HAS_BIOLOGY flag. } // Look up the local biomes: glcpos__wmpos(&(c->glcpos), &wmpos); // TODO: Avoid using THE_WORLD here? wr = get_world_region(THE_WORLD, &wmpos); if (wr == NULL) { // TODO: Go farther here? return; // outside the world map: no biology } get_world_neighborhood_small(THE_WORLD, &wmpos, wr_neighborhood); // Use the center of our chunk to compute region contenders: idx.xyz.x = CHUNK_SIZE / 2; idx.xyz.y = CHUNK_SIZE / 2; idx.xyz.z = CHUNK_SIZE / 2; idx.xyz.w = 0; cidx__glpos(c, &idx, &glpos); compute_region_contenders( THE_WORLD, wr_neighborhood, &glpos, 1232331, &wr, &wr_second, &strbest, &strsecond ); // Mix biomes for this chunk: local_biome = create_merged_biome( wr, wr_second, strbest, strsecond ); // Add seeds: idx.xyz.w = 0; for (idx.xyz.x = 0; idx.xyz.x < CHUNK_SIZE; ++idx.xyz.x) { for (idx.xyz.y = 0; idx.xyz.y < CHUNK_SIZE; ++idx.xyz.y) { for (idx.xyz.z = 0; idx.xyz.z < CHUNK_SIZE; ++idx.xyz.z) { // Get global cell position for hashing: cidx__glpos(c, &idx, &glpos); // TODO: optimize this within a loop... fill_cell_neighborhood_exact(idx, &ch_nbh, &cl_nbh); cl = cl_nbh.members[NBH_CENTER]; // Array is in xyz order so up/down is +/- 1, north/south is +/- 3, and // east/west is +/- 9. // If our secondary is empty we can put a seed here: figure out what // distribution to draw from. sp_list = NULL; if (b_is_void(cl->blocks[1])) { if (b_id(cl->blocks[0]) == B_AIR) { // Ephemeral species seeds settle in the air directly on top of // dirt/sand/mud/etc. substrate = cl_nbh.members[NBH_CENTER - NBH_DIR_UD]->blocks[0]; if (b_is_natural_terrain(substrate)) { sp_list = local_biome->ephemeral_terrestrial_flora; } } else if (b_id(cl->blocks[0]) == B_WATER) { // Aquatic ephemeral species start in water above dirt/sand/mud/etc. substrate = cl_nbh.members[NBH_CENTER - NBH_DIR_UD]->blocks[0]; if (b_is_natural_terrain(substrate)) { sp_list = local_biome->ephemeral_aquatic_flora; } } else if (b_is_natural_terrain(cl->blocks[0])) { substrate = cl->blocks[0]; if ( b_id(cl_nbh.members[NBH_CENTER + NBH_DIR_UD]->blocks[0]) == B_AIR ) { // Most terrestrial species sprout in the ground with air above. // TODO: Subterranean species! // Select between spacings: if (wide_spacing_hit(glpos, spacing_hash)) { sp_list = local_biome->wide_spaced_terrestrial_flora; } else if (medium_spacing_hit(glpos, spacing_hash)) { sp_list = local_biome->medium_spaced_terrestrial_flora; } else if (close_spacing_hit(glpos, spacing_hash)) { sp_list = local_biome->close_spaced_terrestrial_flora; } else { sp_list = local_biome->ubiquitous_terrestrial_flora; } } else if ( b_id(cl_nbh.members[NBH_CENTER + NBH_DIR_UD]->blocks[0]) ==B_WATER ) { // Aquatic plants sprout from seeds in terrain below water. // Select between spacings: if (wide_spacing_hit(glpos, spacing_hash)) { sp_list = local_biome->wide_spaced_aquatic_flora; } else if (medium_spacing_hit(glpos, spacing_hash)) { sp_list = local_biome->medium_spaced_aquatic_flora; } else if (close_spacing_hit(glpos, spacing_hash)) { sp_list = local_biome->close_spaced_aquatic_flora; } else { sp_list = local_biome->ubiquitous_aquatic_flora; } } else if ( b_id(cl_nbh.members[NBH_CENTER - NBH_DIR_UD]->blocks[0]) == B_AIR ) { // Some plants can also grow down into air from ceilings. sp_list = local_biome->hanging_terrestrial_flora; } // TODO: Should things grow in underwater ceilings? } // Now we generate a seed from the species list we decided on: if (sp_list != NULL) { fqsp = pick_appropriate_frequent_species( sp_list, substrate, seed_hash ); if (frequent_species_species_type(fqsp) != SPT_NO_SPECIES) { cl->blocks[1] = b_make_species( seed_block_type(frequent_species_species_type(fqsp)), frequent_species_species(fqsp) ); // TODO: Real sprout timers... gri_set_sprout_timer(&(cl->blocks[1]), 1); seed_hash = prng( idx.xyz.x + idx.xyz.y + glpos.z + prng(seed_hash + glpos.x + glpos.y + idx.xyz.z) ); } } } } } } // Clean up the local biome info now that we're done with it: cleanup_biome(local_biome); // Grow plants a bit: // TODO: How many cycles to use? #ifdef DEBUG if (!grow_plants(c, 2)) { // At this point if growth fails (it really shouldn't) the best we can do // is emit a warning... fprintf( stderr, "WARNING: Growth failed after adding seeds during biology generation.\n" ); } #else grow_plants(c, 2); #endif // Set the CF_HAS_BIOLOGY flag for this chunk: c->chunk_flags |= CF_HAS_BIOLOGY; }
bool BlenderSession::builtin_image_float_pixels(const string &builtin_name, void *builtin_data, float *pixels) { if(!builtin_data) return false; PointerRNA ptr; RNA_id_pointer_create((ID*)builtin_data, &ptr); BL::ID b_id(ptr); if(b_id.is_a(&RNA_Image)) { /* image data */ BL::Image b_image(b_id); int frame = builtin_image_frame(builtin_name); int width = b_image.size()[0]; int height = b_image.size()[1]; int channels = b_image.channels(); float *image_pixels; image_pixels = image_get_float_pixels_for_frame(b_image, frame); if(image_pixels) { memcpy(pixels, image_pixels, width * height * channels * sizeof(float)); MEM_freeN(image_pixels); } else { if(channels == 1) { memset(pixels, 0, width * height * sizeof(float)); } else { float *fp = pixels; for(int i = 0; i < width * height; i++, fp += channels) { fp[0] = 1.0f; fp[1] = 0.0f; fp[2] = 1.0f; if(channels == 4) fp[3] = 1.0f; } } } return true; } else if(b_id.is_a(&RNA_Object)) { /* smoke volume data */ BL::Object b_ob(b_id); BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob); if(!b_domain) return false; int3 resolution = get_int3(b_domain.domain_resolution()); int length, amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1; int width = resolution.x * amplify; int height = resolution.y * amplify; int depth = resolution.z * amplify; if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY)) { SmokeDomainSettings_density_grid_get_length(&b_domain.ptr, &length); if(length == width*height*depth) { SmokeDomainSettings_density_grid_get(&b_domain.ptr, pixels); return true; } } else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME)) { /* this is in range 0..1, and interpreted by the OpenGL smoke viewer * as 1500..3000 K with the first part faded to zero density */ SmokeDomainSettings_flame_grid_get_length(&b_domain.ptr, &length); if(length == width*height*depth) { SmokeDomainSettings_flame_grid_get(&b_domain.ptr, pixels); return true; } } else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) { /* the RGB is "premultiplied" by density for better interpolation results */ SmokeDomainSettings_color_grid_get_length(&b_domain.ptr, &length); if(length == width*height*depth*4) { SmokeDomainSettings_color_grid_get(&b_domain.ptr, pixels); return true; } } fprintf(stderr, "Cycles error: unexpected smoke volume resolution, skipping\n"); } return false; }
texture* gen_block_texture(block b) { char filename[1024]; block id = b_id(b); if (b_species(b) != 0) { switch (id) { default: // Fall out to the file base case below break; case B_DIRT: return gen_dirt_texture(b_species(b)); case B_MUD: return gen_mud_texture(b_species(b)); case B_SAND: return gen_sand_texture(b_species(b)); case B_CLAY: return gen_clay_texture(b_species(b)); case B_STONE: return gen_stone_texture(b_species(b)); case B_MUSHROOM_SPORES: case B_MUSHROOM_SHOOTS: case B_MUSHROOM_GROWN: return gen_mushroom_texture(b); case B_GIANT_MUSHROOM_SPORES: case B_GIANT_MUSHROOM_CORE: case B_GIANT_MUSHROOM_MYCELIUM: case B_GIANT_MUSHROOM_SPROUT: case B_GIANT_MUSHROOM_STALK: case B_GIANT_MUSHROOM_CAP: return gen_giant_mushroom_texture(b); case B_MOSS_SPORES: case B_MOSS_SHOOTS: case B_MOSS_GROWN: case B_MOSS_FLOWERING: case B_MOSS_FRUITING: return gen_moss_texture(b); case B_GRASS_SEEDS: case B_GRASS_ROOTS: case B_GRASS_SHOOTS: case B_GRASS_GROWN: case B_GRASS_BUDDING: case B_GRASS_FLOWERING: case B_GRASS_FRUITING: return gen_grass_texture(b); case B_VINE_SEEDS: case B_VINE_CORE: case B_VINE_ROOTS: case B_VINE_SHOOTS: case B_VINE_SPROUTING: case B_VINE_GROWN: case B_VINE_BUDDING: case B_VINE_FLOWERING: case B_VINE_FRUITING: case B_VINE_SHEDDING: case B_VINE_DORMANT: return gen_vine_texture(b); case B_HERB_SEEDS: case B_HERB_CORE: case B_HERB_ROOTS: case B_HERB_SHOOTS: case B_HERB_STEMS: case B_HERB_LEAVES: case B_HERB_BUDDING: case B_HERB_FLOWERING: case B_HERB_FRUITING: return gen_herb_texture(b); case B_BUSH_SEEDS: case B_BUSH_CORE: case B_BUSH_ROOTS: case B_BUSH_SHOOTS: case B_BUSH_BRANCHES_SPROUTING: case B_BUSH_BRANCHES_GROWN: case B_BUSH_BRANCHES_BUDDING: case B_BUSH_BRANCHES_FLOWERING: case B_BUSH_BRANCHES_FRUITING: case B_BUSH_BRANCHES_SHEDDING: case B_BUSH_BRANCHES_DORMANT: case B_BUSH_LEAVES_SPROUTING: case B_BUSH_LEAVES_GROWN: case B_BUSH_LEAVES_BUDDING: case B_BUSH_LEAVES_FLOWERING: case B_BUSH_LEAVES_FRUITING: case B_BUSH_LEAVES_SHEDDING: case B_BUSH_LEAVES_DORMANT: return gen_bush_texture(b); case B_SHRUB_SEEDS: case B_SHRUB_CORE: case B_SHRUB_ROOTS: case B_SHRUB_THICK_ROOTS: case B_SHRUB_SHOOTS: case B_SHRUB_BRANCHES_SPROUTING: case B_SHRUB_BRANCHES_GROWN: case B_SHRUB_BRANCHES_BUDDING: case B_SHRUB_BRANCHES_FLOWERING: case B_SHRUB_BRANCHES_FRUITING: case B_SHRUB_BRANCHES_SHEDDING: case B_SHRUB_BRANCHES_DORMANT: case B_SHRUB_LEAVES_SPROUTING: case B_SHRUB_LEAVES_GROWN: case B_SHRUB_LEAVES_BUDDING: case B_SHRUB_LEAVES_FLOWERING: case B_SHRUB_LEAVES_FRUITING: case B_SHRUB_LEAVES_SHEDDING: case B_SHRUB_LEAVES_DORMANT: return gen_shrub_texture(b); case B_TREE_SEEDS: case B_TREE_CORE: case B_TREE_HEART_CORE: case B_TREE_ROOTS: case B_TREE_THICK_ROOTS: case B_TREE_HEART_ROOTS: case B_TREE_SHOOTS: case B_TREE_TRUNK: case B_TREE_BARE_BRANCHES: case B_TREE_BRANCHES_SPROUTING: case B_TREE_BRANCHES_GROWN: case B_TREE_BRANCHES_BUDDING: case B_TREE_BRANCHES_FLOWERING: case B_TREE_BRANCHES_FRUITING: case B_TREE_BRANCHES_SHEDDING: case B_TREE_BRANCHES_DORMANT: case B_TREE_LEAVES_SPROUTING: case B_TREE_LEAVES_GROWN: case B_TREE_LEAVES_BUDDING: case B_TREE_LEAVES_FLOWERING: case B_TREE_LEAVES_FRUITING: case B_TREE_LEAVES_SHEDDING: case B_TREE_LEAVES_DORMANT: return gen_tree_texture(b); case B_AQUATIC_GRASS_SEEDS: case B_AQUATIC_GRASS_ROOTS: case B_AQUATIC_GRASS_SHOOTS: case B_AQUATIC_GRASS_GROWN: case B_AQUATIC_GRASS_FLOWERING: case B_AQUATIC_GRASS_FRUITING: return gen_aquatic_grass_texture(b); case B_AQUATIC_PLANT_SEEDS: case B_AQUATIC_PLANT_CORE: case B_AQUATIC_PLANT_ANCHORS: case B_AQUATIC_PLANT_SHOOTS: case B_AQUATIC_PLANT_STEMS: case B_AQUATIC_PLANT_LEAVES_GROWN: case B_AQUATIC_PLANT_LEAVES_FLOWERING: case B_AQUATIC_PLANT_LEAVES_FRUITING: return gen_aquatic_plant_texture(b); case B_YOUNG_CORAL: case B_CORAL_CORE: case B_CORAL_BODY: case B_CORAL_FROND: return gen_coral_texture(b); // TODO: More block types here!! } } // Base case if species is 0 or block type isn't gen-able: look for a file. // TODO: switch to using string.h... sprintf( filename, "%s/%s.png", BLOCK_TEXTURE_DIR, BLOCK_NAMES[id] ); if (access(filename, R_OK) != -1) { return load_texture_from_png(filename); } // Give up return NULL; }