1 #define _USE_MATH_DEFINES
4 #include "primitivebuilder.h"
12 UvSphereBuilder::UvSphereBuilder(float r, unsigned s, unsigned n):
21 rings = (segments+1)/2;
26 void UvSphereBuilder::build(PrimitiveBuilder &builder) const
28 float u_scale = 1.0f/segments;
29 float v_scale = 1.0f/rings;
30 adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, radius*M_PI);
32 for(unsigned i=0; i<=rings; ++i)
34 float av = i*M_PI/rings-M_PI/2;
38 for(unsigned j=0; j<=segments; ++j)
40 float au = j*M_PI*2/segments;
44 builder.normal(cv*cu, cv*su, sv);
45 builder.texcoord(j*u_scale, i*v_scale);
47 builder.tangent(-su, cu, 0);
48 builder.vertex(cv*cu*radius, cv*su*radius, sv*radius);
52 builder.begin(TRIANGLES);
53 for(unsigned j=0; j<segments; ++j)
56 builder.element(segments+2+j);
57 builder.element(segments+1+j);
59 unsigned top = (rings+1)*(segments+1)-1;
60 for(unsigned j=0; j<segments; ++j)
62 builder.element(top-j);
63 builder.element(top-(segments+2+j));
64 builder.element(top-(segments+1+j));
68 for(unsigned i=1; i<rings; ++i)
70 builder.begin(TRIANGLE_STRIP);
71 unsigned base = i*(segments+1);
72 for(unsigned j=0; j<=segments; ++j)
74 builder.element(base+segments+1+j);
75 builder.element(base+j);
82 // https://en.wikipedia.org/wiki/Regular_icosahedron#Cartesian_coordinates
83 const float IcoSphereBuilder::base_vertices[12*3] =
85 0.0f, -0.5257311f, -0.8506508f,
86 0.0f, 0.5257311f, -0.8506508f,
87 0.0f, -0.5257311f, 0.8506508f,
88 0.0f, 0.5257311f, 0.8506508f,
89 -0.8506508f, 0.0f, -0.5257311f,
90 -0.8506508f, 0.0f, 0.5257311f,
91 0.8506508f, 0.0f, -0.5257311f,
92 0.8506508f, 0.0f, 0.5257311f,
93 -0.5257311f, -0.8506508f, 0.0f,
94 0.5257311f, -0.8506508f, 0.0f,
95 -0.5257311f, 0.8506508f, 0.0f,
96 0.5257311f, 0.8506508f, 0.0f
99 const unsigned IcoSphereBuilder::base_triangles[20*3] =
123 unsigned IcoSphereBuilder::base_edges[30*2] = { 0, 0 };
124 unsigned IcoSphereBuilder::base_tri_edges[20*3] = { 0, 0, 0 };
126 IcoSphereBuilder::IcoSphereBuilder(float r, unsigned s):
130 if(base_edges[0]==base_edges[1])
134 void IcoSphereBuilder::initialize_edges()
136 vector<int> edge_map(12*12, -1);
137 unsigned next_edge = 0;
138 for(unsigned i=0; i<20; ++i)
139 for(unsigned j=0; j<3; ++j)
141 unsigned v1 = base_triangles[i*3+j];
142 unsigned v2 = base_triangles[i*3+(j+1)%3];
143 int e = edge_map[v1*12+v2];
147 base_edges[e*2] = v1;
148 base_edges[e*2+1] = v2;
149 // The other triangle using this edge will have the vertices swapped
150 edge_map[v2*12+v1] = e|32;
152 base_tri_edges[i*3+j] = e;
156 void IcoSphereBuilder::build(PrimitiveBuilder &bld) const
158 for(unsigned i=0; i<12; ++i)
160 const float *v = base_vertices+i*3;
161 bld.normal(v[0], v[1], v[2]);
162 bld.vertex(v[0]*radius, v[1]*radius, v[2]*radius);
167 vector<Vector3> edge_subdiv(30*(subdivision+1));
168 for(unsigned i=0; i<30; ++i)
170 Vector3 v1(base_vertices+base_edges[i*2]*3);
171 Vector3 v2(base_vertices+base_edges[i*2+1]*3);
172 for(unsigned j=1; j<subdivision; ++j)
174 float t = static_cast<float>(j)/subdivision;
175 Vector3 v = v1*(1.0f-t)+v2*t;
176 edge_subdiv[i*(subdivision-1)+j-1] = v;
179 bld.vertex(v*radius);
183 for(unsigned i=0; i<20; ++i)
184 for(unsigned j=1; j<subdivision; ++j)
186 unsigned e = base_tri_edges[i*3];
187 Vector3 v1 = edge_subdiv[edge_vertex(e, subdivision-j)];
188 e = base_tri_edges[i*3+1];
189 Vector3 v2 = edge_subdiv[edge_vertex(e, j)];
190 for(unsigned k=1; k<j; ++k)
192 float t = static_cast<float>(k)/j;
193 Vector3 v = normalize(v1*(1.0f-t)+v2*t);
195 bld.vertex(v*radius);
199 for(unsigned i=0; i<20; ++i)
201 unsigned mid = 12+30*(subdivision-1)+i*(subdivision-1)*(subdivision-2)/2;
202 for(unsigned j=1; j<=subdivision; ++j)
204 bld.begin(TRIANGLE_STRIP);
206 bld.element(base_triangles[i*3]);
208 bld.element(12+edge_vertex(base_tri_edges[i*3], subdivision-j));
212 bld.element(base_triangles[i*3+1]);
213 bld.element(12+edge_vertex(base_tri_edges[i*3+1], j));
217 bld.element(12+edge_vertex(base_tri_edges[i*3], subdivision-j+1));
220 bld.element(12+edge_vertex(base_tri_edges[i*3+2], subdivision-1));
222 bld.element(mid+(j-1)*(j-2)/2);
224 for(unsigned k=2; k<j; ++k)
226 bld.element(mid+(j-2)*(j-3)/2+k-2);
228 bld.element(12+edge_vertex(base_tri_edges[i*3+2], subdivision-k));
230 bld.element(mid+(j-1)*(j-2)/2+k-1);
233 bld.element(12+edge_vertex(base_tri_edges[i*3+1], j-1));
235 bld.element(base_triangles[i*3+2]);
237 bld.element(12+edge_vertex(base_tri_edges[i*3+1], j));
245 bld.begin(TRIANGLES);
246 for(unsigned i=0; i<20*3; ++i)
247 bld.element(base_triangles[i]);
252 unsigned IcoSphereBuilder::edge_vertex(unsigned e, unsigned i) const
254 return (e&31)*(subdivision-1)+((e&32)?subdivision-i:i)-1;