1 /***********************************************************************
2     created:    Thu Jan 8 2009
3     author:     Paul D Turner
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2009 Paul D Turner & The CEGUI Development Team
7  *
8  *   Permission is hereby granted, free of charge, to any person obtaining
9  *   a copy of this software and associated documentation files (the
10  *   "Software"), to deal in the Software without restriction, including
11  *   without limitation the rights to use, copy, modify, merge, publish,
12  *   distribute, sublicense, and/or sell copies of the Software, and to
13  *   permit persons to whom the Software is furnished to do so, subject to
14  *   the following conditions:
15  *
16  *   The above copyright notice and this permission notice shall be
17  *   included in all copies or substantial portions of the Software.
18  *
19  *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23  *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24  *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25  *   OTHER DEALINGS IN THE SOFTWARE.
26  ***************************************************************************/
27 #include "CEGUI/RendererModules/OpenGLES/GeometryBuffer.h"
28 #include "CEGUI/RenderEffect.h"
29 #include "CEGUI/RendererModules/OpenGLES/Texture.h"
30 #include "CEGUI/Vertex.h"
31 
32 // Start of CEGUI namespace section
33 namespace CEGUI
34 {
35 //----------------------------------------------------------------------------//
OpenGLESGeometryBuffer()36 OpenGLESGeometryBuffer::OpenGLESGeometryBuffer() :
37     d_activeTexture(0),
38     d_clipRect(0, 0, 0, 0),
39     d_clippingActive(true),
40     d_translation(0, 0, 0),
41     d_rotation(0, 0, 0),
42     d_pivot(0, 0, 0),
43     d_effect(0),
44     d_matrixValid(false)
45 {
46     //d_matrix does not need to be initialised here, we have d_matrixValid
47     //for(unsigned int i = 0; i < 16;++i)
48     //    d_matrix[i]=0.0;
49 }
50 
51 //----------------------------------------------------------------------------//
appendVertex(const Vertex & vertex)52 void OpenGLESGeometryBuffer::appendVertex(const Vertex& vertex)
53 {
54     appendGeometry(&vertex, 1);
55 }
56 
57 //----------------------------------------------------------------------------//
draw() const58 void OpenGLESGeometryBuffer::draw() const
59 {
60     // setup clip region
61     GLint vp[4];
62     glGetIntegerv(GL_VIEWPORT, vp);
63     glScissor(static_cast<GLint>(d_clipRect.left()),
64               static_cast<GLint>(vp[3] - d_clipRect.bottom()),
65               static_cast<GLint>(d_clipRect.getWidth()),
66               static_cast<GLint>(d_clipRect.getHeight()));
67 
68     // apply the transformations we need to use.
69     if (!d_matrixValid)
70         updateMatrix();
71 
72     glMatrixMode(GL_MODELVIEW);
73     glLoadMatrixf(d_matrix);
74 
75     const int pass_count = d_effect ? d_effect->getPassCount() : 1;
76     for (int pass = 0; pass < pass_count; ++pass)
77     {
78         // set up RenderEffect
79         if (d_effect)
80             d_effect->performPreRenderFunctions(pass);
81 
82         // draw the batches
83         size_t pos = 0;
84         BatchList::const_iterator i = d_batches.begin();
85         for ( ; i != d_batches.end(); ++i)
86         {
87             glBindTexture(GL_TEXTURE_2D, (*i).first);
88             // set up pointers to the vertex element arrays
89             glTexCoordPointer(2, GL_FLOAT, sizeof(GLVertex),
90                               &d_vertices[pos]);
91             glColorPointer(4, GL_FLOAT, sizeof(GLVertex),
92                            &d_vertices[pos].colour[0]);
93             glVertexPointer(3, GL_FLOAT, sizeof(GLVertex),
94                             &d_vertices[pos].position[0]);
95             // draw the geometry
96 			glDrawArrays(GL_TRIANGLES, 0, (*i).second);
97             pos += (*i).second;
98         }
99     }
100 
101     // clean up RenderEffect
102     if (d_effect)
103         d_effect->performPostRenderFunctions();
104 }
105 
106 //----------------------------------------------------------------------------//
setTranslation(const Vector3f & v)107 void OpenGLESGeometryBuffer::setTranslation(const Vector3f& v)
108 {
109     d_translation = v;
110     d_matrixValid = false;
111 }
112 
113 //----------------------------------------------------------------------------//
setRotation(const Quaternion & r)114 void OpenGLESGeometryBuffer::setRotation(const Quaternion& r)
115 {
116     d_rotation = r;
117     d_matrixValid = false;
118 }
119 
120 //----------------------------------------------------------------------------//
setPivot(const Vector3f & p)121 void OpenGLESGeometryBuffer::setPivot(const Vector3f& p)
122 {
123     d_pivot = Vector3f(p.d_x, p.d_y, p.d_z);
124     d_matrixValid = false;
125 }
126 
127 //----------------------------------------------------------------------------//
setClippingRegion(const Rectf & region)128 void OpenGLESGeometryBuffer::setClippingRegion(const Rectf& region)
129 {
130     d_clipRect = region;
131 }
132 
133 //----------------------------------------------------------------------------//
appendGeometry(const Vertex * const vbuff,uint vertex_count)134 void OpenGLESGeometryBuffer::appendGeometry(const Vertex* const vbuff,
135     uint vertex_count)
136 {
137     performBatchManagement();
138 
139     // update size of current batch
140     d_batches.back().second += vertex_count;
141 
142     // buffer these vertices
143     GLVertex vd;
144     const Vertex* vs = vbuff;
145     for (uint i = 0; i < vertex_count; ++i, ++vs)
146     {
147         // copy vertex info the buffer, converting from CEGUI::Vertex to
148         // something directly usable by OpenGLES as needed.
149         vd.tex[0]      = vs->tex_coords.d_x;
150         vd.tex[1]      = vs->tex_coords.d_y;
151         vd.colour[0]   = vs->colour_val.getRed();
152         vd.colour[1]   = vs->colour_val.getGreen();
153         vd.colour[2]   = vs->colour_val.getBlue();
154         vd.colour[3]   = vs->colour_val.getAlpha();
155         vd.position[0] = vs->position.d_x;
156         vd.position[1] = vs->position.d_y;
157         vd.position[2] = vs->position.d_z;
158         d_vertices.push_back(vd);
159     }
160 }
161 
162 //----------------------------------------------------------------------------//
setActiveTexture(Texture * texture)163 void OpenGLESGeometryBuffer::setActiveTexture(Texture* texture)
164 {
165     d_activeTexture = static_cast<OpenGLESTexture*>(texture);
166 }
167 
168 //----------------------------------------------------------------------------//
reset()169 void OpenGLESGeometryBuffer::reset()
170 {
171     d_batches.clear();
172     d_vertices.clear();
173     d_activeTexture = 0;
174 }
175 
176 //----------------------------------------------------------------------------//
getActiveTexture() const177 Texture* OpenGLESGeometryBuffer::getActiveTexture() const
178 {
179     return d_activeTexture;
180 }
181 
182 //----------------------------------------------------------------------------//
getVertexCount() const183 uint OpenGLESGeometryBuffer::getVertexCount() const
184 {
185     return d_vertices.size();
186 }
187 
188 //----------------------------------------------------------------------------//
getBatchCount() const189 uint OpenGLESGeometryBuffer::getBatchCount() const
190 {
191     return d_batches.size();
192 }
193 
194 //----------------------------------------------------------------------------//
performBatchManagement()195 void OpenGLESGeometryBuffer::performBatchManagement()
196 {
197     const GLuint gltex = d_activeTexture ?
198                             d_activeTexture->getOpenGLESTexture() : 0;
199 
200     // create a new batch if there are no batches yet, or if the active texture
201     // differs from that used by the current batch.
202     if (d_batches.empty() || (gltex != d_batches.back().first))
203         d_batches.push_back(BatchInfo(gltex, 0));
204 }
205 
206 //----------------------------------------------------------------------------//
setRenderEffect(RenderEffect * effect)207 void OpenGLESGeometryBuffer::setRenderEffect(RenderEffect* effect)
208 {
209     d_effect = effect;
210 }
211 
212 //----------------------------------------------------------------------------//
getRenderEffect()213 RenderEffect* OpenGLESGeometryBuffer::getRenderEffect()
214 {
215     return d_effect;
216 }
217 
218 //----------------------------------------------------------------------------//
getMatrix() const219 const float* OpenGLESGeometryBuffer::getMatrix() const
220 {
221     if (!d_matrixValid)
222         updateMatrix();
223 
224     return d_matrix;
225 }
226 
227 //----------------------------------------------------------------------------//
updateMatrix() const228 void OpenGLESGeometryBuffer::updateMatrix() const
229 {
230     glMatrixMode(GL_MODELVIEW);
231     glPushMatrix();
232 
233     const Vector3f final_trans(d_translation.d_x + d_pivot.d_x,
234                                d_translation.d_y + d_pivot.d_y,
235                                d_translation.d_z + d_pivot.d_z);
236 
237     glLoadIdentity();
238     glTranslatef(final_trans.d_x, final_trans.d_y, final_trans.d_z);
239 
240     float rotation_matrix[16];
241     rotation_matrix[ 0] = 1.0f - 2.0f * (d_rotation.d_y * d_rotation.d_y + d_rotation.d_z * d_rotation.d_z);
242     rotation_matrix[ 1] = 2.0f * (d_rotation.d_x * d_rotation.d_y + d_rotation.d_z * d_rotation.d_w);
243     rotation_matrix[ 2] = 2.0f * (d_rotation.d_x * d_rotation.d_z - d_rotation.d_y * d_rotation.d_w);
244     rotation_matrix[ 3] = 0.0f;
245 
246     rotation_matrix[ 4] = 2.0f * (d_rotation.d_x * d_rotation.d_y - d_rotation.d_z * d_rotation.d_w);
247     rotation_matrix[ 5] = 1.0f - 2.0f * (d_rotation.d_x * d_rotation.d_x + d_rotation.d_z * d_rotation.d_z);
248     rotation_matrix[ 6] = 2.0f * (d_rotation.d_z * d_rotation.d_y + d_rotation.d_x * d_rotation.d_w);
249     rotation_matrix[ 7] = 0.0f;
250 
251     rotation_matrix[ 8] = 2.0f * (d_rotation.d_x * d_rotation.d_z + d_rotation.d_y * d_rotation.d_w);
252     rotation_matrix[ 9] = 2.0f * (d_rotation.d_y * d_rotation.d_z - d_rotation.d_x * d_rotation.d_w);
253     rotation_matrix[10] = 1.0f - 2.0f * (d_rotation.d_x * d_rotation.d_x + d_rotation.d_y * d_rotation.d_y);
254     rotation_matrix[11] = 0.0f;
255 
256     rotation_matrix[12] = 0.0f;
257     rotation_matrix[13] = 0.0f;
258     rotation_matrix[14] = 0.0f;
259     rotation_matrix[15] = 1.0f;
260 
261     glMultMatrixf(rotation_matrix);
262 
263     glTranslatef(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);
264 
265 	glGetFloatv(GL_MODELVIEW_MATRIX, d_matrix);
266     glPopMatrix();
267 
268     d_matrixValid = true;
269 }
270 
271 //----------------------------------------------------------------------------//
setClippingActive(const bool active)272 void OpenGLESGeometryBuffer::setClippingActive(const bool active)
273 {
274     d_clippingActive = active;
275 }
276 
277 //----------------------------------------------------------------------------//
isClippingActive() const278 bool OpenGLESGeometryBuffer::isClippingActive() const
279 {
280     return d_clippingActive;
281 }
282 //----------------------------------------------------------------------------//
283 
284 } // End of  CEGUI namespace section
285