1 module armos.graphics.bufferentity;
2 
3 import armos.graphics;
4 import armos.graphics.mesh;
5 import armos.graphics.material;
6 import armos.graphics.buffer;
7 import armos.graphics.buffermesh;
8 import armos.graphics.shader;
9 
10 /++
11 +/
12 class BufferEntity {
13     import armos.utils.scoped;
14     public{
15         ///
16         this(Mesh mesh, Material material, in BufferUsageFrequency freq, in BufferUsageNature nature){
17             this(new BufferMesh(mesh, freq, nature), material);
18         }
19         
20         ///
21         this(BufferBundle bufferBundle, Material material){
22             _material = material;
23             _bufferBundle = bufferBundle;
24             updateShaderAttribs();
25         }
26         
27         ///
28         this(){}
29         
30         ///
31         BufferEntity updateShaderAttribs(){
32             auto scopedVao = _bufferBundle.vao.scoped;
33             import std.algorithm;
34             _bufferBundle.attrs.keys.filter!(key => _bufferBundle.attrs[key].type!=BufferType.ElementArray && _bufferBundle.attrs[key].type!=BufferType.DrawIndirect)
35                                     .each!((key){
36                                         if(_bufferBundle.attrs[key].size > 0){
37                                             _bufferBundle.attrs[key].begin;
38                                             _material.shader.attr(key);
39                                             _bufferBundle.attrs[key].end;
40                                         }
41                                     });
42             return this;
43         }
44 
45         BufferEntity updateBuffers(){
46             import std.algorithm;
47             _bufferBundle.attrs.keys.each!((key){
48                     _bufferBundle.attr(key).updateGlBuffer;
49                     });
50             return this;
51         }
52         
53         ///
54         void begin(){
55             _material.begin;
56             _bufferBundle.vao.begin;
57         }
58         
59         ///
60         void end(){
61             _bufferBundle.vao.end;
62             _material.end;
63         }
64         
65         ///
66         BufferBundle bufferBundle(){
67             return _bufferBundle;
68         }
69         
70         ///
71         BufferEntity bufferBundle(BufferBundle bb){
72             _bufferBundle = bb;
73             if(_material && _material.shader) updateShaderAttribs();
74             return this;
75         }
76         
77         ///
78         BufferEntity mesh(Mesh mesh, in BufferUsageFrequency freq, in BufferUsageNature nature){
79             _bufferBundle = new BufferMesh(mesh, freq, nature);
80             if(_material && _material.shader) updateShaderAttribs();
81             return this;
82         }
83         
84         ///
85         Material material(){
86             return _material;
87         }
88         
89         ///
90         BufferEntity material(armos.graphics.Material m){
91             _material = m;
92             return this;
93         }
94         
95         ///
96         BufferEntity shader(Shader shader){
97             if(_material)_material = new DefaultMaterial;
98             _material.shader = shader;
99             if(_bufferBundle) updateShaderAttribs();
100             return this;
101         }
102         
103         void draw(){
104             updateBuffers;
105             updateShaderAttribs;
106             drawWithoutUpdate;
107         }
108 
109         ///
110         void drawWithoutUpdate(){
111             const scopedVao      = scoped(_bufferBundle.vao);
112             const scopedMaterial = scoped(_material);
113             const iboScope       = scoped(_bufferBundle.attrs["index"]);
114 
115             import armos.graphics.renderer;
116             _material.shader.uniform("modelViewMatrix", viewMatrix * modelMatrix);
117             _material.shader.uniform("projectionMatrix", projectionMatrix);
118             _material.shader.uniform("modelViewProjectionMatrix", modelViewProjectionMatrix);
119             _material.shader.uniform("textureMatrix", textureMatrix);
120             _material.shader.enableAttribs();
121                 int elements;
122                 import derelict.opengl3.gl;
123                 glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &elements);
124                 import std.conv;
125                 immutable int size = (elements/GLuint.sizeof).to!int;
126                 glDrawElements(_primitiveMode, size, GL_UNSIGNED_INT, null);
127             _material.shader.disableAttribs();
128         }
129         
130         void draw(in armos.graphics.PolyRenderMode renderMode){
131             import derelict.opengl3.gl;
132             glPolygonMode(GL_FRONT_AND_BACK, renderMode);
133             draw;
134             glPolygonMode(GL_FRONT_AND_BACK, currentStyle.polyRenderMode);
135         }
136         
137         /++
138             entityをワイヤフレームで描画します.
139         +/
140         void drawWireFrame(){
141             draw(armos.graphics.PolyRenderMode.WireFrame);
142         };
143         
144         /++
145             entityの頂点を点で描画します.
146         +/
147         void drawVertices(){
148             draw(armos.graphics.PolyRenderMode.Points);
149         };
150         
151         /++
152             meshの面を塗りつぶして描画します.
153         +/
154         void drawFill(){
155             draw(armos.graphics.PolyRenderMode.Fill);
156         };
157         
158         ///
159         BufferEntity primitiveMode(in armos.graphics.PrimitiveMode mode){
160             _primitiveMode = mode;
161             return this;
162         }
163         
164         ///
165         armos.graphics.PrimitiveMode primitiveMode()const{
166             return _primitiveMode;
167         }
168     }//public
169 
170     private{
171         armos.graphics.BufferBundle _bufferBundle;
172         armos.graphics.Material _material;
173         armos.graphics.PrimitiveMode _primitiveMode = armos.graphics.PrimitiveMode.Triangles;
174     }//private
175 }//class BufferEntity