3 #include "primitivebuilder.h"
11 UvSphereBuilder::UvSphereBuilder(float r, unsigned s, unsigned n):
20 rings = (segments+1)/2;
25 void UvSphereBuilder::build(PrimitiveBuilder &builder) const
27 float u_scale = 1.0f/segments;
28 float v_scale = 1.0f/rings;
29 adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, radius*M_PI);
31 for(unsigned i=0; i<=rings; ++i)
33 float av = i*M_PI/rings-M_PI/2;
37 for(unsigned j=0; j<=segments; ++j)
39 float au = j*M_PI*2/segments;
43 builder.normal(cv*cu, cv*su, sv);
44 builder.texcoord(j*u_scale, i*v_scale);
47 builder.tangent(-su, cu, 0);
48 builder.binormal(-sv*cu, -sv*su, cv);
50 builder.vertex(cv*cu*radius, cv*su*radius, sv*radius);
54 builder.begin(TRIANGLES);
55 for(unsigned j=0; j<segments; ++j)
58 builder.element(segments+2+j);
59 builder.element(segments+1+j);
61 unsigned top = (rings+1)*(segments+1)-1;
62 for(unsigned j=0; j<segments; ++j)
64 builder.element(top-j);
65 builder.element(top-(segments+2+j));
66 builder.element(top-(segments+1+j));
70 for(unsigned i=1; i<rings; ++i)
72 builder.begin(TRIANGLE_STRIP);
73 unsigned base = i*(segments+1);
74 for(unsigned j=0; j<=segments; ++j)
76 builder.element(base+segments+1+j);
77 builder.element(base+j);
84 // https://en.wikipedia.org/wiki/Regular_icosahedron#Cartesian_coordinates
85 float IcoSphereBuilder::base_vertices[12*3] =
87 0.0f, -0.5257311f, -0.8506508f,
88 0.0f, 0.5257311f, -0.8506508f,
89 0.0f, -0.5257311f, 0.8506508f,
90 0.0f, 0.5257311f, 0.8506508f,
91 -0.8506508f, 0.0f, -0.5257311f,
92 -0.8506508f, 0.0f, 0.5257311f,
93 0.8506508f, 0.0f, -0.5257311f,
94 0.8506508f, 0.0f, 0.5257311f,
95 -0.5257311f, -0.8506508f, 0.0f,
96 0.5257311f, -0.8506508f, 0.0f,
97 -0.5257311f, 0.8506508f, 0.0f,
98 0.5257311f, 0.8506508f, 0.0f
101 unsigned IcoSphereBuilder::base_triangles[20*3] =
125 unsigned IcoSphereBuilder::base_edges[30*2] = { 0, 0 };
126 unsigned IcoSphereBuilder::base_tri_edges[20*3] = { 0, 0, 0 };
128 IcoSphereBuilder::IcoSphereBuilder(float r, unsigned s):
132 if(base_edges[0]==base_edges[1])
136 void IcoSphereBuilder::initialize_edges()
138 vector<int> edge_map(12*12, -1);
139 unsigned next_edge = 0;
140 for(unsigned i=0; i<20; ++i)
141 for(unsigned j=0; j<3; ++j)
143 unsigned v1 = base_triangles[i*3+j];
144 unsigned v2 = base_triangles[i*3+(j+1)%3];
145 int e = edge_map[v1*12+v2];
149 base_edges[e*2] = v1;
150 base_edges[e*2+1] = v2;
151 // The other triangle using this edge will have the vertices swapped
152 edge_map[v2*12+v1] = e|32;
154 base_tri_edges[i*3+j] = e;
158 void IcoSphereBuilder::build(PrimitiveBuilder &bld) const
160 for(unsigned i=0; i<12; ++i)
162 const float *v = base_vertices+i*3;
163 bld.normal(v[0], v[1], v[2]);
164 bld.vertex(v[0]*radius, v[1]*radius, v[2]*radius);
169 vector<Vector3> edge_subdiv(30*(subdivision+1));
170 for(unsigned i=0; i<30; ++i)
172 Vector3 v1(base_vertices+base_edges[i*2]*3);
173 Vector3 v2(base_vertices+base_edges[i*2+1]*3);
174 for(unsigned j=1; j<subdivision; ++j)
176 float t = static_cast<float>(j)/subdivision;
177 Vector3 v = v1*(1.0f-t)+v2*t;
178 edge_subdiv[i*(subdivision-1)+j-1] = v;
181 bld.vertex(v*radius);
185 for(unsigned i=0; i<20; ++i)
186 for(unsigned j=1; j<subdivision; ++j)
188 unsigned e = base_tri_edges[i*3];
189 Vector3 v1 = edge_subdiv[edge_vertex(e, subdivision-j)];
190 e = base_tri_edges[i*3+1];
191 Vector3 v2 = edge_subdiv[edge_vertex(e, j)];
192 for(unsigned k=1; k<j; ++k)
194 float t = static_cast<float>(k)/j;
195 Vector3 v = normalize(v1*(1.0f-t)+v2*t);
197 bld.vertex(v*radius);
201 for(unsigned i=0; i<20; ++i)
203 unsigned mid = 12+30*(subdivision-1)+i*(subdivision-1)*(subdivision-2)/2;
204 for(unsigned j=1; j<=subdivision; ++j)
206 bld.begin(TRIANGLE_STRIP);
208 bld.element(base_triangles[i*3]);
210 bld.element(12+edge_vertex(base_tri_edges[i*3], subdivision-j));
214 bld.element(base_triangles[i*3+1]);
215 bld.element(12+edge_vertex(base_tri_edges[i*3+1], j));
219 bld.element(12+edge_vertex(base_tri_edges[i*3], subdivision-j+1));
222 bld.element(12+edge_vertex(base_tri_edges[i*3+2], subdivision-1));
224 bld.element(mid+(j-1)*(j-2)/2);
226 for(unsigned k=2; k<j; ++k)
228 bld.element(mid+(j-2)*(j-3)/2+k-2);
230 bld.element(12+edge_vertex(base_tri_edges[i*3+2], subdivision-k));
232 bld.element(mid+(j-1)*(j-2)/2+k-1);
235 bld.element(12+edge_vertex(base_tri_edges[i*3+1], j-1));
237 bld.element(base_triangles[i*3+2]);
239 bld.element(12+edge_vertex(base_tri_edges[i*3+1], j));
247 bld.begin(TRIANGLES);
248 for(unsigned i=0; i<20*3; ++i)
249 bld.element(base_triangles[i]);
254 unsigned IcoSphereBuilder::edge_vertex(unsigned e, unsigned i) const
256 return (e&31)*(subdivision-1)+((e&32)?subdivision-i:i)-1;