1 /*
2 -----------------------------------------------------------------------------
3 This source file is part of OGRE
4 (Object-oriented Graphics Rendering Engine)
5 For the latest info, see http://www.ogre3d.org/
6 
7 Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
15 
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18 
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26 -----------------------------------------------------------------------------
27 */
28 
29 #include "OgreStableHeaders.h"
30 #include "OgrePrefabFactory.h"
31 #include "OgreHardwareBufferManager.h"
32 #include "OgreMesh.h"
33 #include "OgreSubMesh.h"
34 
35 namespace Ogre {
36 	//---------------------------------------------------------------------
createPrefab(Mesh * mesh)37 	bool PrefabFactory::createPrefab(Mesh* mesh)
38 	{
39 		const String& resourceName = mesh->getName();
40 
41 		if(resourceName == "Prefab_Plane")
42 		{
43 			createPlane(mesh);
44 			return true;
45 		}
46 		else if(resourceName == "Prefab_Cube")
47 		{
48 			createCube(mesh);
49 			return true;
50 		}
51 		else if(resourceName == "Prefab_Sphere")
52 		{
53 			createSphere(mesh);
54 			return true;
55 		}
56 
57 		return false;
58 	}
59 	//---------------------------------------------------------------------
createPlane(Mesh * mesh)60 	void PrefabFactory::createPlane(Mesh* mesh)
61 	{
62 		SubMesh* sub = mesh->createSubMesh();
63 		float vertices[32] = {
64 			-100, -100, 0,	// pos
65 			0,0,1,			// normal
66 			0,1,			// texcoord
67 			100, -100, 0,
68 			0,0,1,
69 			1,1,
70 			100,  100, 0,
71 			0,0,1,
72 			1,0,
73 			-100,  100, 0 ,
74 			0,0,1,
75 			0,0
76 		};
77 		mesh->sharedVertexData = OGRE_NEW VertexData();
78 		mesh->sharedVertexData->vertexCount = 4;
79 		VertexDeclaration* decl = mesh->sharedVertexData->vertexDeclaration;
80 		VertexBufferBinding* bind = mesh->sharedVertexData->vertexBufferBinding;
81 
82 		size_t offset = 0;
83 		decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
84 		offset += VertexElement::getTypeSize(VET_FLOAT3);
85 		decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
86 		offset += VertexElement::getTypeSize(VET_FLOAT3);
87 		decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
88 		offset += VertexElement::getTypeSize(VET_FLOAT2);
89 
90 		HardwareVertexBufferSharedPtr vbuf =
91 			HardwareBufferManager::getSingleton().createVertexBuffer(
92 			offset, 4, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
93 		bind->setBinding(0, vbuf);
94 
95 		vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
96 
97 		sub->useSharedVertices = true;
98 		HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
99 			createIndexBuffer(
100 			HardwareIndexBuffer::IT_16BIT,
101 			6,
102 			HardwareBuffer::HBU_STATIC_WRITE_ONLY);
103 
104 		unsigned short faces[6] = {0,1,2,
105 			0,2,3 };
106 		sub->indexData->indexBuffer = ibuf;
107 		sub->indexData->indexCount = 6;
108 		sub->indexData->indexStart =0;
109 		ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
110 
111 		mesh->_setBounds(AxisAlignedBox(-100,-100,0,100,100,0), true);
112 		mesh->_setBoundingSphereRadius(Math::Sqrt(100*100+100*100));
113 	}
114 	//---------------------------------------------------------------------
createCube(Mesh * mesh)115 	void PrefabFactory::createCube(Mesh* mesh)
116 	{
117 		SubMesh* sub = mesh->createSubMesh();
118 
119 		const int NUM_VERTICES = 4 * 6; // 4 vertices per side * 6 sides
120 		const int NUM_ENTRIES_PER_VERTEX = 8;
121 		const int NUM_VERTEX_ENTRIES = NUM_VERTICES * NUM_ENTRIES_PER_VERTEX;
122 		const int NUM_INDICES = 3 * 2 * 6; // 3 indices per face * 2 faces per side * 6 sides
123 
124 		const float CUBE_SIZE = 100.0f;
125 		const float CUBE_HALF_SIZE = CUBE_SIZE / 2.0f;
126 
127 		// Create 4 vertices per side instead of 6 that are shared for the whole cube.
128 		// The reason for this is with only 6 vertices the normals will look bad
129 		// since each vertex can "point" in a different direction depending on the face it is included in.
130 		float vertices[NUM_VERTEX_ENTRIES] = {
131 			// front side
132 			-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE,	// pos
133 			0,0,1,	// normal
134 			0,1,	// texcoord
135 			CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE,
136 			0,0,1,
137 			1,1,
138 			CUBE_HALF_SIZE,  CUBE_HALF_SIZE, CUBE_HALF_SIZE,
139 			0,0,1,
140 			1,0,
141 			-CUBE_HALF_SIZE,  CUBE_HALF_SIZE, CUBE_HALF_SIZE ,
142 			0,0,1,
143 			0,0,
144 
145 			// back side
146 			CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
147 			0,0,-1,
148 			0,1,
149 			-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
150 			0,0,-1,
151 			1,1,
152 			-CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
153 			0,0,-1,
154 			1,0,
155 			CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
156 			0,0,-1,
157 			0,0,
158 
159 			// left side
160 			-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
161 			-1,0,0,
162 			0,1,
163 			-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE,
164 			-1,0,0,
165 			1,1,
166 			-CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE,
167 			-1,0,0,
168 			1,0,
169 			-CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
170 			-1,0,0,
171 			0,0,
172 
173 			// right side
174 			CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE,
175 			1,0,0,
176 			0,1,
177 			CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
178 			1,0,0,
179 			1,1,
180 			CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
181 			1,0,0,
182 			1,0,
183 			CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE,
184 			1,0,0,
185 			0,0,
186 
187 			// up side
188 			-CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE,
189 			0,1,0,
190 			0,1,
191 			CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE,
192 			0,1,0,
193 			1,1,
194 			CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
195 			0,1,0,
196 			1,0,
197 			-CUBE_HALF_SIZE, CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
198 			0,1,0,
199 			0,0,
200 
201 			// down side
202 			-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
203 			0,-1,0,
204 			0,1,
205 			CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
206 			0,-1,0,
207 			1,1,
208 			CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE,
209 			0,-1,0,
210 			1,0,
211 			-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, CUBE_HALF_SIZE,
212 			0,-1,0,
213 			0,0
214 		};
215 
216 		mesh->sharedVertexData = OGRE_NEW VertexData();
217 		mesh->sharedVertexData->vertexCount = NUM_VERTICES;
218 		VertexDeclaration* decl = mesh->sharedVertexData->vertexDeclaration;
219 		VertexBufferBinding* bind = mesh->sharedVertexData->vertexBufferBinding;
220 
221 		size_t offset = 0;
222 		decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
223 		offset += VertexElement::getTypeSize(VET_FLOAT3);
224 		decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL);
225 		offset += VertexElement::getTypeSize(VET_FLOAT3);
226 		decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
227 		offset += VertexElement::getTypeSize(VET_FLOAT2);
228 
229 		HardwareVertexBufferSharedPtr vbuf =
230 			HardwareBufferManager::getSingleton().createVertexBuffer(
231 			offset, NUM_VERTICES, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
232 		bind->setBinding(0, vbuf);
233 
234 		vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true);
235 
236 		sub->useSharedVertices = true;
237 		HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().
238 			createIndexBuffer(
239 			HardwareIndexBuffer::IT_16BIT,
240 			NUM_INDICES,
241 			HardwareBuffer::HBU_STATIC_WRITE_ONLY);
242 
243 		unsigned short faces[NUM_INDICES] = {
244 			// front
245 			0,1,2,
246 			0,2,3,
247 
248 			// back
249 			4,5,6,
250 			4,6,7,
251 
252 			// left
253 			8,9,10,
254 			8,10,11,
255 
256 			// right
257 			12,13,14,
258 			12,14,15,
259 
260 			// up
261 			16,17,18,
262 			16,18,19,
263 
264 			// down
265 			20,21,22,
266 			20,22,23
267 		};
268 
269 		sub->indexData->indexBuffer = ibuf;
270 		sub->indexData->indexCount = NUM_INDICES;
271 		sub->indexData->indexStart = 0;
272 		ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true);
273 
274 		mesh->_setBounds(AxisAlignedBox(-CUBE_HALF_SIZE, -CUBE_HALF_SIZE, -CUBE_HALF_SIZE,
275 			CUBE_HALF_SIZE, CUBE_HALF_SIZE, CUBE_HALF_SIZE), true);
276 
277 		mesh->_setBoundingSphereRadius(CUBE_HALF_SIZE);
278 	}
279 	//---------------------------------------------------------------------
createSphere(Mesh * mesh)280 	void PrefabFactory::createSphere(Mesh* mesh)
281 	{
282 		// sphere creation code taken from the DeferredShading sample, originally from the wiki
283 		SubMesh *pSphereVertex = mesh->createSubMesh();
284 
285 		const int NUM_SEGMENTS = 16;
286 		const int NUM_RINGS = 16;
287 		const Real SPHERE_RADIUS = 50.0;
288 
289 		mesh->sharedVertexData = OGRE_NEW VertexData();
290 		VertexData* vertexData = mesh->sharedVertexData;
291 
292 		// define the vertex format
293 		VertexDeclaration* vertexDecl = vertexData->vertexDeclaration;
294 		size_t currOffset = 0;
295 		// positions
296 		vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION);
297 		currOffset += VertexElement::getTypeSize(VET_FLOAT3);
298 		// normals
299 		vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL);
300 		currOffset += VertexElement::getTypeSize(VET_FLOAT3);
301 		// two dimensional texture coordinates
302 		vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
303 
304 		// allocate the vertex buffer
305 		vertexData->vertexCount = (NUM_RINGS + 1) * (NUM_SEGMENTS+1);
306 		HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
307 		VertexBufferBinding* binding = vertexData->vertexBufferBinding;
308 		binding->setBinding(0, vBuf);
309 		float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD));
310 
311 		// allocate index buffer
312 		pSphereVertex->indexData->indexCount = 6 * NUM_RINGS * (NUM_SEGMENTS + 1);
313 		pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
314 		HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer;
315 		unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD));
316 
317 		float fDeltaRingAngle = (Math::PI / NUM_RINGS);
318 		float fDeltaSegAngle = (2 * Math::PI / NUM_SEGMENTS);
319 		unsigned short wVerticeIndex = 0 ;
320 
321 		// Generate the group of rings for the sphere
322 		for( int ring = 0; ring <= NUM_RINGS; ring++ ) {
323 			float r0 = SPHERE_RADIUS * sinf (ring * fDeltaRingAngle);
324 			float y0 = SPHERE_RADIUS * cosf (ring * fDeltaRingAngle);
325 
326 			// Generate the group of segments for the current ring
327 			for(int seg = 0; seg <= NUM_SEGMENTS; seg++) {
328 				float x0 = r0 * sinf(seg * fDeltaSegAngle);
329 				float z0 = r0 * cosf(seg * fDeltaSegAngle);
330 
331 				// Add one vertex to the strip which makes up the sphere
332 				*pVertex++ = x0;
333 				*pVertex++ = y0;
334 				*pVertex++ = z0;
335 
336 				Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy();
337 				*pVertex++ = vNormal.x;
338 				*pVertex++ = vNormal.y;
339 				*pVertex++ = vNormal.z;
340 
341 				*pVertex++ = (float) seg / (float) NUM_SEGMENTS;
342 				*pVertex++ = (float) ring / (float) NUM_RINGS;
343 
344 				if (ring != NUM_RINGS) {
345 					// each vertex (except the last) has six indicies pointing to it
346 					*pIndices++ = wVerticeIndex + NUM_SEGMENTS + 1;
347 					*pIndices++ = wVerticeIndex;
348 					*pIndices++ = wVerticeIndex + NUM_SEGMENTS;
349 					*pIndices++ = wVerticeIndex + NUM_SEGMENTS + 1;
350 					*pIndices++ = wVerticeIndex + 1;
351 					*pIndices++ = wVerticeIndex;
352 					wVerticeIndex ++;
353 				}
354 			}; // end for seg
355 		} // end for ring
356 
357 		// Unlock
358 		vBuf->unlock();
359 		iBuf->unlock();
360 		// Generate face list
361 		pSphereVertex->useSharedVertices = true;
362 
363 		// the original code was missing this line:
364 		mesh->_setBounds( AxisAlignedBox( Vector3(-SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS),
365 			Vector3(SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS) ), false );
366 
367 		mesh->_setBoundingSphereRadius(SPHERE_RADIUS);
368 	}
369 	//---------------------------------------------------------------------
370 }
371