00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "CaelumPrecompiled.h"
00022 #include "GeometryFactory.h"
00023
00024 namespace Caelum {
00025
00026 void GeometryFactory::generateSphericDome (const Ogre::String &name, int segments, DomeType type) {
00027
00028 if (Ogre::MeshManager::getSingleton ().resourceExists (name)) {
00029 return;
00030 }
00031
00032 Ogre::LogManager::getSingleton ().logMessage (
00033 "Caelum: Creating " + name + " sphere mesh resource...");
00034
00035
00036 Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton ().createManual (name, RESOURCE_GROUP_NAME);
00037
00038 Ogre::SubMesh *sub = msh->createSubMesh ();
00039
00040
00041 Ogre::VertexData *vertexData = new Ogre::VertexData ();
00042 msh->sharedVertexData = vertexData;
00043
00044
00045 Ogre::VertexDeclaration *vertexDecl = vertexData->vertexDeclaration;
00046 size_t currOffset = 0;
00047
00048 vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION);
00049 currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT3);
00050
00051 vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL);
00052 currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT3);
00053
00054 vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0);
00055 currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT2);
00056
00057
00058 switch (type) {
00059 case DT_GRADIENTS:
00060 vertexData->vertexCount = segments * (segments - 1) + 2;
00061 break;
00062 case DT_STARFIELD:
00063 vertexData->vertexCount = (segments + 1) * (segments + 1);
00064 break;
00065 };
00066 Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton ().createVertexBuffer (vertexDecl->getVertexSize (0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
00067 Ogre::VertexBufferBinding *binding = vertexData->vertexBufferBinding;
00068 binding->setBinding (0, vBuf);
00069
00070 float *pVertex = static_cast<float *>(vBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD));
00071
00072
00073 switch (type) {
00074 case DT_GRADIENTS:
00075 sub->indexData->indexCount = 2 * segments * (segments - 1) * 3;
00076 break;
00077 case DT_STARFIELD:
00078 sub->indexData->indexCount = 2 * (segments - 1) * segments * 3;
00079 break;
00080 };
00081 sub->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton ().createIndexBuffer (Ogre::HardwareIndexBuffer::IT_16BIT, sub->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
00082 Ogre::HardwareIndexBufferSharedPtr iBuf = sub->indexData->indexBuffer;
00083 unsigned short *pIndices = static_cast<unsigned short *>(iBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD));
00084
00085
00086 switch (type) {
00087 case DT_GRADIENTS:
00088 fillGradientsDomeBuffers (pVertex, pIndices, segments);
00089 break;
00090 case DT_STARFIELD:
00091 fillStarfieldDomeBuffers (pVertex, pIndices, segments);
00092 break;
00093 };
00094
00095
00096 vBuf->unlock ();
00097
00098
00099 iBuf->unlock ();
00100
00101
00102 sub->useSharedVertices = true;
00103 msh->_setBounds (Ogre::AxisAlignedBox (-1, -1, -1, 1, 1, 1), false);
00104 msh->_setBoundingSphereRadius (1);
00105 msh->load ();
00106
00107 Ogre::LogManager::getSingleton ().logMessage (
00108 "Caelum: generateSphericDome DONE");
00109 }
00110
00111 void GeometryFactory::fillGradientsDomeBuffers (float *pVertex, unsigned short *pIndices, int segments) {
00112 const float deltaLatitude = Ogre::Math::PI / (float )segments;
00113 const float deltaLongitude = Ogre::Math::PI * 2.0 / (float )segments;
00114
00115
00116 for (int i = 1; i < segments; i++) {
00117 float r0 = Ogre::Math::Sin (Ogre::Radian (i * deltaLatitude));
00118 float y0 = Ogre::Math::Cos (Ogre::Radian (i * deltaLatitude));
00119
00120 for (int j = 0; j < segments; j++) {
00121 float x0 = r0 * Ogre::Math::Sin (Ogre::Radian (j * deltaLongitude));
00122 float z0 = r0 * Ogre::Math::Cos (Ogre::Radian (j * deltaLongitude));
00123
00124 *pVertex++ = x0;
00125 *pVertex++ = y0;
00126 *pVertex++ = z0;
00127
00128 *pVertex++ = -x0;
00129 *pVertex++ = -y0;
00130 *pVertex++ = -z0;
00131
00132 *pVertex++ = 0;
00133 *pVertex++ = 1 - y0;
00134 }
00135 }
00136
00137
00138 *pVertex++ = 0;
00139 *pVertex++ = 1;
00140 *pVertex++ = 0;
00141 *pVertex++ = 0;
00142 *pVertex++ = -1;
00143 *pVertex++ = 0;
00144 *pVertex++ = 0;
00145 *pVertex++ = 0;
00146
00147
00148 *pVertex++ = 0;
00149 *pVertex++ = -1;
00150 *pVertex++ = 0;
00151 *pVertex++ = 0;
00152 *pVertex++ = 1;
00153 *pVertex++ = 0;
00154 *pVertex++ = 0;
00155 *pVertex++ = 2;
00156
00157
00158 for (int i = 0; i < segments - 2; i++) {
00159 for (int j = 0; j < segments; j++) {
00160 *pIndices++ = segments * i + j;
00161 *pIndices++ = segments * i + (j + 1) % segments;
00162 *pIndices++ = segments * (i + 1) + (j + 1) % segments;
00163 *pIndices++ = segments * i + j;
00164 *pIndices++ = segments * (i + 1) + (j + 1) % segments;
00165 *pIndices++ = segments * (i + 1) + j;
00166 }
00167 }
00168
00169
00170 for (int i = 0; i < segments; i++) {
00171 *pIndices++ = segments * (segments - 1);
00172 *pIndices++ = (i + 1) % segments;
00173 *pIndices++ = i;
00174 }
00175
00176
00177 for (int i = 0; i < segments; i++) {
00178 *pIndices++ = segments * (segments - 1) + 1;
00179 *pIndices++ = segments * (segments - 2) + i;
00180 *pIndices++ = segments * (segments - 2) + (i + 1) % segments;
00181 }
00182 }
00183
00184 void GeometryFactory::fillStarfieldDomeBuffers (float *pVertex, unsigned short *pIndices, int segments) {
00185 const float deltaLatitude = Ogre::Math::PI / (float )segments;
00186 const float deltaLongitude = Ogre::Math::PI * 2.0 / (float )segments;
00187
00188
00189 for (int i = 0; i <= segments; i++) {
00190 float r0 = Ogre::Math::Sin (Ogre::Radian (i * deltaLatitude));
00191 float y0 = Ogre::Math::Cos (Ogre::Radian (i * deltaLatitude));
00192
00193 for (int j = 0; j <= segments; j++) {
00194 float x0 = r0 * Ogre::Math::Sin (Ogre::Radian (j * deltaLongitude));
00195 float z0 = r0 * Ogre::Math::Cos (Ogre::Radian (j * deltaLongitude));
00196
00197 *pVertex++ = x0;
00198 *pVertex++ = y0;
00199 *pVertex++ = z0;
00200
00201 *pVertex++ = -x0;
00202 *pVertex++ = -y0;
00203 *pVertex++ = -z0;
00204
00205 *pVertex++ = (float )j / (float )segments;
00206 *pVertex++ = 1 - (y0 * 0.5 + 0.5);
00207 }
00208 }
00209
00210
00211 int vRowSize = segments + 1;
00212 for (int i = 1; i < segments; i++) {
00213 for (int j = 0; j < segments; j++) {
00214 int baseIdx = vRowSize * i + j;
00215 *pIndices++ = baseIdx;
00216 *pIndices++ = baseIdx + 1;
00217 *pIndices++ = baseIdx + vRowSize + 1;
00218 *pIndices++ = baseIdx + 1;
00219 *pIndices++ = baseIdx;
00220 *pIndices++ = baseIdx - vRowSize;
00221 }
00222 }
00223 }
00224 }