1.3.49
 
Loading...
Searching...
No Matches
bean.cpp
1#include "CanopyGenerator.h"
2
3using namespace helios;
4using namespace std;
5
6std::vector<std::vector<uint>> beanCluster(const vec3 center, const BeanParameters &params, Context *context) {
7
8 std::vector<std::vector<uint>> U;
9
10 // todo, nothing here yet
11
12 return U;
13}
14
15std::vector<uint> leafPrototype(const BeanParameters &params, Context *context) {
16
17 int Nx = params.leaf_subdivisions.x;
18 int Ny = ceil(params.leaf_subdivisions.y * 0.5);
19
20 float dx = 1.f / float(Nx);
21 float dy = 0.5f / float(Ny);
22
23 std::vector<uint> UUIDs; //(Nx*Ny*4);
24
25 float a0 = 0.6; // magnitude of leaf bend
26 float e0 = 0.5f; // rate of leaf bend
27
28 int ii = 0;
29 for (int i = 0; i < Nx; i++) {
30 for (int j = 0; j < Ny; j++) {
31
32 float x = float(i) * dx;
33 float y = float(j) * dy;
34
35 float z;
36
37 z = a0 * x / (e0 + x) - e0 * y * y;
38 vec3 v0(x, y, z);
39
40 z = a0 * (x + dx) / (e0 + x + dx) - e0 * y * y;
41 vec3 v1(x + dx, y, z);
42
43 z = a0 * (x + dx) / (e0 + x + dx) - e0 * (y + dy) * (y + dy);
44 vec3 v2(x + dx, y + dy, z);
45
46 z = a0 * x / (e0 + x) - e0 * (y + dy) * (y + dy);
47 vec3 v3(x, y + dy, z);
48
49 vec2 uv0(x, 0.5f + j * dy);
50 vec2 uv1(x + dx, 0.5f + j * dy);
51 vec2 uv2(x + dx, 0.5f + (j + 1) * dy);
52 vec2 uv3(x, 0.5f + (j + 1) * dy);
53
54 UUIDs.push_back(context->addTriangle(v0, v1, v2, params.leaf_texture_file.c_str(), uv0, uv1, uv2));
55 UUIDs.push_back(context->addTriangle(v0, v2, v3, params.leaf_texture_file.c_str(), uv0, uv2, uv3));
56
57 v0.y = -v0.y;
58 v1.y = -v1.y;
59 v2.y = -v2.y;
60 v3.y = -v3.y;
61
62 uv0 = make_vec2(x, 0.5f - j * dy);
63 uv1 = make_vec2(x + dx, 0.5f - j * dy);
64 uv2 = make_vec2(x + dx, 0.5f - (j + 1) * dy);
65 uv3 = make_vec2(x, 0.5f - (j + 1) * dy);
66
67 UUIDs.push_back(context->addTriangle(v0, v2, v1, params.leaf_texture_file.c_str(), uv0, uv2, uv1));
68 UUIDs.push_back(context->addTriangle(v0, v3, v2, params.leaf_texture_file.c_str(), uv0, uv3, uv2));
69
70
71 ii += 4;
72 }
73 }
74
75 context->rotatePrimitive(UUIDs, 0.6, "y");
76 context->translatePrimitive(UUIDs, make_vec3(0.1, 0.12, 0.06));
77
78 // std::vector<uint> UUIDs = context->loadOBJ( "../obj/leaf_new.obj", make_vec3(0.5,0,0), 0, nullrotation, RGB::green, true );
79 // context->scalePrimitive( UUIDs, make_vec3(0.4,0.5,0.5) );
80 // context->translatePrimitive( UUIDs, make_vec3(-0.25,0.6,0.06) );
81 // context->rotatePrimitive( UUIDs, -0.5*PI_F, "z" );
82
83 // std::vector<uint> UUIDs = context->addTile( make_vec3(0.5,0,0), make_vec2(1,1), nullrotation, make_int2(1,1), params.leaf_texture_file.c_str() );
84
85 std::vector<vec3> nodes;
86 nodes.push_back(make_vec3(0, 0, 0));
87 nodes.push_back(make_vec3(0.06, 0, 0.0));
88 nodes.push_back(make_vec3(0.13, 0, 0.02));
89 nodes.push_back(make_vec3(0.13, 0, 0.05));
90
91 float Rpetiole = 0.015;
92
93 std::vector<float> radius{Rpetiole, Rpetiole, Rpetiole * 0.9f, Rpetiole * 0.8f};
94 std::vector<RGBcolor> color{params.shoot_color, params.shoot_color, params.shoot_color, params.shoot_color};
95
96 std::vector<uint> U = context->addTube(params.shoot_subdivisions, nodes, radius, color);
97 // uint objID = context->addTubeObject( params.shoot_subdivisions, nodes, radius, color );
98 // std::vector<uint> U = context->getObjectPrimitiveUUIDs(objID);
99
100 UUIDs.insert(UUIDs.end(), U.begin(), U.end());
101
102 return UUIDs;
103}
104
105void beanLeaflet(const BeanParameters &params, const helios::vec3 base_position, const helios::vec3 base_direction, float length, float bend_angle, float parent_radius, std::vector<std::vector<uint>> &leaf_UUIDs, std::vector<uint> &branch_UUIDs,
106 std::vector<std::vector<std::vector<uint>>> &fruit_UUIDs, std::vector<uint> &leaf_prototype, std::minstd_rand0 &rand_generator, Context *context) {
107
108 std::vector<vec3> nodes;
109 std::vector<float> radius;
110 std::vector<RGBcolor> color;
111
112 int node_count = std::ceil(2.f * length * params.shoot_subdivisions) + 1;
113
114 vec3 dir = base_direction;
115 dir.normalize();
116
117 SphericalCoord base_angle = cart2sphere(dir);
118
119 nodes.push_back(base_position);
120 radius.push_back(0.5f * parent_radius);
121 color.push_back(params.shoot_color);
122
123 float theta = base_angle.elevation;
124 for (int i = 1; i < node_count; i++) {
125
126 float vfrac = float(i) / float(node_count - 1);
127
128 radius.push_back(0.45f * parent_radius * (1.f - 0.3 * vfrac));
129
130 vec3 position = nodes.back() + length / float(node_count - 1) * (sphere2cart(make_SphericalCoord(1, theta, base_angle.azimuth)));
131
132 theta -= bend_angle / float(node_count - 1);
133
134 nodes.push_back(position);
135
136 color.push_back(params.shoot_color);
137 }
138
139 std::vector<uint> U = context->addTube(params.shoot_subdivisions, nodes, radius, color);
140 // uint objID = context->addTubeObject( params.shoot_subdivisions, nodes, radius, color );
141 // std::vector<uint> U = context->getObjectPrimitiveUUIDs(objID);
142
143 branch_UUIDs.insert(branch_UUIDs.end(), U.begin(), U.end());
144
145 // tip leaf
146 U = context->copyPrimitive(leaf_prototype);
147 // objID = context->addPolymeshObject(U);
148
149 context->scalePrimitive(U, make_vec3(params.leaf_length, params.leaf_length * 0.9f, params.leaf_length));
150 context->rotatePrimitive(U, -(theta + getVariation(0.3f * PI_F, rand_generator)), "y");
151 context->rotatePrimitive(U, -base_angle.azimuth + 0.5f * PI_F, "z");
152 context->translatePrimitive(U, nodes.back() - sphere2cart(make_SphericalCoord(0.001f, theta, base_angle.azimuth)));
153 // context->scaleObject( objID, make_vec3(params.leaf_length, params.leaf_length*0.9f, params.leaf_length) );
154 // context->rotateObject( objID, -(theta + getVariation( 0.3*PI_F, rand_generator )), "y" );
155 // context->rotateObject( objID, -base_angle.azimuth+0.5f*PI_F, "z" );
156 // context->translateObject( objID, nodes.back()-sphere2cart(make_SphericalCoord(0.001f,theta,base_angle.azimuth)) );
157
158 leaf_UUIDs.push_back(U);
159
160 // lateral leaves
161
162 float leaf_downangle = 0.1 * PI_F;
163 float leaf_bfrac = 0.8;
164
165 vec3 r0 = interpolateTube(nodes, leaf_bfrac);
166 vec3 r1 = interpolateTube(nodes, 1.01 * leaf_bfrac);
167 vec3 dr = r1 - r0; // vector pointing in direction of shoot at location of leaf
168
169 float elevation = cart2sphere(dr).elevation;
170 float azimuth = cart2sphere(dr).azimuth;
171
172 std::vector<uint> U1 = context->copyPrimitive(leaf_prototype);
173 // objID = context->addPolymeshObject(U1);
174
175 context->scalePrimitive(U1, make_vec3(params.leaf_length, params.leaf_length * 0.9, params.leaf_length));
176 context->rotatePrimitive(U1, elevation + getVariation(0.2f * PI_F, rand_generator), "x");
177 context->rotatePrimitive(U1, leaf_downangle + getVariation(0.2f * PI_F, rand_generator), "y");
178 context->rotatePrimitive(U1, -azimuth, "z");
179 context->translatePrimitive(U1, r0 + 0.01 * params.leaf_length * make_vec3(cosf(-azimuth), sinf(-azimuth), 0));
180 // context->scaleObject( objID, make_vec3(params.leaf_length, params.leaf_length*0.9, params.leaf_length) );
181 // context->rotateObject( objID, elevation + getVariation( 0.2*PI_F, rand_generator ), "x" );
182 // context->rotateObject( objID, leaf_downangle + getVariation( 0.2*PI_F, rand_generator ), "y" );
183 // context->rotateObject( objID, -azimuth, "z" );
184 // context->translateObject( objID, r0 + 0.01*params.leaf_length*make_vec3( cosf(-azimuth), sinf(-azimuth), 0) );
185
186 std::vector<uint> U2 = context->copyPrimitive(leaf_prototype);
187 // objID = context->addPolymeshObject(U2);
188
189 context->scalePrimitive(U2, make_vec3(params.leaf_length, params.leaf_length * 0.9, params.leaf_length));
190 context->rotatePrimitive(U2, -elevation + getVariation(0.2f * PI_F, rand_generator), "x");
191 context->rotatePrimitive(U2, leaf_downangle + getVariation(0.2f * PI_F, rand_generator), "y");
192 context->rotatePrimitive(U2, -azimuth + PI_F, "z");
193 context->translatePrimitive(U2, r0 - 0.01 * params.leaf_length * make_vec3(cosf(-azimuth), sinf(-azimuth), 0));
194 // context->scaleObject( objID, make_vec3(params.leaf_length, params.leaf_length*0.9, params.leaf_length) );
195 // context->rotateObject( objID, -elevation + getVariation( 0.2*PI_F, rand_generator ), "x" );
196 // context->rotateObject( objID, leaf_downangle + getVariation( 0.2*PI_F, rand_generator ), "y" );
197 // context->rotateObject( objID, -azimuth+PI_F, "z" );
198 // context->translateObject( objID, r0 - 0.01*params.leaf_length*make_vec3( cosf(-azimuth), sinf(-azimuth), 0) );
199
200 leaf_UUIDs.push_back(U1);
201 leaf_UUIDs.push_back(U2);
202
203 // fruit
204
205 if (params.pod_length > 0 && context->randu() < 0.66) {
206
207 vec3 cluster_position = interpolateTube(nodes, 0.25) - make_vec3(0, 0, 4 * params.pod_length);
208
209 fruit_UUIDs.push_back(beanCluster(cluster_position, params, context));
210 }
211}
212
213void beanShoot(const BeanParameters &params, const helios::vec3 base_position, const helios::SphericalCoord &shoot_direction, float scale, std::vector<std::vector<uint>> &leaf_UUIDs, std::vector<uint> &branch_UUIDs,
214 std::vector<std::vector<std::vector<uint>>> &fruit_UUIDs, std::vector<uint> &leaf_prototype, std::minstd_rand0 &rand_generator, Context *context) {
215 std::vector<std::vector<uint>> UUIDs_leaf;
216 std::vector<std::vector<std::vector<uint>>> UUIDs_pod;
217
218 std::vector<vec3> nodes;
219
220 nodes.push_back(base_position + make_vec3(0, 0, 0) * scale);
221 nodes.push_back(base_position + make_vec3(0, 0, params.stem_length / 2.f) * scale);
222 nodes.push_back(base_position + make_vec3(0, 0, params.stem_length) * scale);
223
224 std::vector<float> radius{params.stem_radius * scale, params.stem_radius * scale, params.stem_radius * scale * 0.9f};
225 std::vector<RGBcolor> color{params.shoot_color, params.shoot_color, params.shoot_color};
226
227 std::vector<uint> UUIDs_stem = context->addTube(params.shoot_subdivisions, nodes, radius, color);
228 // uint objID = context->addTubeObject( params.shoot_subdivisions, nodes, radius, color );
229 // UUIDs_stem = context->getObjectPrimitiveUUIDs(objID);
230
231 std::vector<uint> U = context->copyPrimitive(leaf_prototype);
232 // objID = context->addPolymeshObject(U);
233
234 float az0 = getVariation(2.f * PI_F, rand_generator);
235
236 context->scalePrimitive(U, make_vec3(params.leaf_length, params.leaf_length * 0.9f, params.leaf_length) * 0.7);
237 context->rotatePrimitive(U, getVariation(0.2f * PI_F, rand_generator), "y");
238 context->rotatePrimitive(U, az0, "z");
239 context->translatePrimitive(U, base_position + make_vec3(0, 0, 0.75f * params.stem_length) * scale);
240 // context->scaleObject( objID, make_vec3(params.leaf_length, params.leaf_length*0.9f, params.leaf_length)*0.7 );
241 // context->rotateObject( objID, getVariation( 0.2*PI_F, rand_generator ), "y" );
242 // context->rotateObject( objID, az0, "z" );
243 // context->translateObject( objID, base_position+make_vec3(0,0, 0.75f*params.stem_length)*scale );
244
245 leaf_UUIDs.push_back(U);
246
247 U = context->copyPrimitive(leaf_prototype);
248 // objID = context->addPolymeshObject(U);
249
250 context->scalePrimitive(U, make_vec3(params.leaf_length, params.leaf_length * 0.9f, params.leaf_length) * 0.7);
251 context->rotatePrimitive(U, getVariation(0.2f * PI_F, rand_generator), "y");
252 context->rotatePrimitive(U, az0 + PI_F, "z");
253 context->translatePrimitive(U, base_position + make_vec3(0, 0, 0.75f * params.stem_length) * scale);
254 // context->scaleObject( objID, make_vec3(params.leaf_length, params.leaf_length*0.9f, params.leaf_length)*0.7 );
255 // context->rotateObject( objID, getVariation( 0.2*PI_F, rand_generator ), "y" );
256 // context->rotateObject( objID, az0+PI_F, "z" );
257 // context->translateObject( objID, base_position+make_vec3(0,0, 0.75f*params.stem_length)*scale );
258
259 leaf_UUIDs.push_back(U);
260
261 float shoot_zenith = 0.2 * PI_F + getVariation(0.1f * PI_F, rand_generator);
262 float shoot_azimuth = getVariation(2.f * PI_F, rand_generator);
263
264 vec3 leaflet_direction = sphere2cart(make_SphericalCoord(0.5f * PI_F - shoot_zenith, shoot_azimuth + getVariation(0.2f * PI_F, rand_generator)));
265
266 beanLeaflet(params, nodes.back(), leaflet_direction, params.leaflet_length, 0.2 * PI_F, params.stem_radius, UUIDs_leaf, UUIDs_stem, UUIDs_pod, leaf_prototype, rand_generator, context);
267
268 leaflet_direction = sphere2cart(make_SphericalCoord(0.5f * PI_F - shoot_zenith, PI_F + shoot_azimuth + getVariation(0.2f * PI_F, rand_generator)));
269
270 beanLeaflet(params, nodes.back(), leaflet_direction, params.leaflet_length, 0.2 * PI_F, params.stem_radius, UUIDs_leaf, UUIDs_stem, UUIDs_pod, leaf_prototype, rand_generator, context);
271
272 for (uint i = 0; i < UUIDs_leaf.size(); i++) {
273 context->rotatePrimitive(UUIDs_leaf.at(i), shoot_direction.zenith, "x");
274 context->rotatePrimitive(UUIDs_leaf.at(i), shoot_direction.azimuth, "z");
275 }
276 context->rotatePrimitive(UUIDs_stem, shoot_direction.zenith, "x");
277 context->rotatePrimitive(UUIDs_stem, shoot_direction.azimuth, "z");
278
279 leaf_UUIDs.insert(leaf_UUIDs.end(), UUIDs_leaf.begin(), UUIDs_leaf.end());
280 branch_UUIDs.insert(branch_UUIDs.end(), UUIDs_stem.begin(), UUIDs_stem.end());
281 fruit_UUIDs.insert(fruit_UUIDs.end(), UUIDs_pod.begin(), UUIDs_pod.end());
282}
283
284uint CanopyGenerator::bean(const BeanParameters &params, const vec3 &origin) {
285
286 std::vector<std::vector<uint>> leaf_UUIDs;
287 std::vector<uint> branch_UUIDs;
288 std::vector<std::vector<std::vector<uint>>> fruit_UUIDs;
289
290 std::vector<uint> leaf_prototype = leafPrototype(params, context);
291
292 beanShoot(params, origin, make_SphericalCoord(0.5 * PI_F, 0), 1, leaf_UUIDs, branch_UUIDs, fruit_UUIDs, leaf_prototype, generator, context);
293
294 UUID_leaf.push_back(leaf_UUIDs);
295 UUID_branch.push_back(branch_UUIDs);
296 UUID_fruit.push_back(fruit_UUIDs);
297
298 context->deletePrimitive(leaf_prototype);
299
300 return UUID_leaf.size() - 1;
301}