1 #include "pch.h"
2 #include "DynamicLines.h"
3
4 #include <OgreHardwareVertexBuffer.h>
5 #include <OgreHardwareBufferManager.h>
6 #include <OgreCamera.h>
7
8 #include <cassert>
9 #include <cmath>
10
11 using namespace Ogre;
12
13
14 // DynamicRenderable
15 //=============================================================================================
16
DynamicRenderable()17 DynamicRenderable::DynamicRenderable() :
18 mVertexBufferCapacity(0), mIndexBufferCapacity(0)
19 {
20 }
~DynamicRenderable()21 DynamicRenderable::~DynamicRenderable()
22 {
23 delete mRenderOp.vertexData;
24 delete mRenderOp.indexData;
25 }
26
27 //------------------------------------------------------------------------------------------------
initialize(RenderOperation::OperationType operationType,bool useIndices)28 void DynamicRenderable::initialize(RenderOperation::OperationType operationType, bool useIndices)
29 {
30 // Initialize render operation
31 mRenderOp.operationType = operationType;
32 mRenderOp.useIndexes = useIndices;
33 mRenderOp.vertexData = new VertexData;
34 if (mRenderOp.useIndexes)
35 mRenderOp.indexData = new IndexData;
36
37 // Reset buffer capacities
38 mVertexBufferCapacity = 0;
39 mIndexBufferCapacity = 0;
40
41 // Create vertex declaration
42 createVertexDeclaration();
43 }
44
45 //------------------------------------------------------------------------------------------------
prepareHardwareBuffers(size_t vertexCount,size_t indexCount)46 void DynamicRenderable::prepareHardwareBuffers(size_t vertexCount, size_t indexCount)
47 {
48 // Prepare vertex buffer
49 size_t newVertCapacity = mVertexBufferCapacity;
50 if ((vertexCount > mVertexBufferCapacity) ||
51 (!mVertexBufferCapacity))
52 {
53 // vertexCount exceeds current capacity!
54 // It is necessary to reallocate the buffer.
55
56 // Check if this is the first call
57 if (!newVertCapacity)
58 newVertCapacity = 1;
59
60 // Make capacity the next power of two
61 while (newVertCapacity < vertexCount)
62 newVertCapacity <<= 1;
63 }else
64 if (vertexCount < mVertexBufferCapacity>>1) {
65 // Make capacity the previous power of two
66 while (vertexCount < newVertCapacity>>1)
67 newVertCapacity >>= 1; }
68
69 if (newVertCapacity != mVertexBufferCapacity)
70 {
71 mVertexBufferCapacity = newVertCapacity;
72 // Create new vertex buffer
73 HardwareVertexBufferSharedPtr vbuf =
74 HardwareBufferManager::getSingleton().createVertexBuffer(
75 mRenderOp.vertexData->vertexDeclaration->getVertexSize(0)*2,
76 mVertexBufferCapacity,
77 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?
78
79 // Bind buffer
80 mRenderOp.vertexData->vertexBufferBinding->setBinding(0, vbuf);
81 }
82
83 // Update vertex count in the render operation
84 mRenderOp.vertexData->vertexCount = vertexCount;
85
86 if (mRenderOp.useIndexes)
87 {
88 OgreAssert(indexCount <= std::numeric_limits<unsigned short>::max(), "indexCount exceeds 16 bit");
89
90 size_t newIndexCapacity = mIndexBufferCapacity;
91 // Prepare index buffer
92 if ((indexCount > newIndexCapacity) ||
93 (!newIndexCapacity))
94 {
95 // indexCount exceeds current capacity!
96 // It is necessary to reallocate the buffer.
97
98 // Check if this is the first call
99 if (!newIndexCapacity)
100 newIndexCapacity = 1;
101
102 // Make capacity the next power of two
103 while (newIndexCapacity < indexCount)
104 newIndexCapacity <<= 1;
105
106 }
107 else if (indexCount < newIndexCapacity>>1)
108 {
109 // Make capacity the previous power of two
110 while (indexCount < newIndexCapacity>>1)
111 newIndexCapacity >>= 1;
112 }
113
114 if (newIndexCapacity != mIndexBufferCapacity)
115 {
116 mIndexBufferCapacity = newIndexCapacity;
117 // Create new index buffer
118 mRenderOp.indexData->indexBuffer =
119 HardwareBufferManager::getSingleton().createIndexBuffer(
120 HardwareIndexBuffer::IT_16BIT, mIndexBufferCapacity,
121 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); // TODO: Custom HBU_?
122 }
123
124 // Update index count in the render operation
125 mRenderOp.indexData->indexCount = indexCount;
126 }
127 }
128 //------------------------------------------------------------------------------------------------
129
getBoundingRadius(void) const130 Real DynamicRenderable::getBoundingRadius(void) const
131 {
132 return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength()));
133 }
134
getSquaredViewDepth(const Camera * cam) const135 Real DynamicRenderable::getSquaredViewDepth(const Camera* cam) const
136 {
137 Vector3 vMin, vMax, vMid, vDist;
138 vMin = mBox.getMinimum();
139 vMax = mBox.getMaximum();
140 vMid = ((vMax - vMin) * 0.5) + vMin;
141 vDist = cam->getDerivedPosition() - vMid;
142
143 return vDist.squaredLength();
144 }
145
146
147 // DynamicRenderable
148 //=============================================================================================
149
DynamicLines(RenderOperation::OperationType opType)150 DynamicLines::DynamicLines(RenderOperation::OperationType opType)
151 {
152 initialize(opType, false);
153 mDirty = true;
154
155 iBufferSize = 2;
156 prepareHardwareBuffers(iBufferSize, 0);
157
158 // Temp fix to remove clipping
159 Vector3 vaabMin = Vector3(-1000, -1000, -1000);
160 Vector3 vaabMax = Vector3(1000, 1000, 1000);
161 mBox.setExtents(vaabMin, vaabMax);
162 }
163
~DynamicLines()164 DynamicLines::~DynamicLines()
165 {
166 }
167
setOperationType(RenderOperation::OperationType opType)168 void DynamicLines::setOperationType(RenderOperation::OperationType opType)
169 {
170 mRenderOp.operationType = opType;
171 }
172
getOperationType() const173 RenderOperation::OperationType DynamicLines::getOperationType() const
174 {
175 return mRenderOp.operationType;
176 }
177
178 //---------------------------------------------------
addLine(const Vector3 & vectStart,const Vector3 & vectEnd,const ColourValue & colStart,const ColourValue & colEnd)179 void DynamicLines::addLine(const Vector3 &vectStart, const Vector3 &vectEnd, const ColourValue &colStart, const ColourValue &colEnd)
180 {
181 mPoints.push_back(vectStart);
182 mPoints.push_back(vectEnd);
183 mColors.push_back(colStart);
184 mColors.push_back(colEnd);
185 mDirty = true;
186 }
187
addLine(const Vector3 & vectStart,const Vector3 & vectEnd,const ColourValue & col)188 void DynamicLines::addLine(const Vector3 &vectStart, const Vector3 &vectEnd, const ColourValue &col)
189 {
190 mPoints.push_back(vectStart);
191 mPoints.push_back(vectEnd);
192 mColors.push_back(col);
193 mColors.push_back(col);
194 mDirty = true;
195 }
196
197
clear()198 void DynamicLines::clear()
199 {
200 mPoints.clear();
201 mColors.clear();
202 mDirty = true;
203 }
204
update()205 void DynamicLines::update()
206 {
207 if(mDirty)
208 fillHardwareBuffers();
209 }
210
211
createVertexDeclaration()212 void DynamicLines::createVertexDeclaration()
213 {
214 VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration;
215 decl->addElement(0, 0, VET_FLOAT3, VES_POSITION);
216 decl->addElement(0, Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), VET_COLOUR, VES_DIFFUSE);
217 }
218
fillHardwareBuffers()219 void DynamicLines::fillHardwareBuffers()
220 {
221 int size = mPoints.size();
222
223 // Double buffer size if we have reach the maximum size
224 if(iBufferSize < size)
225 {
226 iBufferSize = size * 2;
227 prepareHardwareBuffers(iBufferSize, 0);
228 }
229
230 unsigned char *pVert;
231 float *pFloat;
232 Ogre::ARGB *pCol;
233
234 HardwareVertexBufferSharedPtr vbuf =
235 mRenderOp.vertexData->vertexBufferBinding->getBuffer(0);
236
237 pVert = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD));
238
239 Ogre::VertexDeclaration::VertexElementList elems = mRenderOp.vertexData->vertexDeclaration->findElementsBySource(0);
240 Ogre::VertexDeclaration::VertexElementList::const_iterator elemItr = elems.begin(), elemEnd = elems.end();
241
242 for(int i = 0; i < iBufferSize/*size*/; ++i)
243 {
244 for (elemItr = elems.begin(); elemItr != elemEnd; ++elemItr)
245 {
246 const Ogre::VertexElement& elem = *elemItr;
247 switch (elem.getSemantic())
248 {
249 case Ogre::VES_POSITION:
250 elem.baseVertexPointerToElement(pVert, &pFloat);
251 if(i < size)
252 {
253 *pFloat++ = mPoints[i].x;
254 *pFloat++ = mPoints[i].y;
255 *pFloat++ = mPoints[i].z;
256 } else
257 {
258 *pFloat++ = 0.0f;
259 *pFloat++ = 0.0f;
260 *pFloat++ = 0.0f;
261 }
262 break;
263 case Ogre::VES_DIFFUSE:
264 elem.baseVertexPointerToElement(pVert, &pCol);
265 {
266 if(i < size)
267 *pCol++ = Ogre::VertexElement::convertColourValue(Ogre::ColourValue(mColors[i].r, mColors[i].g, mColors[i].b, mColors[i].a), Ogre::VET_COLOUR_ARGB);
268 else
269 *pCol++ = Ogre::VertexElement::convertColourValue(Ogre::ColourValue(0.0, 0.0, 0.0, 0.0), Ogre::VET_COLOUR_ARGB);
270 }
271 break;
272 }
273 }
274 pVert += vbuf->getVertexSize();
275 }
276 vbuf->unlock();
277 mDirty = false;
278 clear();
279 }
280