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