1 module unecht.core.components.shapes;
2 
3 import unecht.core.component;
4 import unecht.core.components.material;
5 import unecht.core.components.renderer;
6 import unecht.core.components.misc;
7 import unecht.core.defaultInspector;
8 
9 import unecht.gl.vertexBufferObject;
10 import unecht.gl.vertexArrayObject;
11 import unecht.gl.texture;
12 
13 import gl3n.linalg;
14 
15 ///
16 final class UEShapeBox : UEComponent {
17     
18     mixin(UERegisterObject!());
19 
20     @Serialize private
21     {
22         UERenderer renderer;
23         UEMesh mesh;
24         UEMaterial material;
25     }
26 
27     override void onCreate() {
28         super.onCreate;
29 
30         if(!renderer)
31         {
32             renderer = this.entity.getComponent!UERenderer;
33             if(!renderer)
34                 renderer = this.entity.addComponent!UERenderer;
35         }
36 
37         if(!mesh)
38         {
39             mesh = this.entity.getComponent!UEMesh;
40             if(!mesh)
41             {
42                 mesh = this.entity.addComponent!UEMesh;
43             }
44         }
45 
46         if(!material)
47         {
48             material = this.entity.getComponent!UEMaterial;
49             if(!material)
50             {
51                 material = this.entity.addComponent!UEMaterial;
52                 material.setProgram(UEMaterial.vs_shaded,UEMaterial.fs_shaded, "shaded");
53             }
54         }
55 
56         renderer.mesh = mesh;
57         renderer.material = material;
58         
59         mesh.vertexArrayObject = new GLVertexArrayObject();
60         mesh.vertexArrayObject.bind();
61         scope(exit) mesh.vertexArrayObject.unbind();
62         
63         auto upLF = vec3(-1,1,-1);
64         auto upLB = vec3(-1,1,1);
65         auto upRB = vec3(1,1,1);
66         auto upRF = vec3(1,1,-1);
67         
68         auto dnLF = vec3(-1,-1,-1);
69         auto dnLB = vec3(-1,-1,1);
70         auto dnRB = vec3(1,-1,1);
71         auto dnRF = vec3(1,-1,-1);
72 
73         mesh.setVertexData([
74                 //top
75                 upLF,upLB,upRB,upRF,
76                 //front
77                 upLF,upRF,dnLF,dnRF,
78                 //bottom
79                 dnLF,dnRF,dnLB,dnRB,
80                 //left
81                 upLF,upLB,dnLF,dnLB,
82                 //back
83                 upRB,upLB,dnRB,dnLB,
84                 //right
85                 upRB,upRF,dnRB,dnRF
86             ]);
87         
88         auto ul = vec2(0,0);
89         auto ur = vec2(1,0);
90         auto lr = vec2(1,1);
91         auto ll = vec2(0,1);
92         
93         mesh.uvBuffer = new GLVertexBufferObject([
94                 //top
95                 ul,ur,lr,ll,
96                 //front
97                 ul,ur,ll,lr,
98                 //bottom
99                 ul,ur,ll,lr,
100                 //left
101                 ul,ur,ll,lr,
102                 //back
103                 ul,ur,ll,lr,
104                 //right
105                 ul,ur,ll,lr,
106             ]);
107         
108         mesh.normalBuffer = new GLVertexBufferObject([
109                 // top
110                 vec3(0,1,0),vec3(0,1,0),vec3(0,1,0),vec3(0,1,0),
111                 // front
112                 vec3(0,0,-1),vec3(0,0,-1),vec3(0,0,-1),vec3(0,0,-1),
113                 // bottom
114                 vec3(0,-1,0),vec3(0,-1,0),vec3(0,-1,0),vec3(0,-1,0),
115                 // left
116                 vec3(-1,0,0),vec3(-1,0,0),vec3(-1,0,0),vec3(-1,0,0),
117                 // back
118                 vec3(0,0,1),vec3(0,0,1),vec3(0,0,1),vec3(0,0,1),
119                 // right
120                 vec3(1,0,0),vec3(1,0,0),vec3(1,0,0),vec3(1,0,0)
121             ]);
122         
123         mesh.indexBuffer = new GLVertexBufferObject([
124                 //top
125                 0,1,2, 
126                 0,2,3,
127                 //front
128                 4,5,6,
129                 5,7,6,
130                 //bottom
131                 8,9,10,
132                 9,11,10,
133                 //left
134                 12,14,13, 13,14,15,
135                 //back
136                 16,17,18, 17,19,18,
137                 //right
138                 20,22,21, 21,22,23
139             ]);
140     }
141 }
142 
143 ///
144 final class UEShapeSphere : UEComponent {
145     
146     mixin(UERegisterObject!());
147 
148     UERenderer renderer;
149     
150     override void onCreate() {
151         super.onCreate;      
152 
153         renderer = this.entity.getComponent!UERenderer;
154         if(!renderer)
155             renderer = this.entity.addComponent!UERenderer;
156             
157         auto mesh = this.entity.getComponent!UEMesh;
158         if(!mesh)
159             mesh = this.entity.addComponent!UEMesh;
160 
161         auto material = this.entity.getComponent!UEMaterial;
162         if(!material)
163             material = this.entity.addComponent!UEMaterial;
164 
165         renderer.material = material;
166 
167         material.setProgram(UEMaterial.vs_shaded,UEMaterial.fs_shaded, "shaded");
168         renderer.mesh = mesh;
169         
170         mesh.vertexArrayObject = new GLVertexArrayObject();
171         mesh.vertexArrayObject.bind();
172 
173         createSphereMesh(mesh,24,24);
174 
175         mesh.vertexArrayObject.unbind();
176     }
177 
178     ///
179     override void onDestroy() {
180         super.onDestroy;
181         
182         renderer = null;
183     }
184 
185     ///
186     private void createSphereMesh(UEMesh _mesh, int width, int height)
187     {
188         import std.math:PI;
189         import std.c.math:sinf,cosf;
190         
191         float theta, phi;
192         int t, j, ntri, nvec;
193         
194         nvec = (height-2)* width+2;
195         ntri = (height-2)*(width-1)*2;
196         
197         auto dat = new vec3[nvec];
198         auto idx = new uint[ntri*3];
199         auto norm = new vec3[nvec];
200         
201         for( t=0, j=1; j<height-1; j++ )
202         {
203             for( int i=0; i<width; i++ )
204             {
205                 theta = (cast(float)j)/(height-1) * PI;
206                 phi   = (cast(float)i)/(width-1) * PI*2;
207                 auto x =  sinf(theta) * cosf(phi);
208                 auto y =  cosf(theta);
209                 auto z = -sinf(theta) * sinf(phi);
210 
211                 auto pos = dat[t++] = vec3(x,y,z);
212 
213                 norm[t-1] = pos.normalized;
214             }
215         }
216         dat[t++] = norm[t-1] = vec3(0,1,0);
217         dat[t++] = norm[t-1] = vec3(0,-1,0);
218         
219         for( t=0, j=0; j<height-3; j++ )
220         {
221             for( int i=0; i<width-1; i++ )
222             {
223                 idx[t++] = (j  )*width + i  ;
224                 idx[t++] = (j+1)*width + i+1;
225                 idx[t++] = (j  )*width + i+1;
226                 idx[t++] = (j  )*width + i  ;
227                 idx[t++] = (j+1)*width + i  ;
228                 idx[t++] = (j+1)*width + i+1;
229             }
230         }
231 
232         for( int i=0; i<width-1; i++ )
233         {
234             idx[t++] = (height-2)*width;
235             idx[t++] = i;
236             idx[t++] = i+1;
237             idx[t++] = (height-2)*width+1;
238             idx[t++] = (height-3)*width + i+1;
239             idx[t++] = (height-3)*width + i;
240         }
241 
242         _mesh.setVertexData(dat);
243         _mesh.indexBuffer = new GLVertexBufferObject(idx);
244         _mesh.normalBuffer = new GLVertexBufferObject(norm);
245     }
246 }