X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fbuilders%2Fsphere.cpp;fp=source%2Fbuilders%2Fsphere.cpp;h=dd27fad40e28cc1608ad9699b121d1c4af0f0ffb;hb=7aaec9a70b8d7733429bec043f8e33e02956f266;hp=0000000000000000000000000000000000000000;hpb=bec07999d95b76f4b47cffcc564d0cd0afc0435e;p=libs%2Fgl.git diff --git a/source/builders/sphere.cpp b/source/builders/sphere.cpp new file mode 100644 index 00000000..dd27fad4 --- /dev/null +++ b/source/builders/sphere.cpp @@ -0,0 +1,261 @@ +#define _USE_MATH_DEFINES +#include +#include +#include "primitivebuilder.h" +#include "sphere.h" + +using namespace std; + +namespace Msp { +namespace GL { + +UvSphereBuilder::UvSphereBuilder(float r, unsigned s, unsigned n): + radius(r), + segments(s), + rings(n) +{ + if(segments<3) + segments = 3; + + if(rings==0) + rings = (segments+1)/2; + else if(rings<2) + rings = 2; +} + +void UvSphereBuilder::build(PrimitiveBuilder &builder) const +{ + float u_scale = 1.0f/segments; + float v_scale = 1.0f/rings; + adjust_texture_scale(u_scale, v_scale, radius*M_PI*2, radius*M_PI); + + for(unsigned i=0; i<=rings; ++i) + { + float av = i*M_PI/rings-M_PI/2; + float cv = cos(av); + float sv = sin(av); + + for(unsigned j=0; j<=segments; ++j) + { + float au = j*M_PI*2/segments; + float cu = cos(au); + float su = sin(au); + + builder.normal(cv*cu, cv*su, sv); + builder.texcoord(j*u_scale, i*v_scale); + if(generate_tbn) + { + builder.tangent(-su, cu, 0); + builder.binormal(-sv*cu, -sv*su, cv); + } + builder.vertex(cv*cu*radius, cv*su*radius, sv*radius); + } + } + + builder.begin(TRIANGLES); + for(unsigned j=0; j edge_map(12*12, -1); + unsigned next_edge = 0; + for(unsigned i=0; i<20; ++i) + for(unsigned j=0; j<3; ++j) + { + unsigned v1 = base_triangles[i*3+j]; + unsigned v2 = base_triangles[i*3+(j+1)%3]; + int e = edge_map[v1*12+v2]; + if(e<0) + { + e = next_edge++; + base_edges[e*2] = v1; + base_edges[e*2+1] = v2; + // The other triangle using this edge will have the vertices swapped + edge_map[v2*12+v1] = e|32; + } + base_tri_edges[i*3+j] = e; + } +} + +void IcoSphereBuilder::build(PrimitiveBuilder &bld) const +{ + for(unsigned i=0; i<12; ++i) + { + const float *v = base_vertices+i*3; + bld.normal(v[0], v[1], v[2]); + bld.vertex(v[0]*radius, v[1]*radius, v[2]*radius); + } + + if(subdivision>1) + { + vector edge_subdiv(30*(subdivision+1)); + for(unsigned i=0; i<30; ++i) + { + Vector3 v1(base_vertices+base_edges[i*2]*3); + Vector3 v2(base_vertices+base_edges[i*2+1]*3); + for(unsigned j=1; j(j)/subdivision; + Vector3 v = v1*(1.0f-t)+v2*t; + edge_subdiv[i*(subdivision-1)+j-1] = v; + v.normalize(); + bld.normal(v); + bld.vertex(v*radius); + } + } + + for(unsigned i=0; i<20; ++i) + for(unsigned j=1; j(k)/j; + Vector3 v = normalize(v1*(1.0f-t)+v2*t); + bld.normal(v); + bld.vertex(v*radius); + } + } + + for(unsigned i=0; i<20; ++i) + { + unsigned mid = 12+30*(subdivision-1)+i*(subdivision-1)*(subdivision-2)/2; + for(unsigned j=1; j<=subdivision; ++j) + { + bld.begin(TRIANGLE_STRIP); + if(j==subdivision) + bld.element(base_triangles[i*3]); + else + bld.element(12+edge_vertex(base_tri_edges[i*3], subdivision-j)); + + if(j==1) + { + bld.element(base_triangles[i*3+1]); + bld.element(12+edge_vertex(base_tri_edges[i*3+1], j)); + } + else + { + bld.element(12+edge_vertex(base_tri_edges[i*3], subdivision-j+1)); + + if(j==subdivision) + bld.element(12+edge_vertex(base_tri_edges[i*3+2], subdivision-1)); + else + bld.element(mid+(j-1)*(j-2)/2); + + for(unsigned k=2; k