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