1 module des.assimp.generator;
2 
3 import des.util.logsys;
4 import des.util.stdext.algorithm;
5 
6 import des.assimp.mesh;
7 
8 ///
9 class SMUniformSurfaceMeshGenerator
10 {
11     mixin ClassLogger;
12 protected:
13 
14     ///
15     vec2[] planeCoords( uivec2 res )
16     {
17         vec2[] ret;
18 
19         float sx = 1.0 / res.x;
20         float sy = 1.0 / res.y;
21 
22         foreach( y; 0 .. res.y+1 )
23             foreach( x; 0 .. res.x+1 )
24                 ret ~= vec2( sx * x, sy * y );
25 
26         return ret;
27     }
28 
29     ///
30     uint[] triangleStripPlaneIndex( uivec2 res, uint term=uint.max )
31     {
32         uint[] ret;
33         foreach( y; 0 .. res.y-1 )
34         {
35             ret ~= [ y*res.x, (y+1)*res.x ];
36             foreach( x; 1 .. res.x )
37                 ret ~= [ y*res.x+x, (y+1)*res.x+x ];
38             ret ~= term;
39         }
40         return ret;
41     }
42 
43     abstract
44     {
45         vec3[] transformCoords( vec2[] );
46         vec2[] transformTexCoords( vec2[] );
47         mat3[] getTangentSpace( vec2[] );
48     }
49 
50 public:
51 
52     this() { logger = new InstanceLogger( this ); }
53 
54     uivec2 subdiv;
55 
56     SMMesh getMesh( string name )
57     {
58         scope(exit) logger.Debug( "generate mesh '%s'" );
59 
60         auto crd = planeCoords( subdiv );
61 
62         SMMesh m;
63 
64         m.name = name;
65         m.type = m.Type.TRIANGLE_STRIP;
66         m.indices = triangleStripPlaneIndex( subdiv+uivec2(1,1) );
67         m.vertices = transformCoords( crd );
68         m.texcoords = [ SMTexCoord( 2, cast(float[])transformTexCoords( crd ) ) ];
69 
70         auto ts = getTangentSpace( crd );
71 
72         m.normals = amap!(a=>vec3(a.col(2)))( ts );
73         m.tangents = amap!(a=>vec3(a.col(0)))( ts );
74         m.bitangents = amap!(a=>vec3(a.col(1)))( ts );
75         m.colors = null;
76 
77         return m;
78     }
79 }
80 
81 //vec3 cylinder( in vec2 c ) pure
82 //{ return vec3( cos(c.x), sin(c.x), c.y ); }
83 
84 class SMSphereMeshGenerator : SMUniformSurfaceMeshGenerator
85 {
86 protected:
87 
88     import std.math;
89 
90     vec3 spheric( in vec2 c ) pure
91     { return vec3( cos(c.x) * sin(c.y), sin(c.x) * sin(c.y), cos(c.y) ); }
92 
93     vec2[] truePos( vec2[] crd )
94     { return amap!( a => a * vec2(PI*2,PI) )( crd ); }
95 
96     mat3 tangentSpace( in vec2 c )
97     {
98         auto t = vec3( cos(c.x), sin(c.x), 0 );
99         auto n = vec3( cos(c.x) * sin(c.y), sin(c.x) * sin(c.y), cos(c.y) );
100         return mat3( t,-cross(t,n),n ).T;
101     }
102 
103     override
104     {
105         vec3[] transformCoords( vec2[] crd )
106         { return amap!( a => spheric(a) * radius )( truePos( crd ) ); }
107 
108         vec2[] transformTexCoords( vec2[] crd ) { return crd; }
109 
110         mat3[] getTangentSpace( vec2[] crd )
111         { return amap!( a => tangentSpace(a) )( truePos( crd ) ); }
112     }
113 
114 public:
115 
116     this( float R, uint rx, uint ry )
117     {
118         subdiv = uivec2(rx,ry);
119         radius = R;
120     }
121 
122     float radius;
123 }
124 
125 SMMesh smGetSphereMesh( string name, float R, uint rx, uint ry )
126 {
127     auto gen = new SMSphereMeshGenerator( R, rx, ry );
128     return gen.getMesh( name );
129 }