1.3.49
 
Loading...
Searching...
No Matches
tomato.cpp
1#include "CanopyGenerator.h"
2
3using namespace helios;
4using namespace std;
5
6std::vector<std::vector<uint>> tomatoCluster(const vec3 center, const TomatoParameters &params, Context *context) {
7
8 std::vector<std::vector<uint>> U;
9
10 U.push_back(context->addSphere(params.fruit_subdivisions, center, params.fruit_radius, params.fruit_color));
11
12 float azimuth = 2.f * PI_F * context->randu();
13
14 if (context->randu() < 0.75) {
15
16 U.push_back(context->addSphere(params.fruit_subdivisions, center + sphere2cart(make_SphericalCoord(1.5 * params.fruit_radius, 0, azimuth)), params.fruit_radius, params.fruit_color));
17 }
18
19 if (context->randu() < 0.5) {
20
21 U.push_back(context->addSphere(params.fruit_subdivisions, center + sphere2cart(make_SphericalCoord(1.5 * params.fruit_radius, 0, azimuth + 0.5 * PI_F)), params.fruit_radius, params.fruit_color));
22 }
23
24 return U;
25}
26
27std::vector<uint> lateralLeaves(const float bfrac, const TomatoParameters params, const float leaf_scale, const std::vector<vec3> nodes, std::string texture, Context *context) {
28
29 float downangle = 0.1 * PI_F;
30
31 vec3 r0 = interpolateTube(nodes, bfrac);
32 vec3 r1 = interpolateTube(nodes, 1.01 * bfrac);
33 vec3 dr = r1 - r0;
34
35 float elevation = cart2sphere(dr).elevation;
36 float azimuth = cart2sphere(dr).azimuth;
37
38 std::vector<uint> U1, U2;
39
40 U1 = context->addTile(make_vec3(0, 0, 0), make_vec2(leaf_scale, leaf_scale * 0.5), make_SphericalCoord(0, PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str());
41
42 context->rotatePrimitive(U1, elevation, "x");
43 context->rotatePrimitive(U1, downangle, "y");
44 context->rotatePrimitive(U1, -azimuth, "z");
45
46 context->translatePrimitive(U1, r0 + 0.6 * leaf_scale * make_vec3(cosf(-azimuth), sinf(-azimuth), -0.5 * sinf(downangle)));
47
48 U2 = context->addTile(make_vec3(0, 0, 0), make_vec2(leaf_scale, leaf_scale * 0.5), make_SphericalCoord(0, PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str());
49
50 context->rotatePrimitive(U2, elevation, "x");
51 context->rotatePrimitive(U2, downangle, "y");
52 context->rotatePrimitive(U2, -azimuth + PI_F, "z");
53
54 context->translatePrimitive(U2, r0 - 0.6 * leaf_scale * make_vec3(cosf(-azimuth), sinf(-azimuth), 0.5 * sinf(downangle)));
55
56 U1.insert(U1.end(), U2.begin(), U2.end());
57
58 return U1;
59}
60
61void tomatoShoot(const TomatoParameters params, const helios::vec3 base_position, const helios::vec3 base_direction, const float length, const float bend_angle, std::vector<std::vector<uint>> &leaf_UUIDs, std::vector<uint> &branch_UUIDs,
62 std::vector<std::vector<std::vector<uint>>> &fruit_UUIDs, Context *context) {
63
64 std::vector<vec3> nodes;
65 std::vector<float> radius;
66 std::vector<RGBcolor> color;
67
68 int node_count = round(2 * length * params.shoot_subdivisions);
69
70 vec3 dir = base_direction;
71 dir.normalize();
72
73 SphericalCoord base_angle = cart2sphere(dir);
74
75 float shoot_radius = 0.005;
76
77 nodes.push_back(base_position);
78 radius.push_back(shoot_radius);
79 color.push_back(params.shoot_color);
80
81 float theta = base_angle.elevation;
82 for (int i = 1; i < node_count; i++) {
83
84 float vfrac = float(i) / float(node_count - 1);
85
86 radius.push_back(shoot_radius * params.plant_height * (1.f - 0.8 * vfrac));
87
88 vec3 position = nodes.back() + length / float(node_count - 1) * (sphere2cart(make_SphericalCoord(1, theta, base_angle.azimuth)));
89
90 theta -= bend_angle / float(node_count - 1);
91
92 nodes.push_back(position);
93
94 color.push_back(params.shoot_color);
95 }
96
97 std::vector<uint> U = context->addTube(params.shoot_subdivisions, nodes, radius, color);
98 branch_UUIDs.insert(branch_UUIDs.end(), U.begin(), U.end());
99
100 // tip leaf
101 U = context->addTile(make_vec3(0, 0, 0), make_vec2(params.leaf_length, params.leaf_length * 0.5), make_SphericalCoord(0, PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str());
102
103 context->rotatePrimitive(U, -theta, "y");
104 context->rotatePrimitive(U, -base_angle.azimuth + 0.5 * PI_F, "z");
105
106 context->translatePrimitive(U, nodes.back() + sphere2cart(make_SphericalCoord(0.45 * params.leaf_length, theta, base_angle.azimuth)));
107
108 leaf_UUIDs.push_back(U);
109
110 // primary lateral leaves
111
112 leaf_UUIDs.push_back(lateralLeaves(0.9, params, 0.3 * params.leaf_length, nodes, params.leaf_texture_file, context));
113
114 leaf_UUIDs.push_back(lateralLeaves(0.8, params, 0.85 * params.leaf_length, nodes, params.leaf_texture_file, context));
115
116 leaf_UUIDs.push_back(lateralLeaves(0.6, params, 0.3 * params.leaf_length, nodes, params.leaf_texture_file, context));
117
118 leaf_UUIDs.push_back(lateralLeaves(0.45, params, 0.75 * params.leaf_length, nodes, params.leaf_texture_file, context));
119
120 // fruit
121
122 if (params.fruit_radius > 0 && context->randu() < 0.66) {
123
124 vec3 cluster_position = interpolateTube(nodes, 0.25) - make_vec3(0, 0, 4 * params.fruit_radius);
125
126 fruit_UUIDs.push_back(tomatoCluster(cluster_position, params, context));
127 }
128}
129
130uint CanopyGenerator::tomato(const TomatoParameters &params, const vec3 &origin) {
131
132 std::vector<std::vector<uint>> leaf_UUIDs;
133 std::vector<uint> branch_UUIDs;
134 std::vector<std::vector<std::vector<uint>>> fruit_UUIDs;
135
136 // main stem
137
138 std::vector<vec3> nodes;
139 std::vector<float> radius;
140 std::vector<RGBcolor> color;
141
142 int node_count = round(2 * params.plant_height * params.shoot_subdivisions);
143
144 float stem_radius = 0.02;
145
146 nodes.push_back(origin);
147 radius.push_back(stem_radius);
148 color.push_back(params.shoot_color);
149
150 for (int i = 1; i < node_count; i++) {
151
152 float vfrac = float(i) / float(node_count - 1);
153
154 radius.push_back(stem_radius * params.plant_height * (1.f - 0.9 * vfrac));
155
156 vec3 position = nodes.back() + params.plant_height / float(node_count - 1) * make_vec3(0, 0, 1);
157
158 nodes.push_back(position);
159
160 color.push_back(params.shoot_color);
161 }
162
163 branch_UUIDs = context->addTube(params.shoot_subdivisions, nodes, radius, color);
164
165 std::vector<float> shoot_heights;
166 shoot_heights.push_back(0.4);
167 shoot_heights.push_back(0.5);
168 shoot_heights.push_back(0.6);
169 shoot_heights.push_back(0.65);
170 shoot_heights.push_back(0.7);
171 shoot_heights.push_back(0.75);
172 shoot_heights.push_back(0.8);
173 shoot_heights.push_back(0.85);
174 shoot_heights.push_back(0.9);
175 shoot_heights.push_back(0.95);
176 shoot_heights.push_back(1);
177
178 int Nshoots = shoot_heights.size();
179
180 for (int i = 0; i < Nshoots; i++) {
181
182 vec3 position = interpolateTube(nodes, shoot_heights.at(i));
183
184 vec3 base_direction = sphere2cart(make_SphericalCoord(0.2 * PI_F + 0.2 * PI_F * float(i) / float(Nshoots - 1), 2 * PI_F * context->randu()));
185
186 float tip_angle = 0.5 * PI_F + 0.2 * PI_F * float(i) / float(Nshoots - 1);
187
188 float length = (0.3 + 0.5 * float(i) / float(Nshoots - 1)) * params.plant_height;
189
190 tomatoShoot(params, position, base_direction, length, tip_angle, leaf_UUIDs, branch_UUIDs, fruit_UUIDs, context);
191 }
192
193 UUID_leaf.push_back(leaf_UUIDs);
194 UUID_branch.push_back(branch_UUIDs);
195 UUID_fruit.push_back(fruit_UUIDs);
196
197 return UUID_leaf.size() - 1;
198}