1 module draw;
2 
3 import std.math;
4 
5 import des.math.linear;
6 import des.util.stdext.algorithm;
7 import des.util.helpers;
8 
9 import des.space;
10 
11 import des.gl;
12 
13 class Sphere : GLSimpleObject, SpaceNode
14 {
15     mixin SpaceNodeHelper;
16 
17 protected:
18 
19     GLBuffer pos, ind;
20 
21     void prepareBuffers()
22     {
23         auto loc = shader.getAttribLocations( "pos" );
24         pos = createArrayBuffer;
25         ind = createIndexBuffer;
26         setAttribPointer( pos, loc[0], 3, GLType.FLOAT );
27 
28         vec3[] buf;
29 
30         vec3 sp( vec2 a, float R ) { return spheric(a) * R; }
31         vec3 cl( vec2 a, float R ) { return cylinder(a) * vec3(R,R,1); }
32 
33         buf ~= amap!(a=>a+vec3(0,0,0))( amap!(a=>sp(a,R))( planeCoord( uivec2( resU, resV/2 ), vec2(0,PI*2), vec2(PI,PI/2) ) ) );
34         buf ~= amap!(a=>a-vec3(0,0,0))( amap!(a=>sp(a,R*0.9))( planeCoord( uivec2( resU, resV/2 ), vec2(0,PI*2), vec2(PI/2,PI) ) ) );
35 
36         pos.setData( buf );
37 
38         ind.setData( triangleStripPlaneIndex( uivec2( resU+1, resV+2 ), uint.max ) );
39     }
40 
41     uint resU, resV;
42     float R;
43 
44 public:
45 
46     this( float r, uint u, uint v )
47     {
48         R = r;
49         resU = u;
50         resV = v;
51         import std.file;
52         super( newEMM!CommonGLShaderProgram(
53                 parseGLShaderSource(
54                     readText(
55                         appPath( "..", "data", "shaders", "object.glsl" )
56                     ))));
57         prepareBuffers();
58     }
59 
60     void draw( Camera cam )
61     {
62         shader.setUniform!col4( "col", col4(1,0,0,1) );
63         glEnable( GL_PRIMITIVE_RESTART );
64         glPrimitiveRestartIndex(uint.max);
65         glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
66         shader.setUniform!mat4( "prj", cam.projection.matrix * cam.resolve(this) );
67         drawElements( DrawMode.TRIANGLE_STRIP );
68         glDisable( GL_PRIMITIVE_RESTART );
69     }
70 }
71 
72 vec2[] planeCoord( uivec2 res, vec2 x_size=vec2(0,1), vec2 y_size=vec2(0,1) )
73 {
74     vec2[] ret;
75 
76     float sx = (x_size[1] - x_size[0]) / res.u;
77     float sy = (y_size[1] - y_size[0]) / res.v;
78 
79     foreach( y; 0 .. res.y+1 )
80         foreach( x; 0 .. res.x+1 )
81             ret ~= vec2( x_size[0] + sx * x, y_size[0] + sy * y );
82 
83     return ret;
84 }
85 
86 vec3 spheric( in vec2 c ) pure
87 { return vec3( cos(c.x) * sin(c.y), sin(c.x) * sin(c.y), cos(c.y) ); }
88 
89 vec3 cylinder( in vec2 c ) pure
90 { return vec3( cos(c.x), sin(c.x), c.y ); }
91 
92 uint[] triangleStripPlaneIndex( uivec2 res, uint term )
93 {
94     uint[] ret;
95     foreach( y; 0 .. res.y-1 )
96     {
97         ret ~= [ y*res.x, (y+1)*res.x ];
98         foreach( x; 1 .. res.x )
99             ret ~= [ y*res.x+x, (y+1)*res.x+x ];
100         ret ~= term;
101     }
102     return ret;
103 }