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