1 /***********************************************************************
2     created:    Mon Feb 9 2009
3     author:     Paul D Turner
4 *************************************************************************/
5 /***************************************************************************
6  *   Copyright (C) 2004 - 2011 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/Direct3D9/GeometryBuffer.h"
28 #include "CEGUI/RendererModules/Direct3D9/Texture.h"
29 #include "CEGUI/RenderEffect.h"
30 #include "CEGUI/Vertex.h"
31 #include <d3d9.h>
32 
33 // Start of CEGUI namespace section
34 namespace CEGUI
35 {
36 //----------------------------------------------------------------------------//
Direct3D9GeometryBuffer(Direct3D9Renderer & owner,LPDIRECT3DDEVICE9 device)37 Direct3D9GeometryBuffer::Direct3D9GeometryBuffer(Direct3D9Renderer& owner,
38                                                  LPDIRECT3DDEVICE9 device) :
39     d_owner(owner),
40     d_activeTexture(0),
41     d_clipRect(0, 0, 0, 0),
42     d_clippingActive(true),
43     d_translation(0, 0, 0),
44     d_rotation(0, 0, 0),
45     d_pivot(0, 0, 0),
46     d_effect(0),
47     d_device(device),
48     d_matrixValid(false)
49 {
50 }
51 
52 //----------------------------------------------------------------------------//
draw() const53 void Direct3D9GeometryBuffer::draw() const
54 {
55     RECT saved_clip;
56     d_device->GetScissorRect(&saved_clip);
57 
58     // setup clip region
59     RECT clip;
60     clip.left   = static_cast<LONG>(d_clipRect.left());
61     clip.top    = static_cast<LONG>(d_clipRect.top());
62     clip.right  = static_cast<LONG>(d_clipRect.right());
63     clip.bottom = static_cast<LONG>(d_clipRect.bottom());
64 
65     // apply the transformations we need to use.
66     if (!d_matrixValid)
67         updateMatrix();
68 
69     d_device->SetTransform(D3DTS_WORLD, &d_matrix);
70 
71     d_owner.setupRenderingBlendMode(d_blendMode);
72 
73     const int pass_count = d_effect ? d_effect->getPassCount() : 1;
74     for (int pass = 0; pass < pass_count; ++pass)
75     {
76         // set up RenderEffect
77         if (d_effect)
78             d_effect->performPreRenderFunctions(pass);
79 
80         // draw the batches
81         size_t pos = 0;
82         BatchList::const_iterator i = d_batches.begin();
83         for ( ; i != d_batches.end(); ++i)
84         {
85             if (i->clip)
86                 d_device->SetScissorRect(&clip);
87 
88             d_device->SetTexture(0, i->texture);
89             d_device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, i->vertexCount / 3,
90                                     &d_vertices[pos], sizeof(D3DVertex));
91             pos += i->vertexCount;
92 
93             if (i->clip)
94                 d_device->SetScissorRect(&saved_clip);
95         }
96     }
97 
98     // clean up RenderEffect
99     if (d_effect)
100         d_effect->performPostRenderFunctions();
101 }
102 
103 //----------------------------------------------------------------------------//
setTranslation(const Vector3f & t)104 void Direct3D9GeometryBuffer::setTranslation(const Vector3f& t)
105 {
106     d_translation = t;
107     d_matrixValid = false;
108 }
109 
110 //----------------------------------------------------------------------------//
setRotation(const Quaternion & r)111 void Direct3D9GeometryBuffer::setRotation(const Quaternion& r)
112 {
113     d_rotation = r;
114     d_matrixValid = false;
115 }
116 
117 //----------------------------------------------------------------------------//
setPivot(const Vector3f & p)118 void Direct3D9GeometryBuffer::setPivot(const Vector3f& p)
119 {
120     d_pivot = p;
121     d_matrixValid = false;
122 }
123 
124 //----------------------------------------------------------------------------//
setClippingRegion(const Rectf & region)125 void Direct3D9GeometryBuffer::setClippingRegion(const Rectf& region)
126 {
127     d_clipRect.top(ceguimax(0.0f, region.top()));
128     d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
129     d_clipRect.left(ceguimax(0.0f, region.left()));
130     d_clipRect.right(ceguimax(0.0f, region.right()));
131 }
132 
133 //----------------------------------------------------------------------------//
appendVertex(const Vertex & vertex)134 void Direct3D9GeometryBuffer::appendVertex(const Vertex& vertex)
135 {
136     appendGeometry(&vertex, 1);
137 }
138 
139 //----------------------------------------------------------------------------//
appendGeometry(const Vertex * const vbuff,uint vertex_count)140 void Direct3D9GeometryBuffer::appendGeometry(const Vertex* const vbuff,
141                                              uint vertex_count)
142 {
143     performBatchManagement();
144 
145     // update size of current batch
146     d_batches.back().vertexCount += vertex_count;
147 
148     // buffer these vertices
149     D3DVertex vd;
150     const Vertex* vs = vbuff;
151     for (uint i = 0; i < vertex_count; ++i, ++vs)
152     {
153         // copy vertex info the buffer, converting from CEGUI::Vertex to
154         // something directly usable by D3D as needed.
155         vd.x       = vs->position.d_x - 0.5f;
156         vd.y       = vs->position.d_y - 0.5f;
157         vd.z       = vs->position.d_z;
158         vd.diffuse = vs->colour_val.getARGB();
159         vd.tu      = vs->tex_coords.d_x;
160         vd.tv      = vs->tex_coords.d_y;
161         d_vertices.push_back(vd);
162     }
163 }
164 
165 //----------------------------------------------------------------------------//
setActiveTexture(Texture * texture)166 void Direct3D9GeometryBuffer::setActiveTexture(Texture* texture)
167 {
168     d_activeTexture = static_cast<Direct3D9Texture*>(texture);
169 }
170 
171 //----------------------------------------------------------------------------//
reset()172 void Direct3D9GeometryBuffer::reset()
173 {
174     d_batches.clear();
175     d_vertices.clear();
176     d_activeTexture = 0;
177 }
178 
179 //----------------------------------------------------------------------------//
getActiveTexture() const180 Texture* Direct3D9GeometryBuffer::getActiveTexture() const
181 {
182     return d_activeTexture;
183 }
184 
185 //----------------------------------------------------------------------------//
getVertexCount() const186 uint Direct3D9GeometryBuffer::getVertexCount() const
187 {
188     return d_vertices.size();
189 }
190 
191 //----------------------------------------------------------------------------//
getBatchCount() const192 uint Direct3D9GeometryBuffer::getBatchCount() const
193 {
194     return d_batches.size();
195 }
196 
197 //----------------------------------------------------------------------------//
setRenderEffect(RenderEffect * effect)198 void Direct3D9GeometryBuffer::setRenderEffect(RenderEffect* effect)
199 {
200     d_effect = effect;
201 }
202 
203 //----------------------------------------------------------------------------//
getRenderEffect()204 RenderEffect* Direct3D9GeometryBuffer::getRenderEffect()
205 {
206     return d_effect;
207 }
208 
209 //----------------------------------------------------------------------------//
performBatchManagement()210 void Direct3D9GeometryBuffer::performBatchManagement()
211 {
212     const LPDIRECT3DTEXTURE9 t = d_activeTexture ?
213                                  d_activeTexture->getDirect3D9Texture() : 0;
214 
215     // create a new batch if there are no batches yet, or if the active texture
216     // differs from that used by the current batch.
217     if (d_batches.empty() ||
218         t != d_batches.back().texture ||
219         d_clippingActive != d_batches.back().clip)
220     {
221         BatchInfo batch = {t, 0, d_clippingActive};
222         d_batches.push_back(batch);
223     }
224 }
225 
226 //----------------------------------------------------------------------------//
updateMatrix() const227 void Direct3D9GeometryBuffer::updateMatrix() const
228 {
229     const D3DXVECTOR3 p(d_pivot.d_x, d_pivot.d_y, d_pivot.d_z);
230     const D3DXVECTOR3 t(d_translation.d_x, d_translation.d_y, d_translation.d_z);
231 
232     D3DXQUATERNION r;
233     r.x = d_rotation.d_x;
234     r.y = d_rotation.d_y;
235     r.z = d_rotation.d_z;
236     r.w = d_rotation.d_w;
237 
238     D3DXMatrixTransformation(&d_matrix, 0, 0, 0, &p, &r, &t);
239 
240     d_matrixValid = true;
241 }
242 
243 //----------------------------------------------------------------------------//
getMatrix() const244 const D3DXMATRIX* Direct3D9GeometryBuffer::getMatrix() const
245 {
246     if (!d_matrixValid)
247         updateMatrix();
248 
249     return &d_matrix;
250 }
251 
252 //----------------------------------------------------------------------------//
setClippingActive(const bool active)253 void Direct3D9GeometryBuffer::setClippingActive(const bool active)
254 {
255     d_clippingActive = active;
256 }
257 
258 //----------------------------------------------------------------------------//
isClippingActive() const259 bool Direct3D9GeometryBuffer::isClippingActive() const
260 {
261     return d_clippingActive;
262 }
263 
264 //----------------------------------------------------------------------------//
265 
266 } // End of  CEGUI namespace section
267